Received: by 2002:a05:6358:9144:b0:117:f937:c515 with SMTP id r4csp2600076rwr; Sat, 6 May 2023 15:03:58 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ5IH79JDjRRaQCVwMfB3/mmfcfGCi2YwD932aJ9OLTVIRHtPzjqiDyEvfzVBAgjFX/huGT5 X-Received: by 2002:a17:90b:3757:b0:247:afed:6d62 with SMTP id ne23-20020a17090b375700b00247afed6d62mr5653495pjb.46.1683410637783; Sat, 06 May 2023 15:03:57 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1683410637; cv=none; d=google.com; s=arc-20160816; b=NXuqDcd7LHhlKE6GNBrf2LMJoOQO6VIdag2Q1xFGRWii7osSNzALSTKvmswyCwTsGt BB+BmFrcGV3wNBLeexzBrOdvZcl2A0mu+CpnIVOvhy4qZdrwtTYl+iRLL47KX0qBr5WP GINigqrhaD9ETJVHTKdiRrZ/SvKHh2UhkjzNvC4wqLqZBe3XAWcsLj9YkGLJENSt0/va R+XvGkwN9t2x034roKvr2v8y3b0FxpwZ4Xb49dQ4NFC/ZY12FkEcgFJFQ3PfDyLPnGG2 UUcUO/8XwUm4tga1mwBIyYau+IB/NwSYb0831SdytMqIMFIp1VwIkdOB2KSmCDOSaltv Sp9g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :organization:references:in-reply-to:message-id:subject:cc:to:from :date; bh=9JPu2XjadhC27hqmoTFrZFU2ZHnNM1osfoEH40B5Dxg=; b=ru6mA94pl2xWFDPurQ9Cj0F569Qh/VyGFs6jypit1Tn7yRgUiPqkCIkLmsM+9l77+F sqD/y5PuQ8uMDymbmHhvsq+3t5VkNqGvDIQ5uZ0p82rmEoh+RU1rBtZ30OE0YsYnvMS5 AjfbNvonQ5slKDyUY0tLm6C/XHaZJRwVm7PqCIH5ISVEKUeIVYxwKX5Xgz1PIaeExAH2 BVruP49Q6HQ+31jKVBpADR6OFWOYU1L+vC+raG4OCHbl8tjCi9hCJ4aql6fou2sAjgi7 gRhx0w0yAtSsQrwJ9cEBEs2Kjt6A5IdPo8DxXGuS/EMmrhWuVlH+ELKD3n7R8woQwPNK ggjA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id mz7-20020a17090b378700b0024e0eec665fsi9512350pjb.73.2023.05.06.15.03.43; Sat, 06 May 2023 15:03:57 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229707AbjEFV7O (ORCPT + 99 others); Sat, 6 May 2023 17:59:14 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51412 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229628AbjEFV7N (ORCPT ); Sat, 6 May 2023 17:59:13 -0400 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 187D421572; Sat, 6 May 2023 14:59:06 -0700 (PDT) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 35B8E1FB; Sat, 6 May 2023 14:59:50 -0700 (PDT) Received: from slackpad.lan (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 990333F5A1; Sat, 6 May 2023 14:59:02 -0700 (PDT) Date: Sat, 6 May 2023 22:58:48 +0100 From: Andre Przywara To: Maksim Kiselev Cc: Icenowy Zheng , Mark Brown , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Paul Walmsley , Palmer Dabbelt , Albert Ou , Cristian Ciocaltea , Heiko Stuebner , Maxime Ripard , linux-spi@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, linux-riscv@lists.infradead.org Subject: Re: [PATCH v2 3/6] spi: sun6i: add quirk for in-controller clock divider Message-ID: <20230506225848.3278d7ab@slackpad.lan> In-Reply-To: <20230506073018.1411583-4-bigunclemax@gmail.com> References: <20230506073018.1411583-1-bigunclemax@gmail.com> <20230506073018.1411583-4-bigunclemax@gmail.com> Organization: Arm Ltd. X-Mailer: Claws Mail 4.1.0 (GTK 3.24.31; x86_64-slackware-linux-gnu) MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_MED, SPF_HELO_NONE,SPF_NONE,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Sat, 6 May 2023 10:30:11 +0300 Maksim Kiselev wrote: > From: Icenowy Zheng > > Previously SPI controllers in Allwinner SoCs has a clock divider inside. > However now the clock divider is removed and to set the transfer clock > rate it's only needed to set the SPI module clock to the target value. > > Add a quirk for this kind of SPI controllers. > > Signed-off-by: Icenowy Zheng > --- > drivers/spi/spi-sun6i.c | 68 +++++++++++++++++++++++------------------ > 1 file changed, 38 insertions(+), 30 deletions(-) > > diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c > index 01a01cd86db5..82523011a3a5 100644 > --- a/drivers/spi/spi-sun6i.c > +++ b/drivers/spi/spi-sun6i.c > @@ -87,6 +87,7 @@ > > struct sun6i_spi_cfg { > unsigned long fifo_depth; > + bool has_clk_ctl; > }; > > struct sun6i_spi { > @@ -260,7 +261,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master, > struct spi_transfer *tfr) > { > struct sun6i_spi *sspi = spi_master_get_devdata(master); > - unsigned int mclk_rate, div, div_cdr1, div_cdr2, timeout; > + unsigned int div, div_cdr1, div_cdr2, timeout; > unsigned int start, end, tx_time; > unsigned int trig_level; > unsigned int tx_len = 0, rx_len = 0; > @@ -350,39 +351,44 @@ static int sun6i_spi_transfer_one(struct spi_master *master, > > sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg); > > - /* Ensure that we have a parent clock fast enough */ > - mclk_rate = clk_get_rate(sspi->mclk); > - if (mclk_rate < (2 * tfr->speed_hz)) { > - clk_set_rate(sspi->mclk, 2 * tfr->speed_hz); > - mclk_rate = clk_get_rate(sspi->mclk); > - } > + if (sspi->cfg->has_clk_ctl) { > + unsigned int mclk_rate = clk_get_rate(sspi->mclk); New line here please, to separate variable declaration from code. > + /* Ensure that we have a parent clock fast enough */ > + if (mclk_rate < (2 * tfr->speed_hz)) { > + clk_set_rate(sspi->mclk, 2 * tfr->speed_hz); > + mclk_rate = clk_get_rate(sspi->mclk); > + } > > - /* > - * Setup clock divider. > - * > - * We have two choices there. Either we can use the clock > - * divide rate 1, which is calculated thanks to this formula: > - * SPI_CLK = MOD_CLK / (2 ^ cdr) > - * Or we can use CDR2, which is calculated with the formula: > - * SPI_CLK = MOD_CLK / (2 * (cdr + 1)) > - * Wether we use the former or the latter is set through the > - * DRS bit. > - * > - * First try CDR2, and if we can't reach the expected > - * frequency, fall back to CDR1. > - */ > - div_cdr1 = DIV_ROUND_UP(mclk_rate, tfr->speed_hz); > - div_cdr2 = DIV_ROUND_UP(div_cdr1, 2); > - if (div_cdr2 <= (SUN6I_CLK_CTL_CDR2_MASK + 1)) { > - reg = SUN6I_CLK_CTL_CDR2(div_cdr2 - 1) | SUN6I_CLK_CTL_DRS; > - tfr->effective_speed_hz = mclk_rate / (2 * div_cdr2); > + /* > + * Setup clock divider. > + * > + * We have two choices there. Either we can use the clock > + * divide rate 1, which is calculated thanks to this formula: > + * SPI_CLK = MOD_CLK / (2 ^ cdr) > + * Or we can use CDR2, which is calculated with the formula: > + * SPI_CLK = MOD_CLK / (2 * (cdr + 1)) > + * Wether we use the former or the latter is set through the > + * DRS bit. > + * > + * First try CDR2, and if we can't reach the expected > + * frequency, fall back to CDR1. > + */ > + div_cdr1 = DIV_ROUND_UP(mclk_rate, tfr->speed_hz); > + div_cdr2 = DIV_ROUND_UP(div_cdr1, 2); > + if (div_cdr2 <= (SUN6I_CLK_CTL_CDR2_MASK + 1)) { > + reg = SUN6I_CLK_CTL_CDR2(div_cdr2 - 1) | SUN6I_CLK_CTL_DRS; > + tfr->effective_speed_hz = mclk_rate / (2 * div_cdr2); > + } else { > + div = min(SUN6I_CLK_CTL_CDR1_MASK, order_base_2(div_cdr1)); > + reg = SUN6I_CLK_CTL_CDR1(div); > + tfr->effective_speed_hz = mclk_rate / (1 << div); > + } > + > + sun6i_spi_write(sspi, SUN6I_CLK_CTL_REG, reg); > } else { > - div = min(SUN6I_CLK_CTL_CDR1_MASK, order_base_2(div_cdr1)); > - reg = SUN6I_CLK_CTL_CDR1(div); > - tfr->effective_speed_hz = mclk_rate / (1 << div); > + clk_set_rate(sspi->mclk, tfr->speed_hz); Don't we need to set tfr->effective_speed_hz to the actually programmed clock rate here? The rest looks fine, it's really mostly that old block indented. Cheers, Andre > } > > - sun6i_spi_write(sspi, SUN6I_CLK_CTL_REG, reg); > /* Finally enable the bus - doing so before might raise SCK to HIGH */ > reg = sun6i_spi_read(sspi, SUN6I_GBL_CTL_REG); > reg |= SUN6I_GBL_CTL_BUS_ENABLE; > @@ -701,10 +707,12 @@ static void sun6i_spi_remove(struct platform_device *pdev) > > static const struct sun6i_spi_cfg sun6i_a31_spi_cfg = { > .fifo_depth = SUN6I_FIFO_DEPTH, > + .has_clk_ctl = true, > }; > > static const struct sun6i_spi_cfg sun8i_h3_spi_cfg = { > .fifo_depth = SUN8I_FIFO_DEPTH, > + .has_clk_ctl = true, > }; > > static const struct of_device_id sun6i_spi_match[] = {