Received: by 10.223.164.221 with SMTP id h29csp1803523wrb; Thu, 2 Nov 2017 00:52:23 -0700 (PDT) X-Google-Smtp-Source: ABhQp+TbOX9ZSmdrlWToZXeUrqJsH3HzFZGA8MGKeuKjz+7n5sXdwn4h0v7GWyqpuyglOwre3A51 X-Received: by 10.101.64.9 with SMTP id f9mr2723496pgp.114.1509609143836; Thu, 02 Nov 2017 00:52:23 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1509609143; cv=none; d=google.com; s=arc-20160816; b=P4TcWbTqAKUMkEYNkblv6g3L1S+Yi4NZToHQsBjQROqSkWi0NcXesAYM+r4I07Qt0J onKXuh8doL8iBVZABmG9jkLHStM1seFrYXdB7/DsjtNQI4El1qXLwDxv280NhB2YvhLP dVv/HK8bZqhR0pX/td0YEAH7wppdx2seaggMwWejbapCW8+YfgQpcOBBSMKjKeti7cYn tSxNHNwJzwZ3adjG5+f7KS4B+eiu/XJ6PoKjGZuTT3e7GAaVWFv9W+ExwTa55LxKJ4lp AugiEoSLAcK2jJ9hzxJkmR6RsWE1nsL8HOFCEriqfMfR0ok7J0axGOPN8W9w/BYxCQNS gfdA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:user-agent:in-reply-to :content-disposition:mime-version:references:message-id:subject:cc :to:from:date:dmarc-filter:dkim-signature:dkim-signature :arc-authentication-results; bh=fSfavTeFQ/FOA+Ek3B53Yt6FDVN+52v+NRqDBeO+dPc=; b=LjsPjd9/wgjDFlTOKLOIkmBEf+nElKevT/J8vzOuzuRBYj9tR5dL8sCdVNP4TBDoaC UxowfdhxO+50hkrwH2iy87QwS33R5jfEE6sGs80sFvmLIISwaPj9YNRUTWvQvDgbhEW/ NICHe04QBZaWtOMwSRSEqCJj3eVhjMVumRrIXXG3n7uXAMn4+y3vDXD84zVGZUkl5LWP D02f54p+W5+aoDlXf7a5Pw8hIyXPo8vMkMp8WnZfNoTp8fMGTs+jvAlANuva1Kjy7+kC THGB1l7lnmEF6eabzOQsQoz4q2jpI0ps9V3jbH4H5l8dHYATKXspNuo0bETDq98WASQI SZyg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@codeaurora.org header.s=default header.b=Pr+eG/jW; dkim=pass header.i=@codeaurora.org header.s=default header.b=jtAymSRB; 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 k4si3198309pgp.422.2017.11.02.00.52.09; Thu, 02 Nov 2017 00:52:23 -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=@codeaurora.org header.s=default header.b=Pr+eG/jW; dkim=pass header.i=@codeaurora.org header.s=default header.b=jtAymSRB; 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 S1755201AbdKBHun (ORCPT + 99 others); Thu, 2 Nov 2017 03:50:43 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:43866 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750836AbdKBHul (ORCPT ); Thu, 2 Nov 2017 03:50:41 -0400 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id 2D2C0607BA; Thu, 2 Nov 2017 07:50:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1509609041; bh=I5/jnAPoEiS0mj1SNFjTk3zmFQ0ZNHnuliyrtA/69us=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=Pr+eG/jWgXtJaIL5HQIVye+FAVXWwxbgiQ8FeL49o3pfexQ8I6dQfX40RX4CKEmIt uiJsp/wPrYNCd20pJuWJJUg09zSJhPiaOtT5IVmiqVjJjUR+QHvEK95FXHgb6rN9io JALJRR3CGrnYuYHOFOwKe/Ah5wQeSFGGqKFFJrko= X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on pdx-caf-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.8 required=2.0 tests=ALL_TRUSTED,BAYES_00, DKIM_SIGNED,T_DKIM_INVALID autolearn=no autolearn_force=no version=3.4.0 Received: from localhost (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1.2 with cipher DHE-RSA-AES128-SHA (128/128 bits)) (No client certificate requested) (Authenticated sender: sboyd@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id 45A03606B7; Thu, 2 Nov 2017 07:50:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1509609040; bh=I5/jnAPoEiS0mj1SNFjTk3zmFQ0ZNHnuliyrtA/69us=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=jtAymSRBByqYMoFyubwpxYfakNP37Vb+7Q7rZ6wHSkCQopmIAqZxZfY/7ZOYLONAw tTQlXxEA/HT8FQigK9WISC5BX+cL5AlpQiq2APcw8tha4wiFx030syRsFgnETKUCU5 cJ9obALSM9KoK2DYNbS7dR2HBmpRZ2zxJHotyQY4= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 45A03606B7 Authentication-Results: pdx-caf-mail.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: pdx-caf-mail.web.codeaurora.org; spf=none smtp.mailfrom=sboyd@codeaurora.org Date: Thu, 2 Nov 2017 00:50:39 -0700 From: Stephen Boyd To: Dong Aisheng Cc: linux-clk@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, mturquette@baylibre.com, dongas86@gmail.com, shawnguo@kernel.org, Anson.Huang@nxp.com, ping.bai@nxp.com Subject: Re: [PATCH V2 01/10] clk: clk-divider: add CLK_DIVIDER_ZERO_GATE clk support Message-ID: <20171102075039.GU30645@codeaurora.org> References: <1499946435-7177-1-git-send-email-aisheng.dong@nxp.com> <1499946435-7177-2-git-send-email-aisheng.dong@nxp.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1499946435-7177-2-git-send-email-aisheng.dong@nxp.com> User-Agent: Mutt/1.5.21 (2010-09-15) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 07/13, Dong Aisheng wrote: > diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c > index 9bb472c..55f8c41 100644 > --- a/drivers/clk/clk-divider.c > +++ b/drivers/clk/clk-divider.c > @@ -123,6 +123,9 @@ unsigned long divider_recalc_rate(struct clk_hw *hw, unsigned long parent_rate, > struct clk_divider *divider = to_clk_divider(hw); > unsigned int div; > > + if (flags & CLK_DIVIDER_ZERO_GATE && !val) > + return 0; > + > div = _get_div(table, val, flags, divider->width); > if (!div) { > WARN(!(flags & CLK_DIVIDER_ALLOW_ZERO), > @@ -141,8 +144,13 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw, > struct clk_divider *divider = to_clk_divider(hw); > unsigned int val; > > - val = clk_readl(divider->reg) >> divider->shift; > - val &= div_mask(divider->width); > + if ((divider->flags & CLK_DIVIDER_ZERO_GATE) && > + !clk_hw_is_enabled(hw)) { This seems racy. Are we holding the register lock here? > + val = divider->cached_val; > + } else { > + val = clk_readl(divider->reg) >> divider->shift; > + val &= div_mask(divider->width); > + } > > return divider_recalc_rate(hw, parent_rate, val, divider->table, > divider->flags); > @@ -392,6 +400,12 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, > value = divider_get_val(rate, parent_rate, divider->table, > divider->width, divider->flags); > > + if ((divider->flags & CLK_DIVIDER_ZERO_GATE) && > + !clk_hw_is_enabled(hw)) { Same racy comment here. > + divider->cached_val = value; > + return 0; > + } > + > if (divider->lock) > spin_lock_irqsave(divider->lock, flags); > else > @@ -414,10 +428,85 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, > return 0; > } > > +static int clk_divider_enable(struct clk_hw *hw) > +{ > + struct clk_divider *divider = to_clk_divider(hw); > + unsigned long flags = 0; > + u32 val; > + > + if (!(divider->flags & CLK_DIVIDER_ZERO_GATE)) > + return 0; This is not good. We will always jump to these functions on enable/disable for a divider although 99.9% of all dividers that exist won't need to run this code at all. Can you please move this logic into your own divider implementation? The flag can be added to the generic layer if necessary but I'd prefer to see this logic kept in the driver that uses it. If we get more than one driver doing the cached divider thing then we can think about moving it to the more generic place like here, but for now we should be able to keep this contained away from the basic types and handled by the quirky driver that needs it. > + > + if (!divider->cached_val) { > + pr_err("%s: no valid preset rate\n", clk_hw_get_name(hw)); > + return -EINVAL; > + } > + > + if (divider->lock) > + spin_lock_irqsave(divider->lock, flags); > + else > + __acquire(divider->lock); > + > + /* restore div val */ > + val = clk_readl(divider->reg); > + val |= divider->cached_val << divider->shift; > + clk_writel(val, divider->reg); > + > + if (divider->lock) > + spin_unlock_irqrestore(divider->lock, flags); > + else > + __release(divider->lock); > + > + return 0; > +} > + > +static void clk_divider_disable(struct clk_hw *hw) > +{ > + struct clk_divider *divider = to_clk_divider(hw); > + unsigned long flags = 0; > + u32 val; > + > + if (!(divider->flags & CLK_DIVIDER_ZERO_GATE)) > + return; > + > + if (divider->lock) > + spin_lock_irqsave(divider->lock, flags); > + else > + __acquire(divider->lock); > + > + /* store the current div val */ > + val = clk_readl(divider->reg) >> divider->shift; > + val &= div_mask(divider->width); > + divider->cached_val = val; > + clk_writel(0, divider->reg); > + > + if (divider->lock) > + spin_unlock_irqrestore(divider->lock, flags); > + else > + __release(divider->lock); > +} > + > +static int clk_divider_is_enabled(struct clk_hw *hw) > +{ > + struct clk_divider *divider = to_clk_divider(hw); > + u32 val; > + > + if (!(divider->flags & CLK_DIVIDER_ZERO_GATE)) > + return __clk_get_enable_count(hw->clk); The plan was to delete this API once OMAP stopped using it. clk_hw_is_enabled() doesn't work? > + > + val = clk_readl(divider->reg) >> divider->shift; > + val &= div_mask(divider->width); > + > + return val ? 1 : 0; > +} > + > const struct clk_ops clk_divider_ops = { > .recalc_rate = clk_divider_recalc_rate, > .round_rate = clk_divider_round_rate, > .set_rate = clk_divider_set_rate, > + .enable = clk_divider_enable, > + .disable = clk_divider_disable, > + .is_enabled = clk_divider_is_enabled, > }; > EXPORT_SYMBOL_GPL(clk_divider_ops); > > @@ -436,6 +525,7 @@ static struct clk_hw *_register_divider(struct device *dev, const char *name, > struct clk_divider *div; > struct clk_hw *hw; > struct clk_init_data init; > + u32 val; > int ret; > > if (clk_divider_flags & CLK_DIVIDER_HIWORD_MASK) { > @@ -468,6 +558,12 @@ static struct clk_hw *_register_divider(struct device *dev, const char *name, > div->hw.init = &init; > div->table = table; > > + if (div->flags & CLK_DIVIDER_ZERO_GATE) { > + val = clk_readl(reg) >> shift; > + val &= div_mask(width); > + div->cached_val = val; > + } What if it isn't on? Setting cached_val to 0 is ok? > + > /* register the clock */ > hw = &div->hw; > ret = clk_hw_register(dev, hw); -- Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project From 1572807872081216786@xxx Thu Jul 13 11:47:52 +0000 2017 X-GM-THRID: 1572807872081216786 X-Gmail-Labels: Inbox,Category Forums