From patchwork Fri Aug 4 17:43:47 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Brunet X-Patchwork-Id: 9881821 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 90184602B8 for ; Fri, 4 Aug 2017 17:46:09 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7D9942891B for ; Fri, 4 Aug 2017 17:46:09 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7280328930; Fri, 4 Aug 2017 17:46:09 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.3 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM, T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 66D292891B for ; Fri, 4 Aug 2017 17:46:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753200AbdHDRoR (ORCPT ); Fri, 4 Aug 2017 13:44:17 -0400 Received: from mail-wm0-f42.google.com ([74.125.82.42]:36007 "EHLO mail-wm0-f42.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753184AbdHDRoM (ORCPT ); Fri, 4 Aug 2017 13:44:12 -0400 Received: by mail-wm0-f42.google.com with SMTP id t201so25292771wmt.1 for ; Fri, 04 Aug 2017 10:44:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=uTYHLU5iY9QtbsQMz4remriT2S7R6YDD5LjCd16hSME=; b=fRnYPDw3Yv8Y6f5KjrwM1ANAKh/63lP5QvtImNxTtMxdpTm/y5EZARKdptM3lTSt75 vXd1rrWuAA9mhWBgmh137Vjw23BrYcmeMYIHlKAQ+kBodGaUh7etq/D5HsdJv9Q+Irmx rdV2GKAsq7/uew0iRXv1kELWiJlH5fT9ykCYaeHySu9ShtwYxjMS2JwHNuD/4RYFh0PS DhomUqyx7wmz57DOly7k+pk935F5O2MhKYlCawvjk3UGA1V0r1Hp6KMux1ZV4sUNsGot WNvOHTlye36MaEyKxagQNz0+B502tMKyhnwvCRecHduwKEzD4SaHzoGDdN3/3385GAN4 CrAA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=uTYHLU5iY9QtbsQMz4remriT2S7R6YDD5LjCd16hSME=; b=aMKy8a9gmotv61lwhDLc5/o4aCyTomVkvmFXgbXbE6GiKvBdByyNNpkfV0luV0sm++ 88gJB3oCCFt/KaUmXisKDhRIAzd1R0cUBT0q97dXyO8MHClrF6uTE/XAHboClRiXeai/ 2W4XJNqoblLXWkrBqI3RDuLRLkugvvSR3aQWYZjXhErJVrfEi9Yi/Pn/nEHlgJ3n6hFx soF3eXiG0CdMwPJ0pLcyHPXsHj7IKtuFBh2glQ5XBGJHRxIKT9+Fvw/JH8ocVCQ12GxT zypEhcqtdx+J6enfgt/SAIQK2P93C87qBbyReBYJdFW9WRSRg4CnCqtYn3e2MVCglkKA zR+Q== X-Gm-Message-State: AHYfb5j9RXxWJiVzoKRfL/vV+WEq0d13DD6igsK2Ft0N069XoB6ZNpO0 R0hGKGEmf6bacm0h X-Received: by 10.28.109.146 with SMTP id b18mr1787006wmi.34.1501868651343; Fri, 04 Aug 2017 10:44:11 -0700 (PDT) Received: from localhost.localdomain (cag06-3-82-243-161-21.fbx.proxad.net. [82.243.161.21]) by smtp.googlemail.com with ESMTPSA id p17sm996082wma.45.2017.08.04.10.44.10 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 04 Aug 2017 10:44:10 -0700 (PDT) From: Jerome Brunet To: Ulf Hansson , Kevin Hilman , Carlo Caione Cc: Jerome Brunet , linux-mmc@vger.kernel.org, linux-amlogic@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH 08/14] mmc: meson-gx: rework clock init function Date: Fri, 4 Aug 2017 19:43:47 +0200 Message-Id: <20170804174353.16486-9-jbrunet@baylibre.com> X-Mailer: git-send-email 2.9.4 In-Reply-To: <20170804174353.16486-1-jbrunet@baylibre.com> References: <20170804174353.16486-1-jbrunet@baylibre.com> Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Perform basic initialisation of the clk register before providing it to the CCF. Thanks to devm, carrying the clock structure around after init is not necessary. Rework the function to remove these from the controller host data. Finally, set initial mmc clock rate before enabling it, simplifying the exit condition. Signed-off-by: Jerome Brunet Reviewed-by: Kevin Hilman --- drivers/mmc/host/meson-gx-mmc.c | 101 +++++++++++++++++++--------------------- 1 file changed, 49 insertions(+), 52 deletions(-) diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c index 8f9ba5190c18..4cc7d6530536 100644 --- a/drivers/mmc/host/meson-gx-mmc.c +++ b/drivers/mmc/host/meson-gx-mmc.c @@ -42,10 +42,7 @@ #define SD_EMMC_CLOCK 0x0 #define CLK_DIV_MASK GENMASK(5, 0) -#define CLK_DIV_MAX 63 #define CLK_SRC_MASK GENMASK(7, 6) -#define CLK_SRC_XTAL 0 /* external crystal */ -#define CLK_SRC_PLL 1 /* FCLK_DIV2 */ #define CLK_CORE_PHASE_MASK GENMASK(9, 8) #define CLK_TX_PHASE_MASK GENMASK(11, 10) #define CLK_RX_PHASE_MASK GENMASK(13, 12) @@ -137,13 +134,9 @@ struct meson_host { spinlock_t lock; void __iomem *regs; struct clk *core_clk; - struct clk_mux mux; - struct clk *mux_clk; + struct clk *signal_clk; unsigned long req_rate; - struct clk_divider cfg_div; - struct clk *cfg_div_clk; - unsigned int bounce_buf_size; void *bounce_buf; dma_addr_t bounce_dma_addr; @@ -291,7 +284,7 @@ static int meson_mmc_clk_set(struct meson_host *host, unsigned long clk_rate) return 0; } - ret = clk_set_rate(host->cfg_div_clk, clk_rate); + ret = clk_set_rate(host->signal_clk, clk_rate); if (ret) { dev_err(host->dev, "Unable to set cfg_div_clk to %lu. ret=%d\n", clk_rate, ret); @@ -299,7 +292,7 @@ static int meson_mmc_clk_set(struct meson_host *host, unsigned long clk_rate) } host->req_rate = clk_rate; - mmc->actual_clock = clk_get_rate(host->cfg_div_clk); + mmc->actual_clock = clk_get_rate(host->signal_clk); dev_dbg(host->dev, "clk rate: %u Hz\n", mmc->actual_clock); if (clk_rate != mmc->actual_clock) @@ -321,10 +314,13 @@ static int meson_mmc_clk_set(struct meson_host *host, unsigned long clk_rate) static int meson_mmc_clk_init(struct meson_host *host) { struct clk_init_data init; + struct clk_mux *mux; + struct clk_divider *div; + struct clk *clk; char clk_name[32]; int i, ret = 0; const char *mux_parent_names[MUX_CLK_NUM_PARENTS]; - const char *clk_div_parents[1]; + const char *clk_parent[1]; u32 clk_reg; /* get the mux parents */ @@ -343,6 +339,19 @@ static int meson_mmc_clk_init(struct meson_host *host) mux_parent_names[i] = __clk_get_name(clk); } + /* init SD_EMMC_CLOCK to sane defaults w/min clock rate */ + clk_reg = 0; + clk_reg |= FIELD_PREP(CLK_CORE_PHASE_MASK, host->tp.core_phase); + clk_reg |= FIELD_PREP(CLK_TX_PHASE_MASK, host->tp.tx_phase); + clk_reg |= FIELD_PREP(CLK_RX_PHASE_MASK, host->tp.rx_phase); + clk_reg |= CLK_DIV_MASK; + clk_reg |= CLK_ALWAYS_ON; + writel(clk_reg, host->regs + SD_EMMC_CLOCK); + + /* create the mux */ + mux = devm_kzalloc(host->dev, sizeof(mux), GFP_KERNEL); + if (!mux) + return -ENOMEM; /* create the mux */ snprintf(clk_name, sizeof(clk_name), "%s#mux", dev_name(host->dev)); init.name = clk_name; @@ -350,59 +359,47 @@ static int meson_mmc_clk_init(struct meson_host *host) init.flags = 0; init.parent_names = mux_parent_names; init.num_parents = MUX_CLK_NUM_PARENTS; - host->mux.reg = host->regs + SD_EMMC_CLOCK; - host->mux.shift = __bf_shf(CLK_SRC_MASK); - host->mux.mask = CLK_SRC_MASK >> host->mux.shift; - host->mux.flags = 0; - host->mux.table = NULL; - host->mux.hw.init = &init; - host->mux_clk = devm_clk_register(host->dev, &host->mux.hw); - if (WARN_ON(IS_ERR(host->mux_clk))) - return PTR_ERR(host->mux_clk); + mux->reg = host->regs + SD_EMMC_CLOCK; + mux->shift = __bf_shf(CLK_SRC_MASK); + mux->mask = CLK_SRC_MASK >> mux->shift; + mux->hw.init = &init; + + clk = devm_clk_register(host->dev, &mux->hw); + if (WARN_ON(IS_ERR(clk))) + return PTR_ERR(clk); /* create the divider */ + div = devm_kzalloc(host->dev, sizeof(div), GFP_KERNEL); + if (!div) + return -ENOMEM; + snprintf(clk_name, sizeof(clk_name), "%s#div", dev_name(host->dev)); init.name = clk_name; init.ops = &clk_divider_ops; init.flags = CLK_SET_RATE_PARENT; - clk_div_parents[0] = __clk_get_name(host->mux_clk); - init.parent_names = clk_div_parents; - init.num_parents = ARRAY_SIZE(clk_div_parents); + clk_parent[0] = __clk_get_name(clk); + init.parent_names = clk_parent; + init.num_parents = 1; - host->cfg_div.reg = host->regs + SD_EMMC_CLOCK; - host->cfg_div.shift = __bf_shf(CLK_DIV_MASK); - host->cfg_div.width = __builtin_popcountl(CLK_DIV_MASK); - host->cfg_div.hw.init = &init; - host->cfg_div.flags = CLK_DIVIDER_ONE_BASED | - CLK_DIVIDER_ROUND_CLOSEST; + div->reg = host->regs + SD_EMMC_CLOCK; + div->shift = __bf_shf(CLK_DIV_MASK); + div->width = __builtin_popcountl(CLK_DIV_MASK); + div->hw.init = &init; + div->flags = (CLK_DIVIDER_ONE_BASED | + CLK_DIVIDER_ROUND_CLOSEST); - host->cfg_div_clk = devm_clk_register(host->dev, &host->cfg_div.hw); - if (WARN_ON(PTR_ERR_OR_ZERO(host->cfg_div_clk))) - return PTR_ERR(host->cfg_div_clk); + host->signal_clk = devm_clk_register(host->dev, &div->hw); + if (WARN_ON(PTR_ERR_OR_ZERO(host->signal_clk))) + return PTR_ERR(host->signal_clk); /* init SD_EMMC_CLOCK to sane defaults w/min clock rate */ - clk_reg = 0; - clk_reg |= FIELD_PREP(CLK_CORE_PHASE_MASK, host->tp.core_phase); - clk_reg |= FIELD_PREP(CLK_TX_PHASE_MASK, host->tp.tx_phase); - clk_reg |= FIELD_PREP(CLK_RX_PHASE_MASK, host->tp.rx_phase); - clk_reg |= FIELD_PREP(CLK_SRC_MASK, CLK_SRC_XTAL); - clk_reg |= FIELD_PREP(CLK_DIV_MASK, CLK_DIV_MAX); - clk_reg &= ~CLK_ALWAYS_ON; - writel(clk_reg, host->regs + SD_EMMC_CLOCK); - - ret = clk_prepare_enable(host->cfg_div_clk); + host->mmc->f_min = clk_round_rate(host->signal_clk, 400000); + ret = clk_set_rate(host->signal_clk, host->mmc->f_min); if (ret) return ret; - /* Get the nearest minimum clock to 400KHz */ - host->mmc->f_min = clk_round_rate(host->cfg_div_clk, 400000); - - ret = meson_mmc_clk_set(host, host->mmc->f_min); - if (ret) - clk_disable_unprepare(host->cfg_div_clk); - - return ret; + return clk_prepare_enable(host->signal_clk); } static void meson_mmc_set_tuning_params(struct mmc_host *mmc) @@ -987,7 +984,7 @@ static int meson_mmc_probe(struct platform_device *pdev) dma_free_coherent(host->dev, host->bounce_buf_size, host->bounce_buf, host->bounce_dma_addr); err_div_clk: - clk_disable_unprepare(host->cfg_div_clk); + clk_disable_unprepare(host->signal_clk); err_core_clk: clk_disable_unprepare(host->core_clk); free_host: @@ -1009,7 +1006,7 @@ static int meson_mmc_remove(struct platform_device *pdev) dma_free_coherent(host->dev, host->bounce_buf_size, host->bounce_buf, host->bounce_dma_addr); - clk_disable_unprepare(host->cfg_div_clk); + clk_disable_unprepare(host->signal_clk); clk_disable_unprepare(host->core_clk); mmc_free_host(host->mmc);