From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751782AbdA0VrW (ORCPT ); Fri, 27 Jan 2017 16:47:22 -0500 Received: from mail.free-electrons.com ([62.4.15.54]:38392 "EHLO mail.free-electrons.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751220AbdA0Vqu (ORCPT ); Fri, 27 Jan 2017 16:46:50 -0500 From: Maxime Ripard To: Chen-Yu Tsai , Maxime Ripard , Ulf Hansson Cc: Rob Herring , devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-mmc@vger.kernel.org, Andre Przywara Subject: [PATCH v5 1/13] mmc: sunxi: Fix clock frequency change sequence Date: Fri, 27 Jan 2017 22:38:33 +0100 Message-Id: <7a6cea2cb855613fd7fb3d029e92be00c34b252d.1485553113.git-series.maxime.ripard@free-electrons.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: References: In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The SD specification documents that the clock frequency should only be changed once gated (Section 3.2.3 - SD Clock Frequency Change Sequence). The current code first modifies the parent clock, gates it and then modifies the internal divider. This means that since the parent clock rate might be changed, the bus clock might be changed as well before it is gated, which breaks the specification. Move the gating before the parent rate modification. Signed-off-by: Maxime Ripard Tested-by: Florian Vaussard --- drivers/mmc/host/sunxi-mmc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c index b1d1303389a7..ab4324e6eb74 100644 --- a/drivers/mmc/host/sunxi-mmc.c +++ b/drivers/mmc/host/sunxi-mmc.c @@ -761,6 +761,10 @@ static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host, u32 rval, clock = ios->clock; int ret; + ret = sunxi_mmc_oclk_onoff(host, 0); + if (ret) + return ret; + /* 8 bit DDR requires a higher module clock */ if (ios->timing == MMC_TIMING_MMC_DDR52 && ios->bus_width == MMC_BUS_WIDTH_8) @@ -783,10 +787,6 @@ static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host, return ret; } - ret = sunxi_mmc_oclk_onoff(host, 0); - if (ret) - return ret; - /* clear internal divider */ rval = mmc_readl(host, REG_CLKCR); rval &= ~0xff; -- git-series 0.8.11 From mboxrd@z Thu Jan 1 00:00:00 1970 From: Maxime Ripard Subject: [PATCH v5 1/13] mmc: sunxi: Fix clock frequency change sequence Date: Fri, 27 Jan 2017 22:38:33 +0100 Message-ID: <7a6cea2cb855613fd7fb3d029e92be00c34b252d.1485553113.git-series.maxime.ripard@free-electrons.com> References: Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: In-Reply-To: References: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org To: Chen-Yu Tsai , Maxime Ripard , Ulf Hansson Cc: devicetree@vger.kernel.org, Andre Przywara , linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, Rob Herring , linux-arm-kernel@lists.infradead.org List-Id: devicetree@vger.kernel.org The SD specification documents that the clock frequency should only be changed once gated (Section 3.2.3 - SD Clock Frequency Change Sequence). The current code first modifies the parent clock, gates it and then modifies the internal divider. This means that since the parent clock rate might be changed, the bus clock might be changed as well before it is gated, which breaks the specification. Move the gating before the parent rate modification. Signed-off-by: Maxime Ripard Tested-by: Florian Vaussard --- drivers/mmc/host/sunxi-mmc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c index b1d1303389a7..ab4324e6eb74 100644 --- a/drivers/mmc/host/sunxi-mmc.c +++ b/drivers/mmc/host/sunxi-mmc.c @@ -761,6 +761,10 @@ static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host, u32 rval, clock = ios->clock; int ret; + ret = sunxi_mmc_oclk_onoff(host, 0); + if (ret) + return ret; + /* 8 bit DDR requires a higher module clock */ if (ios->timing == MMC_TIMING_MMC_DDR52 && ios->bus_width == MMC_BUS_WIDTH_8) @@ -783,10 +787,6 @@ static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host, return ret; } - ret = sunxi_mmc_oclk_onoff(host, 0); - if (ret) - return ret; - /* clear internal divider */ rval = mmc_readl(host, REG_CLKCR); rval &= ~0xff; -- git-series 0.8.11 From mboxrd@z Thu Jan 1 00:00:00 1970 From: maxime.ripard@free-electrons.com (Maxime Ripard) Date: Fri, 27 Jan 2017 22:38:33 +0100 Subject: [PATCH v5 1/13] mmc: sunxi: Fix clock frequency change sequence In-Reply-To: References: Message-ID: <7a6cea2cb855613fd7fb3d029e92be00c34b252d.1485553113.git-series.maxime.ripard@free-electrons.com> To: linux-arm-kernel@lists.infradead.org List-Id: linux-arm-kernel.lists.infradead.org The SD specification documents that the clock frequency should only be changed once gated (Section 3.2.3 - SD Clock Frequency Change Sequence). The current code first modifies the parent clock, gates it and then modifies the internal divider. This means that since the parent clock rate might be changed, the bus clock might be changed as well before it is gated, which breaks the specification. Move the gating before the parent rate modification. Signed-off-by: Maxime Ripard Tested-by: Florian Vaussard --- drivers/mmc/host/sunxi-mmc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c index b1d1303389a7..ab4324e6eb74 100644 --- a/drivers/mmc/host/sunxi-mmc.c +++ b/drivers/mmc/host/sunxi-mmc.c @@ -761,6 +761,10 @@ static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host, u32 rval, clock = ios->clock; int ret; + ret = sunxi_mmc_oclk_onoff(host, 0); + if (ret) + return ret; + /* 8 bit DDR requires a higher module clock */ if (ios->timing == MMC_TIMING_MMC_DDR52 && ios->bus_width == MMC_BUS_WIDTH_8) @@ -783,10 +787,6 @@ static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host, return ret; } - ret = sunxi_mmc_oclk_onoff(host, 0); - if (ret) - return ret; - /* clear internal divider */ rval = mmc_readl(host, REG_CLKCR); rval &= ~0xff; -- git-series 0.8.11