Received: by 2002:ac0:a5b6:0:0:0:0:0 with SMTP id m51-v6csp5206036imm; Tue, 19 Jun 2018 06:51:20 -0700 (PDT) X-Google-Smtp-Source: ADUXVKImXPJK8PcZOWXLErhaiWgFdCewp9cceHhqzJrIpkqEf3K/8RJ2r8YWDr92AP7HnrnP1xQA X-Received: by 2002:a63:b215:: with SMTP id x21-v6mr14913044pge.393.1529416280810; Tue, 19 Jun 2018 06:51:20 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1529416280; cv=none; d=google.com; s=arc-20160816; b=eeFZqs4+/dbVABq03mBZPHu6zdOa2194DDypqIdYHXCXyugiJWhkXuB6HXp8Blxet9 SeMuBcpqyi+q6OG9NQ64S/Cp0cvE73xultkoql5rMmUzA+ozY91hjXRFpfT+hBpmvf0P T1x3UMx6kcmWIwVUe9jKDmEgNNrfCEQuTOaKBSHwN0FfE4XubFWrSDa00dbf457e/Tsz aRYY7ms84j7Ksm7jPraqC3HvAz6K8cIqFrxfTz5Ca4dPvBfIRj6rJ+iS2URIORR+K0Rt NBh0okxlc1jLacupRTrSsSlZco7dinJYdXDeLReQ0YrgTtyu57qEiRXTvirgpS8T4fZQ h2rg== 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:dmarc-filter:dkim-signature:dkim-signature :arc-authentication-results; bh=4wA9RhF16fuMKnQlktn88VlNYYX5ehY3EHvAb5vT3HQ=; b=GYdsAY1je8QrKxAepkwIy2gKykJ1Sc5MuVAz8AcN5ErRwxdvKHc83T4SrCRwn2CTj4 J3TzVcVOO72CNaYez0/xLgTONF13ByyQafBBaT1sG1/mY3YhYMZe62qUtW6WwLEO5V/7 Jbfz54VfWL58bBV9R6hDM69PUp7XLlZk3hcnszY6QoaoBTffOddEHHmk8h+J01Qt8oaS mx/LnOdPhTY8rEMlCNaciTGJu2B9f6yrEaj44W2yEWSfnd0nLUmnFZDvRuYAntR80CjB Jo22YuvMeUubAPIYwOeJnW8pNvnleyx7IsQAF7ovN6r8KYy8FnsZlvJrz8MfLmWMrSZU 9qhA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@codeaurora.org header.s=default header.b=Mwj4G5wb; dkim=pass header.i=@codeaurora.org header.s=default header.b=YWkaiEF6; 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 h1-v6si9091449pgf.560.2018.06.19.06.51.07; Tue, 19 Jun 2018 06:51:20 -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=Mwj4G5wb; dkim=pass header.i=@codeaurora.org header.s=default header.b=YWkaiEF6; 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 S966518AbeFSNqX (ORCPT + 99 others); Tue, 19 Jun 2018 09:46:23 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:40348 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S965599AbeFSNqT (ORCPT ); Tue, 19 Jun 2018 09:46:19 -0400 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id 9298960B16; Tue, 19 Jun 2018 13:46:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1529415978; bh=/4y8TUGgGxEhsBy1U2TEl104odot8EkJ/oSYNTUX2T0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Mwj4G5wbJbGzUvRcCZT9JozEjTtTRPIVSWpVpoZXPB8RgT0jJJbF3BR0uLD+WU391 n9XTpSn/g2xAS3lAccyQIrr6sZ7fdHq7ZcJwSmECgoDiAbPbVvXlU61dbzRHBPvyQu 0w7O0iMMTPKWvZrWnFwVpbRLDJzgM9OHuZHuqEiQ= 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 srichara-linux.qualcomm.com (blr-c-bdr-fw-01_globalnat_allzones-outside.qualcomm.com [103.229.19.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: sricharan@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id 4775260B69; Tue, 19 Jun 2018 13:46:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1529415977; bh=/4y8TUGgGxEhsBy1U2TEl104odot8EkJ/oSYNTUX2T0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=YWkaiEF6cU9hRIVwaRcRZBq06HmzjX/PVzPH740rGQ7YH9yiOfn38wX8MCU3X5JnW WPdxOwEmsGUWsNM9hne2Vyws1sARZEtoQHpvneg4OhOErXeZY77SjxiwpDNU+lhUaG k4W1s6kQbPafYmWEQTMjH3pfEwbMqLbxQP4xEvhU= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 4775260B69 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=sricharan@codeaurora.org From: Sricharan R To: robh@kernel.org, viresh.kumar@linaro.org, mark.rutland@arm.com, mturquette@baylibre.com, sboyd@codeaurora.org, linux@armlinux.org.uk, andy.gross@linaro.org, david.brown@linaro.org, rjw@rjwysocki.net, linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, linux-arm-msm@vger.kernel.org, linux-soc@vger.kernel.org, linux-pm@vger.kernel.org, linux@arm.linux.org.uk, thierry.escande@linaro.org, ctatlor97@gmail.com Cc: sricharan@codeaurora.org Subject: [PATCH v10 07/14] clk: qcom: Add support for Krait clocks Date: Tue, 19 Jun 2018 19:15:18 +0530 Message-Id: <1529415925-28915-8-git-send-email-sricharan@codeaurora.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1529415925-28915-1-git-send-email-sricharan@codeaurora.org> References: <1529415925-28915-1-git-send-email-sricharan@codeaurora.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Stephen Boyd The Krait clocks are made up of a series of muxes and a divider that choose between a fixed rate clock and dedicated HFPLLs for each CPU. Instead of using mmio accesses to remux parents, the Krait implementation exposes the remux control via cp15 registers. Support these clocks. Signed-off-by: Stephen Boyd --- drivers/clk/qcom/Kconfig | 4 ++ drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/clk-krait.c | 124 +++++++++++++++++++++++++++++++++++++++++++ drivers/clk/qcom/clk-krait.h | 37 +++++++++++++ 4 files changed, 166 insertions(+) create mode 100644 drivers/clk/qcom/clk-krait.c create mode 100644 drivers/clk/qcom/clk-krait.h diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 95f9980..66894d2 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -261,3 +261,7 @@ config QCOM_HFPLL Support for the high-frequency PLLs present on Qualcomm devices. Say Y if you want to support CPU frequency scaling on devices such as MSM8974, APQ8084, etc. + +config KRAIT_CLOCKS + bool + select KRAIT_L2_ACCESSORS diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index d486aa3..82615ed 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -11,6 +11,7 @@ clk-qcom-y += clk-branch.o clk-qcom-y += clk-regmap-divider.o clk-qcom-y += clk-regmap-mux.o clk-qcom-y += clk-regmap-mux-div.o +clk-qcom-$(CONFIG_KRAIT_CLOCKS) += clk-krait.o clk-qcom-y += clk-hfpll.o clk-qcom-y += reset.o clk-qcom-$(CONFIG_QCOM_GDSC) += gdsc.o diff --git a/drivers/clk/qcom/clk-krait.c b/drivers/clk/qcom/clk-krait.c new file mode 100644 index 0000000..2e41767 --- /dev/null +++ b/drivers/clk/qcom/clk-krait.c @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2018, The Linux Foundation. All rights reserved. + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "clk-krait.h" + +/* Secondary and primary muxes share the same cp15 register */ +static DEFINE_SPINLOCK(krait_clock_reg_lock); + +#define LPL_SHIFT 8 +static void __krait_mux_set_sel(struct krait_mux_clk *mux, int sel) +{ + unsigned long flags; + u32 regval; + + spin_lock_irqsave(&krait_clock_reg_lock, flags); + regval = krait_get_l2_indirect_reg(mux->offset); + regval &= ~(mux->mask << mux->shift); + regval |= (sel & mux->mask) << mux->shift; + if (mux->lpl) { + regval &= ~(mux->mask << (mux->shift + LPL_SHIFT)); + regval |= (sel & mux->mask) << (mux->shift + LPL_SHIFT); + } + krait_set_l2_indirect_reg(mux->offset, regval); + spin_unlock_irqrestore(&krait_clock_reg_lock, flags); + + /* Wait for switch to complete. */ + mb(); + udelay(1); +} + +static int krait_mux_set_parent(struct clk_hw *hw, u8 index) +{ + struct krait_mux_clk *mux = to_krait_mux_clk(hw); + u32 sel; + + sel = clk_mux_reindex(index, mux->parent_map, 0); + mux->en_mask = sel; + /* Don't touch mux if CPU is off as it won't work */ + if (__clk_is_enabled(hw->clk)) + __krait_mux_set_sel(mux, sel); + + return 0; +} + +static u8 krait_mux_get_parent(struct clk_hw *hw) +{ + struct krait_mux_clk *mux = to_krait_mux_clk(hw); + u32 sel; + + sel = krait_get_l2_indirect_reg(mux->offset); + sel >>= mux->shift; + sel &= mux->mask; + mux->en_mask = sel; + + return clk_mux_get_parent(hw, sel, mux->parent_map, 0); +} + +const struct clk_ops krait_mux_clk_ops = { + .set_parent = krait_mux_set_parent, + .get_parent = krait_mux_get_parent, + .determine_rate = __clk_mux_determine_rate_closest, +}; +EXPORT_SYMBOL_GPL(krait_mux_clk_ops); + +/* The divider can divide by 2, 4, 6 and 8. But we only really need div-2. */ +static long krait_div2_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + *parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw), rate * 2); + return DIV_ROUND_UP(*parent_rate, 2); +} + +static int krait_div2_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct krait_div2_clk *d = to_krait_div2_clk(hw); + unsigned long flags; + u32 val; + u32 mask = BIT(d->width) - 1; + + if (d->lpl) + mask = mask << (d->shift + LPL_SHIFT) | mask << d->shift; + + spin_lock_irqsave(&krait_clock_reg_lock, flags); + val = krait_get_l2_indirect_reg(d->offset); + val &= ~mask; + krait_set_l2_indirect_reg(d->offset, val); + spin_unlock_irqrestore(&krait_clock_reg_lock, flags); + + return 0; +} + +static unsigned long +krait_div2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) +{ + struct krait_div2_clk *d = to_krait_div2_clk(hw); + u32 mask = BIT(d->width) - 1; + u32 div; + + div = krait_get_l2_indirect_reg(d->offset); + div >>= d->shift; + div &= mask; + div = (div + 1) * 2; + + return DIV_ROUND_UP(parent_rate, div); +} + +const struct clk_ops krait_div2_clk_ops = { + .round_rate = krait_div2_round_rate, + .set_rate = krait_div2_set_rate, + .recalc_rate = krait_div2_recalc_rate, +}; +EXPORT_SYMBOL_GPL(krait_div2_clk_ops); diff --git a/drivers/clk/qcom/clk-krait.h b/drivers/clk/qcom/clk-krait.h new file mode 100644 index 0000000..441ba1e --- /dev/null +++ b/drivers/clk/qcom/clk-krait.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __QCOM_CLK_KRAIT_H +#define __QCOM_CLK_KRAIT_H + +#include + +struct krait_mux_clk { + unsigned int *parent_map; + u32 offset; + u32 mask; + u32 shift; + u32 en_mask; + bool lpl; + + struct clk_hw hw; + struct notifier_block clk_nb; +}; + +#define to_krait_mux_clk(_hw) container_of(_hw, struct krait_mux_clk, hw) + +extern const struct clk_ops krait_mux_clk_ops; + +struct krait_div2_clk { + u32 offset; + u8 width; + u32 shift; + bool lpl; + + struct clk_hw hw; +}; + +#define to_krait_div2_clk(_hw) container_of(_hw, struct krait_div2_clk, hw) + +extern const struct clk_ops krait_div2_clk_ops; + +#endif -- 1.9.1