Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754405AbbDHTcl (ORCPT ); Wed, 8 Apr 2015 15:32:41 -0400 Received: from arrakis.dune.hu ([78.24.191.176]:55545 "EHLO arrakis.dune.hu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752083AbbDHTcj (ORCPT ); Wed, 8 Apr 2015 15:32:39 -0400 MIME-Version: 1.0 In-Reply-To: <1428516275-12819-6-git-send-email-jonathar@broadcom.com> References: <1428516275-12819-1-git-send-email-jonathar@broadcom.com> <1428516275-12819-6-git-send-email-jonathar@broadcom.com> From: Jonas Gorski Date: Wed, 8 Apr 2015 21:32:09 +0200 Message-ID: Subject: Re: [PATCH v2 5/5] spi: bcm-mspi: Add support to set serial baud clock rate To: Jonathan Richardson Cc: Mark Brown , Dmitry Torokhov , Anatol Pomazau , Scott Branden , Rob Herring , Pawel Moll , Mark Rutland , Ian Campbell , Kumar Gala , "linux-kernel@vger.kernel.org" , linux-spi@vger.kernel.org, bcm-kernel-feedback-list , "devicetree@vger.kernel.org" , Rafal Milecki Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 4753 Lines: 134 Hi, On Wed, Apr 8, 2015 at 8:04 PM, Jonathan Richardson wrote: > The driver wasn't setting the SPBR (serial clock baud rate) which caused > it to run at the slowest speed possible. The driver now calculates the > SPBR based on the reference clock frequency resulting in much faster > SPI transfers. > > Signed-off-by: Jonathan Richardson > --- > drivers/spi/spi-bcm-mspi.c | 50 ++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 50 insertions(+) > > diff --git a/drivers/spi/spi-bcm-mspi.c b/drivers/spi/spi-bcm-mspi.c > index 32bb1f0..9320de9 100644 > --- a/drivers/spi/spi-bcm-mspi.c > +++ b/drivers/spi/spi-bcm-mspi.c > @@ -18,10 +18,15 @@ > #include > #include > #include > +#include > > #include "spi-bcm-mspi.h" > > #define BCM_MSPI_MAX_SPI_BAUD 13500000 /* 216 MHz? */ > +#define SPBR_MIN 8U > +#define SPBR_MAX 255U > +#define MSPI_SPCR0_LSB_OFFSET 0x200 > +#define MSPI_SPCR0_LSB_SHIFT 0 > > /* The longest observed required wait was 19 ms */ > #define BCM_MSPI_SPE_TIMEOUT_MS 80 > @@ -33,7 +38,9 @@ struct bcm_mspi { > > void __iomem *base; > struct spi_master *master; > + struct clk *clk; > size_t read_offset; > + u32 spbr; > > void (*mspi_write)(struct bcm_mspi *mspi, u16 offset, u32 value); > u32 (*mspi_read)(struct bcm_mspi *mspi, u16 offset); > @@ -45,6 +52,15 @@ static inline unsigned int bcm_mspi_calc_timeout(size_t len) > return (len * 9000 / BCM_MSPI_MAX_SPI_BAUD * 110 / 100) + 1; > } > > +static void bcm_mspi_hw_init(struct bcm_mspi *mspi) > +{ > + /* Set SPBR (serial clock baud rate). */ > + if (mspi->spbr) { > + mspi->mspi_write(mspi, MSPI_SPCR0_LSB_OFFSET, > + mspi->spbr << MSPI_SPCR0_LSB_SHIFT); > + } > +} > + > static int bcm_mspi_wait(struct bcm_mspi *mspi, unsigned int timeout_ms) > { > unsigned long deadline; > @@ -222,6 +238,7 @@ static struct bcm_mspi *bcm_mspi_init(struct device *dev) > { > struct bcm_mspi *data; > struct spi_master *master; > + u32 desired_rate; > > master = spi_alloc_master(dev, sizeof(*data)); > if (!master) { > @@ -236,6 +253,33 @@ static struct bcm_mspi *bcm_mspi_init(struct device *dev) > master->dev.of_node = dev->of_node; > master->transfer_one = bcm_mspi_transfer_one; > > + /* > + * Enable clock if provided. The frequency can be changed by setting > + * SPBR (serial clock baud rate) based on the desired 'clock-frequency'. > + * > + * Baud rate is calculated as: mspi_clk / (2 * SPBR) where SPBR is a > + * value between 1-255. If not set then it is left at the h/w default. > + */ > + data->clk = devm_clk_get(dev, "mspi_clk"); > + if (!IS_ERR(data->clk)) { > + int ret = clk_prepare_enable(data->clk); You need to disable_unprepare the clock on removal, I don't see you doing that. > + > + if (ret < 0) { > + dev_err(dev, "failed to enable clock: %d\n", ret); > + return 0; > + } > + > + /* Calculate SPBR if clock-frequency provided. */ > + if (of_property_read_u32(dev->of_node, "clock-frequency", > + &desired_rate) >= 0) { > + u32 spbr = clk_get_rate(data->clk) / (2 * desired_rate); > + > + if (spbr > 0) > + data->spbr = clamp_val(spbr, SPBR_MIN, > + SPBR_MAX); > + } > + } > + > return data; > } > > @@ -287,6 +331,9 @@ static int bcm_mspi_probe(struct platform_device *pdev) > data->mspi_write = bcm_mspi_write; > platform_set_drvdata(pdev, data); > > + /* Initialize SPI controller. */ > + bcm_mspi_hw_init(data); > + > err = devm_spi_register_master(dev, data->master); > if (err) > goto out; > @@ -362,6 +409,9 @@ static int bcm_mspi_bcma_probe(struct bcma_device *core) > > bcma_set_drvdata(core, data); > > + /* Initialize SPI controller. */ > + bcm_mspi_hw_init(data); > + > err = devm_spi_register_master(&core->dev, data->master); > if (err) { > spi_master_put(data->master); > -- Regards Jonas -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/