From patchwork Mon Aug 21 16:02:53 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Brunet X-Patchwork-Id: 110574 Delivered-To: patch@linaro.org Received: by 10.182.109.195 with SMTP id hu3csp4246999obb; Mon, 21 Aug 2017 09:06:31 -0700 (PDT) X-Received: by 10.99.126.91 with SMTP id o27mr16961955pgn.202.1503331591837; Mon, 21 Aug 2017 09:06:31 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1503331591; cv=none; d=google.com; s=arc-20160816; b=WgOATfQxVffW3rMCb+KJPOTxuYru6YODeIEXv7sHSwHL7kxCDtsCH/DNtJMOb+f6SL TZx9MevVhL/jXUXIDk3AjjIxSLM4cnNlTJ96VVaBZbLWh7DEnOlR5XSrSEqFZUsxqLJN wQz3Agf8fmJtC8j/XrsSm9vpBq1Nxn++ilqpotr/J/bJJOd9CucvOE90qM6lZJxtk4d5 iIxldJGMK37QPbzgx6Fy703NchDJKYMtuTRcWpmNQYHXJPbogPTHXmJoCcxdQroQkb+3 +F32bEFfL6Avysg75bXP83Vu/pni6iySV3hiEpRZIfSsgPyNq4IRi4c/aeVCRCu9G+pR KfGw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=T3i+dLud+3nfDzlY0xLnaCWRS2AE5cbtgSr/lumMXD0=; b=LmKXifCO6I8fLrgfdwlQKiixc9lvrWd2EyYs2wSYA8GZ3Pw16kNa/dAx50GaJ5CUfO mc19hiBz8mYIRRMyFvjAv1KU7k+8meNNp+qrT8T1z+FynpFwL9IyfI2ye0125W6K8Qis RlM+hmxnJIFGZd/JfhbkFs+caWpJtevfdy8jUA3nfes6F895X2r9QLs5IFeLJUwvxlbc jyneC+Jbf5juNnhH1FLcjSc6EY7FSn/MG4XSmclfIHlrI7aTvcPY9e56Vc6v22G8/ycG CweAW+8BlNbHNHEdD2T2U75qo/QqQN1LurUVbkdv/uZh/Bpf1gg7dtgUfT15v2XboGnC fKOg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=B+Rgknn7; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id d90si8335969pld.137.2017.08.21.09.06.31; Mon, 21 Aug 2017 09:06:31 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=B+Rgknn7; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932084AbdHUQG2 (ORCPT + 26 others); Mon, 21 Aug 2017 12:06:28 -0400 Received: from mail-wr0-f170.google.com ([209.85.128.170]:36671 "EHLO mail-wr0-f170.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932131AbdHUQDP (ORCPT ); Mon, 21 Aug 2017 12:03:15 -0400 Received: by mail-wr0-f170.google.com with SMTP id f8so66999956wrf.3 for ; Mon, 21 Aug 2017 09:03:15 -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=T3i+dLud+3nfDzlY0xLnaCWRS2AE5cbtgSr/lumMXD0=; b=B+Rgknn7LjWKdenEHnAdLAX1rXzC2RjzsQzp1OM/VUOlqG5L8S6aM8ZCtrZOn6YIPF JdaHh9rirTtAFCr4NMhvUhrP5mFudikkqPX/+yP2ne1WrAgng537uBBIAgh/+ihR4pow OpbNmbYa48aLxwtGBlAHNF+HowZlxPoosJIVCFzEMw218LhQWeJfukLBHQVn9v9MKaKE TsOHNPIN6c3hcr6fxZ+GI0VB06xdme3PNQYQkqiTz3n6pl/Im0IGDJzzt5/Fa68bD+RW CA44fZWxbLqJw3rEapAZSLM6+h2dJfVGDXJQxW+5m+PwdeFDsmju8AFp5o8v/XPoUNjd b0cg== 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=T3i+dLud+3nfDzlY0xLnaCWRS2AE5cbtgSr/lumMXD0=; b=PifOdb6rwhB87zdnphaSo3pBmW+L6bpcZcQhOvzVAdmGxlhx2op5F3JbOW65/aeHMt GGyskZobp+/sZ0dLfzQYYhQX44xIM8DW586GI7g2MZZjNuX6DrHVL6fZHvzKubz41zy5 X4XZF6wJd2U6gDERjEb/a+YSThdBWjVdxfpL1OEPEb2BhyoSRRukI5IpEF8EJmESaS18 o25x8an2sxVIBvrsZaGZWn/dnn9xjvTzzC1YN+GBHe9H9dwQy/WJXHntFQ58A/B+8JuS V4rTsrr5nBNQSGMmshUW1oK7sVE9t4olTRkNVteJIQw3gnhVU+LogrU4WkzrEV9ozv3g iHXA== X-Gm-Message-State: AHYfb5ik2iZ394mh0PPOxPL44KQaELLEmJvAKPJTwzJFB4PFMXiGQ6wD UI6eExOT/PnGiEQy X-Received: by 10.223.169.246 with SMTP id b109mr11674699wrd.179.1503331394267; Mon, 21 Aug 2017 09:03:14 -0700 (PDT) Received: from localhost.localdomain ([90.63.244.31]) by smtp.googlemail.com with ESMTPSA id 63sm8120063wra.30.2017.08.21.09.03.13 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 21 Aug 2017 09:03:13 -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 v2 08/16] mmc: meson-gx: rework clock init function Date: Mon, 21 Aug 2017 18:02:53 +0200 Message-Id: <20170821160301.21899-9-jbrunet@baylibre.com> X-Mailer: git-send-email 2.9.5 In-Reply-To: <20170821160301.21899-1-jbrunet@baylibre.com> References: <20170821160301.21899-1-jbrunet@baylibre.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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. Reviewed-by: Kevin Hilman Signed-off-by: Jerome Brunet --- drivers/mmc/host/meson-gx-mmc.c | 107 +++++++++++++++++++--------------------- 1 file changed, 52 insertions(+), 55 deletions(-) -- 2.9.5 diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c index 8f9ba5190c18..2f45daa5d510 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 *mmc_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->mmc_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->mmc_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,66 +339,67 @@ 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; + snprintf(clk_name, sizeof(clk_name), "%s#mux", dev_name(host->dev)); init.name = clk_name; init.ops = &clk_mux_ops; 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->mmc_clk = devm_clk_register(host->dev, &div->hw); + if (WARN_ON(PTR_ERR_OR_ZERO(host->mmc_clk))) + return PTR_ERR(host->mmc_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->mmc_clk, 400000); + ret = clk_set_rate(host->mmc_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->mmc_clk); } static void meson_mmc_set_tuning_params(struct mmc_host *mmc) @@ -951,7 +948,7 @@ static int meson_mmc_probe(struct platform_device *pdev) meson_mmc_irq_thread, IRQF_SHARED, NULL, host); if (ret) - goto err_div_clk; + goto err_init_clk; mmc->caps |= MMC_CAP_CMD23; mmc->max_blk_count = CMD_CFG_LENGTH_MASK; @@ -967,7 +964,7 @@ static int meson_mmc_probe(struct platform_device *pdev) if (host->bounce_buf == NULL) { dev_err(host->dev, "Unable to map allocate DMA bounce buffer.\n"); ret = -ENOMEM; - goto err_div_clk; + goto err_init_clk; } host->descs = dma_alloc_coherent(host->dev, SD_EMMC_DESC_BUF_LEN, @@ -986,8 +983,8 @@ static int meson_mmc_probe(struct platform_device *pdev) err_bounce_buf: 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); +err_init_clk: + clk_disable_unprepare(host->mmc_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->mmc_clk); clk_disable_unprepare(host->core_clk); mmc_free_host(host->mmc);