From patchwork Thu Sep 26 10:38:15 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dzmitry Sankouski X-Patchwork-Id: 13813206 Received: from mail-lj1-f181.google.com (mail-lj1-f181.google.com [209.85.208.181]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3D3F01AD9EB; Thu, 26 Sep 2024 10:38:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.181 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727347128; cv=none; b=Pana9wFTSM4XkZDhl05Dbc0+0tTlxl4Np/HOwvS75qxzZ62y0nCTKXdUBI0miN6dWvVRn5+mRQ85VVwQQRK6ba05/qz3dhSXTneWohDmwofmSMX9uUsx4LU8b/S6G6YVG2NUeTzaoozo0v9ZDIa1+vEJ05t9ttNtRyuLNPmww4M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727347128; c=relaxed/simple; bh=cU9P4qzHC4jP9o3v4wIQ+UaeV1Ek/oCy3Sa5T8uuL30=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=eq0srcx2aGMVNCMjGtSAJEh+vAZHYCGhLheehKSPEQ6EuRh+2X50wTe4OHZJWgU/6zauBMBvwJvaZ+cBfIpk8NNYSdIIoTQNd6v007W6G4l44eLDWxR4YVfoqLysZqJuOGo3VxdJPipKRtIFSbyrUt+WSe6gjb9V8xwcKFc2TJM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=QbONMyJ6; arc=none smtp.client-ip=209.85.208.181 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="QbONMyJ6" Received: by mail-lj1-f181.google.com with SMTP id 38308e7fff4ca-2f75e5f3debso7382201fa.1; Thu, 26 Sep 2024 03:38:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1727347125; x=1727951925; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=qXV7innKMzJjCsw3L4AU06wd569JCGXLkPWGw2m6iWE=; b=QbONMyJ64Jtxa3m9EIoZ8BD9npxi3nZPTf0cZc66vZdGd/JPkj9Jaf+rL3rX5katn3 sqmGDL+6L46iG9YIMeCo3nnXs2JdEcOFdixhB4ax3RqIaRA5l0GRW22w11gV1ibyet39 ZcMF5MFZdEHRUObgmzjXdEteD/HIhN6Y2rOapLW5CSt8+3H2SI6w+JjCliTUJIv4/L3W b9XS3E/lxlJ42qhJl7bDfR5J+5npqvS6KdX1/rH4nmverWYDIydOSOUkcqCuZ1xoE6dy A3C2Fo0UVQtDJ5zfaTQHE6sdI6XWwQrO7l3xmqYc42UlijFGMzDHNWNcp2spcCgRj+/a UjJQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727347125; x=1727951925; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=qXV7innKMzJjCsw3L4AU06wd569JCGXLkPWGw2m6iWE=; b=FNpJi+TfxyuZV7ZS+W/Uvbk6hKVSJLKDY+sdKR0dIIXl5DyOm1pgRVPOasKW/kA9W4 kICttpEN/8GC4+9l5kyYT9OH9196KRvKQ+RTnN4fXfOQWDGPNTDjJHWo4v63FhE54vyW zFGGkCpkPkthfEBfk5cIL2ovUKMGOzBkN9fuzkJk7eDJIukqX7BN4bSf++oYL10TupqY 1OVlAhpPHs3swhaAGNk+VM1+eiIawI6WhKht1akMJ9A86DUq2MLHgp0MlliyBLq4NX05 TrxSqBMDD48sVgNvJoqboD4uj140uvACnAS5r3Kjyrpb6/GfMVLlPVI9i29ZW2B0l+Rt yHaA== X-Forwarded-Encrypted: i=1; AJvYcCUciQD4uVNxQPVV55X9rVuXcEXPmsWJHMcZRCr1IoivLSrY8q5U/OVcmtmb4P88CVJDd6vMWOmPb8s=@vger.kernel.org, AJvYcCXkfze3EiT8Z3AHSqnLGJJOURPxrV6NXMzJRJWWik6QuOqzLZoj9MhLKTX8hhAgozphXfjJljJxAGr2fK/b@vger.kernel.org X-Gm-Message-State: AOJu0YwsYfV0iCHN+sQujxQtpyn6jad86gxvvQdaWggJD4hESVHvrJme eVAcV8eAvan+Wzl9SpUPLXD3GE3r8JlWGiCM1yUuJ7rqexrxiMdp X-Google-Smtp-Source: AGHT+IHqq7HAndaVicSzhcbSS2gvRRgmsZL6X7XvOrIM5G5fxL5+ql5X55gxtU8HHpG0Y7PjceBIbQ== X-Received: by 2002:a05:651c:1991:b0:2f7:56c2:7288 with SMTP id 38308e7fff4ca-2f913f5201amr40260371fa.7.1727347125023; Thu, 26 Sep 2024 03:38:45 -0700 (PDT) Received: from [127.0.1.1] (mm-20-1-84-93.mgts.dynamic.pppoe.byfly.by. [93.84.1.20]) by smtp.googlemail.com with ESMTPSA id 38308e7fff4ca-2f8d289ee94sm7863791fa.120.2024.09.26.03.38.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 26 Sep 2024 03:38:43 -0700 (PDT) From: Dzmitry Sankouski Date: Thu, 26 Sep 2024 13:38:15 +0300 Subject: [PATCH v5 1/2] clk: qcom: clk-rcg2: document calc_rate function Precedence: bulk X-Mailing-List: linux-arm-msm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240617-starqltechn_integration_upstream-v5-1-761795ea5084@gmail.com> References: <20240617-starqltechn_integration_upstream-v5-0-761795ea5084@gmail.com> In-Reply-To: <20240617-starqltechn_integration_upstream-v5-0-761795ea5084@gmail.com> To: Bjorn Andersson , Michael Turquette , Stephen Boyd Cc: linux-arm-msm@vger.kernel.org, linux-clk@vger.kernel.org, linux-kernel@vger.kernel.org, Dzmitry Sankouski X-Mailer: b4 0.12.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1727347119; l=1073; i=dsankouski@gmail.com; s=20240619; h=from:subject:message-id; bh=cU9P4qzHC4jP9o3v4wIQ+UaeV1Ek/oCy3Sa5T8uuL30=; b=IpSVYdD5v7r9p90hDpaR1esxTaVJtF9OXMXeHPo4ernHjBlk4MaA4Yp8cImzPm1m09oyXSoZO aZ6WU+7huv7CjoPdev2qssvBc70hw632P5/wzyY8xCt7rYsFGZCydSq X-Developer-Key: i=dsankouski@gmail.com; a=ed25519; pk=YJcXFcN1EWrzBYuiE2yi5Mn6WLn6L1H71J+f7X8fMag= Update calc_rate docs to reflect, that pre_div is not pure divisor, but a register value, and requires conversion. Signed-off-by: Dzmitry Sankouski --- drivers/clk/qcom/clk-rcg2.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c index bf26c5448f00..0fc23a87b432 100644 --- a/drivers/clk/qcom/clk-rcg2.c +++ b/drivers/clk/qcom/clk-rcg2.c @@ -153,7 +153,14 @@ static int clk_rcg2_set_parent(struct clk_hw *hw, u8 index) * * parent_rate m * rate = ----------- x --- - * hid_div n + * pre_div n + * + * @param rate - Parent rate. + * @param m - Multiplier. + * @param n - Divisor. + * @param mode - Use zero to ignore m/n calculation. + * @param hid_div - Pre divisor register value. Pre divisor value + * relates to hid_div as pre_div = (hid_div + 1) / 2 */ static unsigned long calc_rate(unsigned long rate, u32 m, u32 n, u32 mode, u32 hid_div) From patchwork Thu Sep 26 10:38:16 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dzmitry Sankouski X-Patchwork-Id: 13813207 Received: from mail-lj1-f171.google.com (mail-lj1-f171.google.com [209.85.208.171]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 55D931AE860; Thu, 26 Sep 2024 10:38:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727347132; cv=none; b=hGUfIFrXY1+wBMZDN5DZdyTjlOS6ZVpF2eXNucJnpm5SZkqIzAjwqMd2TWQkZSdBTlQC23i0vJay4BAlBY4Nf6Ki5MW/4BgzXGyXJyWxzhyjxYKbGm4MhYnB1eQrT/8pwM8iCvqX3NG9LpJS2KEhvP9mL9SxUHm0ibK8Gj0l0tI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1727347132; c=relaxed/simple; bh=DL0WVxt4TNJe2bjSlD/F5XbK0YTNlXdF+v6jNsh9eq8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=lmkLC5V9arFoOde7B+Yz2oXFAjXfG4JdEjWg30sJ/8PN8TFkSuJCk9BBXtsezKtyuJll/7YT7+H14EecFv7UmUZCk4HdB9zV313hODD3zs9AdyAdwcOX2Goc5gsCXFc7WfO2v6AXJ4RFBAQEfCSZYw/Lvcmerm8MzFt5CcrRdlA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=QSltFiqI; arc=none smtp.client-ip=209.85.208.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="QSltFiqI" Received: by mail-lj1-f171.google.com with SMTP id 38308e7fff4ca-2f753375394so7901021fa.0; Thu, 26 Sep 2024 03:38:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1727347128; x=1727951928; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=yqJJeCQuBca5+5pelUwYB3F6DHyevRrug1BbgxepDrY=; b=QSltFiqIG5UWlgvM+zXc7K5lIavc1rtXvHN6Gy3pO0iOBettDGNSmh8inhvPzyNQdV YMk7Op0KeG5/L+poig18EbFoQIAWMCAPlF019qseJQBKHAji2t4CAqyTQPkQgAsLDKpo mhrj/uqwmyvPYlzvvJusNvzYe7hY8Aea/ZcRFkmH51a20SfMG/3SkRPE4c+M/lq8P5E0 LzoFrxJdFYNba4Uit1LX/Q0ZRQe82zr8O313kgtpwoQPHx+U7u2U3kx4jqHkc+FE6Hf6 ZEnON4teKITw8lPcBCsBkB94uKEhK8sVNyjGzdWl0fMCFbQ1qAT5r5NRLjidPM2lLNbo Y3Hg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727347128; x=1727951928; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=yqJJeCQuBca5+5pelUwYB3F6DHyevRrug1BbgxepDrY=; b=RxIi9US5PmBVdiVM3+Lr7NU4yggeVxcn5rUabAXOhlitePRM/Sb0iCbIXuvVgk+FU5 PpXn5BkqRw+dl+1ENsz/qEkpnPtH2LbBm88cqZ3ctZQFm6nAitmsMtBAUq9M4njzOSJW YN2ppmemxcmKuxPG+duGkt8minICw+koXk730z6C6hRF32Nsg4DOGoOZKELAEhcwizsD LceSKRxgY9kPUcmPNVFuriQiu5YrNwrp4i6QJhvDNhWWyQ1FNX14TpWx3jBR4YnDVr2J rufpNz6PYJoWKiW4ALvOnlrSRPyhOi8odhpqHfAoIHutdR76qDjpDNMoCk8dxK/Ri8kE kPXA== X-Forwarded-Encrypted: i=1; AJvYcCXHX76TWjf3vvnLlq0F8+XabavFtmdzolBXl3Eu1yldQr39F24atEkXRw5oOSopWxfPc2azWix+/Z9GAwPD@vger.kernel.org, AJvYcCXVPu9AUvekkTqkrQyG6Hymaa7RQ/Yr3UE5Yw91prz9BpXmgEi0ikK5Y6GxwaNfNFExrLXEe2D+mmw=@vger.kernel.org X-Gm-Message-State: AOJu0YyhQKEerNl+CJL0hZQ4J0mOfGfpZyAhS/h9U6bZNw3SFPihVusr WWfABVrBXc3VaS5lPfiFB2zOIxn1lahpoy1OAkGYVEo5y1Z4CCDIq39L3Q== X-Google-Smtp-Source: AGHT+IHuqKWxlgK+62o47W8Ar15FJFHhvH+E+PRIiW2wgDJvzlKodsksW8HSeDQ8pk/yzrkVh5axQQ== X-Received: by 2002:a2e:4e19:0:b0:2f3:f4e2:869c with SMTP id 38308e7fff4ca-2f91ca731fdmr29026721fa.44.1727347128139; Thu, 26 Sep 2024 03:38:48 -0700 (PDT) Received: from [127.0.1.1] (mm-20-1-84-93.mgts.dynamic.pppoe.byfly.by. [93.84.1.20]) by smtp.googlemail.com with ESMTPSA id 38308e7fff4ca-2f8d289ee94sm7863791fa.120.2024.09.26.03.38.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 26 Sep 2024 03:38:46 -0700 (PDT) From: Dzmitry Sankouski Date: Thu, 26 Sep 2024 13:38:16 +0300 Subject: [PATCH v5 2/2] gcc-sdm845: Add general purpose clock ops Precedence: bulk X-Mailing-List: linux-arm-msm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240617-starqltechn_integration_upstream-v5-2-761795ea5084@gmail.com> References: <20240617-starqltechn_integration_upstream-v5-0-761795ea5084@gmail.com> In-Reply-To: <20240617-starqltechn_integration_upstream-v5-0-761795ea5084@gmail.com> To: Bjorn Andersson , Michael Turquette , Stephen Boyd Cc: linux-arm-msm@vger.kernel.org, linux-clk@vger.kernel.org, linux-kernel@vger.kernel.org, Dzmitry Sankouski X-Mailer: b4 0.12.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1727347119; l=11131; i=dsankouski@gmail.com; s=20240619; h=from:subject:message-id; bh=DL0WVxt4TNJe2bjSlD/F5XbK0YTNlXdF+v6jNsh9eq8=; b=bOBuUS1wpxRlKXJ7EOriuRXEMmyTtq7Jci5UyzGcJ+z7AGUzNpdOfHqD83Eqj6NPKKj6CMXqw e+IlFDSQichDBCRVd8XUHG1y/qXjYe381j6ZLWZytwZp0szEXnu1Axm X-Developer-Key: i=dsankouski@gmail.com; a=ed25519; pk=YJcXFcN1EWrzBYuiE2yi5Mn6WLn6L1H71J+f7X8fMag= SDM845 has "General Purpose" clocks that can be muxed to SoC pins to clock various external devices. Those clocks may be used as e.g. PWM sources for external peripherals. GPCLK can in theory have arbitrary value depending on the use case, so the concept of frequency tables, used in rcg2 clock driver, is not efficient, because it allows only defined frequencies. Introduce clk_rcg2_gp_ops, which automatically calculate clock mnd values for arbitrary clock rate. The calculation done as follows: - upon determine rate request, we calculate m/n/pre_div as follows: - find parent(from our client's assigned-clock-parent) rate - find scaled rates by dividing rates on its greatest common divisor - assign requested scaled rate to m - factorize scaled parent rate, put multipliers to n till max value (determined by mnd_width) - validate calculated values with *_width: - if doesn't fit, delete divisor and multiplier by 2 until fit - return determined rate Limitations: - The driver doesn't select a parent clock (it may be selected by client in device tree with assigned-clocks, assigned-clock-parents properties) Signed-off-by: Dzmitry Sankouski --- Changes in v5: - replace '/' to div64_u64 to fix 32 bit gcc error - fix empty scalar initializer --- drivers/clk/qcom/clk-rcg.h | 1 + drivers/clk/qcom/clk-rcg2.c | 192 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- drivers/clk/qcom/gcc-sdm845.c | 11 ++---- 3 files changed, 190 insertions(+), 14 deletions(-) diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h index 8e0f3372dc7a..8817d14bbda4 100644 --- a/drivers/clk/qcom/clk-rcg.h +++ b/drivers/clk/qcom/clk-rcg.h @@ -189,6 +189,7 @@ struct clk_rcg2_gfx3d { container_of(to_clk_rcg2(_hw), struct clk_rcg2_gfx3d, rcg) extern const struct clk_ops clk_rcg2_ops; +extern const struct clk_ops clk_rcg2_gp_ops; extern const struct clk_ops clk_rcg2_floor_ops; extern const struct clk_ops clk_rcg2_fm_ops; extern const struct clk_ops clk_rcg2_mux_closest_ops; diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c index 0fc23a87b432..5f87b3d3cbe4 100644 --- a/drivers/clk/qcom/clk-rcg2.c +++ b/drivers/clk/qcom/clk-rcg2.c @@ -8,11 +8,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include @@ -32,6 +34,7 @@ #define CFG_REG 0x4 #define CFG_SRC_DIV_SHIFT 0 +#define CFG_SRC_DIV_LENGTH 8 #define CFG_SRC_SEL_SHIFT 8 #define CFG_SRC_SEL_MASK (0x7 << CFG_SRC_SEL_SHIFT) #define CFG_MODE_SHIFT 12 @@ -148,6 +151,14 @@ static int clk_rcg2_set_parent(struct clk_hw *hw, u8 index) return update_config(rcg); } +// Converts divisors to corresponding clock register values. +// @param f - Frequency table with pure m/n/pre_div parameters. +static void convert_to_reg_val(struct freq_tbl *f) +{ + f->pre_div *= 2; + f->pre_div -= 1; +} + /* * Calculate m/n:d rate * @@ -400,16 +411,116 @@ static int clk_rcg2_fm_determine_rate(struct clk_hw *hw, return _freq_tbl_fm_determine_rate(hw, rcg->freq_multi_tbl, req); } -static int __clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f, - u32 *_cfg) +// Split multiplier that doesn't fit in n neither in pre_div. +// +// @param multiplier - multiplier to split between n and pre_div +// @param pre_div - pointer to pre divisor value +// @param n - pointer to n divisor value +// @param pre_div_max - pre divisor maximum value +// +static inline void clk_rcg2_split_div(int multiplier, unsigned int *pre_div, + u16 *n, unsigned int pre_div_max) +{ + *n = mult_frac(multiplier * *n, *pre_div, pre_div_max); + *pre_div = pre_div_max; +} + +static void clk_rcg2_calc_mnd(u64 parent_rate, u64 rate, struct freq_tbl *f, + unsigned int mnd_max, unsigned int pre_div_max) +{ + int i = 2, count = 0; + unsigned int pre_div = 1; + unsigned long rates_gcd, scaled_parent_rate; + u16 m, n = 1, n_candidate = 1, n_max; + + rates_gcd = gcd(parent_rate, rate); + m = div64_u64(rate, rates_gcd); + scaled_parent_rate = div64_u64(parent_rate, rates_gcd); + while (scaled_parent_rate > (mnd_max + m) * pre_div_max) { + // we're exceeding divisor's range, trying lower scale. + if (m > 1) { + m--; + scaled_parent_rate = mult_frac(scaled_parent_rate, m, (m + 1)); + } else { + f->n = mnd_max + m; + f->pre_div = pre_div_max; + f->m = m; + } + } + + n_max = m + mnd_max; + + while (scaled_parent_rate > 1) { + while (scaled_parent_rate % i == 0) { + n_candidate *= i; + if (n_candidate < n_max) + n = n_candidate; + else if (pre_div * i < pre_div_max) + pre_div *= i; + else + clk_rcg2_split_div(i, &pre_div, &n, pre_div_max); + + scaled_parent_rate /= i; + } + i++; + count++; + } + + f->m = m; + f->n = n; + f->pre_div = pre_div > 1 ? pre_div : 0; +} + +static int clk_rcg2_determine_gp_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + struct clk_rcg2 *rcg = to_clk_rcg2(hw); + struct freq_tbl *f; + int mnd_max = BIT(rcg->mnd_width) - 1; + int hid_max = BIT(rcg->hid_width) - 1; + struct clk_hw *parent; + u64 parent_rate; + + parent = clk_hw_get_parent(hw); + parent_rate = clk_get_rate(parent->clk); + if (!parent_rate) + return -EINVAL; + + f = kzalloc(sizeof(*f), GFP_KERNEL); + + if (!f) + return -ENOMEM; + + clk_rcg2_calc_mnd(parent_rate, req->rate, f, mnd_max, hid_max / 2); + convert_to_reg_val(f); + req->rate = calc_rate(parent_rate, f->m, f->n, f->n, f->pre_div); + + kfree(f); + + return 0; +} + +static int __clk_rcg2_configure_parent(struct clk_rcg2 *rcg, u8 src, u32 *_cfg) { - u32 cfg, mask, d_val, not2d_val, n_minus_m; struct clk_hw *hw = &rcg->clkr.hw; - int ret, index = qcom_find_src_index(hw, rcg->parent_map, f->src); + u32 mask = CFG_SRC_SEL_MASK; + int index = qcom_find_src_index(hw, rcg->parent_map, src); if (index < 0) return index; + *_cfg &= ~mask; + *_cfg |= rcg->parent_map[index].cfg << CFG_SRC_SEL_SHIFT; + + return 0; +} + +static int __clk_rcg2_configure_mnd(struct clk_rcg2 *rcg, const struct freq_tbl *f, + u32 *_cfg) +{ + u32 cfg, mask, d_val, not2d_val, n_minus_m; + int ret; + if (rcg->mnd_width && f->n) { mask = BIT(rcg->mnd_width) - 1; ret = regmap_update_bits(rcg->clkr.regmap, @@ -438,9 +549,8 @@ static int __clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f, } mask = BIT(rcg->hid_width) - 1; - mask |= CFG_SRC_SEL_MASK | CFG_MODE_MASK | CFG_HW_CLK_CTRL_MASK; + mask |= CFG_MODE_MASK | CFG_HW_CLK_CTRL_MASK; cfg = f->pre_div << CFG_SRC_DIV_SHIFT; - cfg |= rcg->parent_map[index].cfg << CFG_SRC_SEL_SHIFT; if (rcg->mnd_width && f->n && (f->m != f->n)) cfg |= CFG_MODE_DUAL_EDGE; if (rcg->hw_clk_ctrl) @@ -452,6 +562,22 @@ static int __clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f, return 0; } +static int __clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f, + u32 *_cfg) +{ + int ret; + + ret = __clk_rcg2_configure_parent(rcg, f->src, _cfg); + if (ret) + return ret; + + ret = __clk_rcg2_configure_mnd(rcg, f, _cfg); + if (ret) + return ret; + + return 0; +} + static int clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f) { u32 cfg; @@ -472,6 +598,26 @@ static int clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f) return update_config(rcg); } +static int clk_rcg2_configure_gp(struct clk_rcg2 *rcg, const struct freq_tbl *f) +{ + u32 cfg; + int ret; + + ret = regmap_read(rcg->clkr.regmap, RCG_CFG_OFFSET(rcg), &cfg); + if (ret) + return ret; + + ret = __clk_rcg2_configure_mnd(rcg, f, &cfg); + if (ret) + return ret; + + ret = regmap_write(rcg->clkr.regmap, RCG_CFG_OFFSET(rcg), cfg); + if (ret) + return ret; + + return update_config(rcg); +} + static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate, enum freq_policy policy) { @@ -525,6 +671,28 @@ static int clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate, return __clk_rcg2_set_rate(hw, rate, CEIL); } +static int clk_rcg2_set_gp_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_rcg2 *rcg = to_clk_rcg2(hw); + int mnd_max = BIT(rcg->mnd_width) - 1; + int hid_max = BIT(rcg->hid_width) - 1; + struct freq_tbl *f; + int ret; + + f = kzalloc(sizeof(*f), GFP_KERNEL); + + if (!f) + return -ENOMEM; + + clk_rcg2_calc_mnd(parent_rate, rate, f, mnd_max, hid_max / 2); + convert_to_reg_val(f); + ret = clk_rcg2_configure_gp(rcg, f); + kfree(f); + + return ret; +} + static int clk_rcg2_set_floor_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { @@ -652,6 +820,18 @@ const struct clk_ops clk_rcg2_ops = { }; EXPORT_SYMBOL_GPL(clk_rcg2_ops); +const struct clk_ops clk_rcg2_gp_ops = { + .is_enabled = clk_rcg2_is_enabled, + .get_parent = clk_rcg2_get_parent, + .set_parent = clk_rcg2_set_parent, + .recalc_rate = clk_rcg2_recalc_rate, + .determine_rate = clk_rcg2_determine_gp_rate, + .set_rate = clk_rcg2_set_gp_rate, + .get_duty_cycle = clk_rcg2_get_duty_cycle, + .set_duty_cycle = clk_rcg2_set_duty_cycle, +}; +EXPORT_SYMBOL_GPL(clk_rcg2_gp_ops); + const struct clk_ops clk_rcg2_floor_ops = { .is_enabled = clk_rcg2_is_enabled, .get_parent = clk_rcg2_get_parent, diff --git a/drivers/clk/qcom/gcc-sdm845.c b/drivers/clk/qcom/gcc-sdm845.c index dc3aa7014c3e..0def0fc0e009 100644 --- a/drivers/clk/qcom/gcc-sdm845.c +++ b/drivers/clk/qcom/gcc-sdm845.c @@ -284,11 +284,6 @@ static struct clk_rcg2 gcc_sdm670_cpuss_rbcpr_clk_src = { }; static const struct freq_tbl ftbl_gcc_gp1_clk_src[] = { - F(19200000, P_BI_TCXO, 1, 0, 0), - F(25000000, P_GPLL0_OUT_EVEN, 12, 0, 0), - F(50000000, P_GPLL0_OUT_EVEN, 6, 0, 0), - F(100000000, P_GPLL0_OUT_MAIN, 6, 0, 0), - F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0), { } }; @@ -302,7 +297,7 @@ static struct clk_rcg2 gcc_gp1_clk_src = { .name = "gcc_gp1_clk_src", .parent_data = gcc_parent_data_1, .num_parents = ARRAY_SIZE(gcc_parent_data_1), - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_gp_ops, }, }; @@ -316,7 +311,7 @@ static struct clk_rcg2 gcc_gp2_clk_src = { .name = "gcc_gp2_clk_src", .parent_data = gcc_parent_data_1, .num_parents = ARRAY_SIZE(gcc_parent_data_1), - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_gp_ops, }, }; @@ -330,7 +325,7 @@ static struct clk_rcg2 gcc_gp3_clk_src = { .name = "gcc_gp3_clk_src", .parent_data = gcc_parent_data_1, .num_parents = ARRAY_SIZE(gcc_parent_data_1), - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_gp_ops, }, };