All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 2/2] SPI: S3C64XX: Consider the clk_from_cmu flag
@ 2010-09-09  7:19 Jassi Brar
       [not found] ` <1284016744-21655-1-git-send-email-jassi.brar-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
  0 siblings, 1 reply; 2+ messages in thread
From: Jassi Brar @ 2010-09-09  7:19 UTC (permalink / raw)
  To: grant.likely-s3s/WqlpOiPyB63q8FvJNQ,
	dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f
  Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	broonie-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E

Newer SoCs have the SPI clock scaling control in platform's
clock management unit. Inorder for such SoCs to work, we need
to check the flag clk_from_cmu before making any clock changes.

Signed-off-by: Jassi Brar <jassi.brar-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
---
 arch/arm/plat-samsung/include/plat/s3c64xx-spi.h |    3 +
 drivers/spi/spi_s3c64xx.c                        |   94 +++++++++++++---------
 2 files changed, 59 insertions(+), 38 deletions(-)

diff --git a/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h b/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h
index 55852f4..76fce2a 100644
--- a/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h
+++ b/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h
@@ -32,6 +32,8 @@ struct s3c64xx_spi_csinfo {
  * struct s3c64xx_spi_info - SPI Controller defining structure
  * @src_clk_nr: Clock source index for the CLK_CFG[SPI_CLKSEL] field.
  * @src_clk_name: Platform name of the corresponding clock.
+ * @clk_from_cmu: If the SPI clock/prescalar control block is present
+ *     by the platform's clock-management-unit and not in SPI controller.
  * @num_cs: Number of CS this controller emulates.
  * @cfg_gpio: Configure pins for this SPI controller.
  * @fifo_lvl_mask: All tx fifo_lvl fields start at offset-6
@@ -41,6 +43,7 @@ struct s3c64xx_spi_csinfo {
 struct s3c64xx_spi_info {
 	int src_clk_nr;
 	char *src_clk_name;
+	bool clk_from_cmu;
 
 	int num_cs;
 
diff --git a/drivers/spi/spi_s3c64xx.c b/drivers/spi/spi_s3c64xx.c
index 3ff335d..9343351 100644
--- a/drivers/spi/spi_s3c64xx.c
+++ b/drivers/spi/spi_s3c64xx.c
@@ -429,13 +429,18 @@ static inline void disable_cs(struct s3c64xx_spi_driver_data *sdd,
 
 static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
 {
+	struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
 	void __iomem *regs = sdd->regs;
 	u32 val;
 
 	/* Disable Clock */
-	val = readl(regs + S3C64XX_SPI_CLK_CFG);
-	val &= ~S3C64XX_SPI_ENCLK_ENABLE;
-	writel(val, regs + S3C64XX_SPI_CLK_CFG);
+	if (sci->clk_from_cmu) {
+		clk_disable(sdd->src_clk);
+	} else {
+		val = readl(regs + S3C64XX_SPI_CLK_CFG);
+		val &= ~S3C64XX_SPI_ENCLK_ENABLE;
+		writel(val, regs + S3C64XX_SPI_CLK_CFG);
+	}
 
 	/* Set Polarity and Phase */
 	val = readl(regs + S3C64XX_SPI_CH_CFG);
@@ -473,17 +478,25 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
 
 	writel(val, regs + S3C64XX_SPI_MODE_CFG);
 
-	/* Configure Clock */
-	val = readl(regs + S3C64XX_SPI_CLK_CFG);
-	val &= ~S3C64XX_SPI_PSR_MASK;
-	val |= ((clk_get_rate(sdd->src_clk) / sdd->cur_speed / 2 - 1)
-			& S3C64XX_SPI_PSR_MASK);
-	writel(val, regs + S3C64XX_SPI_CLK_CFG);
-
-	/* Enable Clock */
-	val = readl(regs + S3C64XX_SPI_CLK_CFG);
-	val |= S3C64XX_SPI_ENCLK_ENABLE;
-	writel(val, regs + S3C64XX_SPI_CLK_CFG);
+	if (sci->clk_from_cmu) {
+		/* Configure Clock */
+		/* There is half-multiplier before the SPI */
+		clk_set_rate(sdd->src_clk, sdd->cur_speed * 2);
+		/* Enable Clock */
+		clk_enable(sdd->src_clk);
+	} else {
+		/* Configure Clock */
+		val = readl(regs + S3C64XX_SPI_CLK_CFG);
+		val &= ~S3C64XX_SPI_PSR_MASK;
+		val |= ((clk_get_rate(sdd->src_clk) / sdd->cur_speed / 2 - 1)
+				& S3C64XX_SPI_PSR_MASK);
+		writel(val, regs + S3C64XX_SPI_CLK_CFG);
+
+		/* Enable Clock */
+		val = readl(regs + S3C64XX_SPI_CLK_CFG);
+		val |= S3C64XX_SPI_ENCLK_ENABLE;
+		writel(val, regs + S3C64XX_SPI_CLK_CFG);
+	}
 }
 
 void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id,
@@ -846,7 +859,6 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
 	struct s3c64xx_spi_driver_data *sdd;
 	struct s3c64xx_spi_info *sci;
 	struct spi_message *msg;
-	u32 psr, speed;
 	unsigned long flags;
 	int err = 0;
 
@@ -889,32 +901,37 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
 	}
 
 	/* Check if we can provide the requested rate */
-	speed = clk_get_rate(sdd->src_clk) / 2 / (0 + 1); /* Max possible */
-
-	if (spi->max_speed_hz > speed)
-		spi->max_speed_hz = speed;
-
-	psr = clk_get_rate(sdd->src_clk) / 2 / spi->max_speed_hz - 1;
-	psr &= S3C64XX_SPI_PSR_MASK;
-	if (psr == S3C64XX_SPI_PSR_MASK)
-		psr--;
+	if (!sci->clk_from_cmu) {
+		u32 psr, speed;
+
+		/* Max possible */
+		speed = clk_get_rate(sdd->src_clk) / 2 / (0 + 1);
+
+		if (spi->max_speed_hz > speed)
+			spi->max_speed_hz = speed;
+
+		psr = clk_get_rate(sdd->src_clk) / 2 / spi->max_speed_hz - 1;
+		psr &= S3C64XX_SPI_PSR_MASK;
+		if (psr == S3C64XX_SPI_PSR_MASK)
+			psr--;
+
+		speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1);
+		if (spi->max_speed_hz < speed) {
+			if (psr+1 < S3C64XX_SPI_PSR_MASK) {
+				psr++;
+			} else {
+				err = -EINVAL;
+				goto setup_exit;
+			}
+		}
 
-	speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1);
-	if (spi->max_speed_hz < speed) {
-		if (psr+1 < S3C64XX_SPI_PSR_MASK) {
-			psr++;
-		} else {
+		speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1);
+		if (spi->max_speed_hz >= speed)
+			spi->max_speed_hz = speed;
+		else
 			err = -EINVAL;
-			goto setup_exit;
-		}
 	}
 
-	speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1);
-	if (spi->max_speed_hz >= speed)
-		spi->max_speed_hz = speed;
-	else
-		err = -EINVAL;
-
 setup_exit:
 
 	/* setup() returns with device de-selected */
@@ -936,7 +953,8 @@ static void s3c64xx_spi_hwinit(struct s3c64xx_spi_driver_data *sdd, int channel)
 	/* Disable Interrupts - we use Polling if not DMA mode */
 	writel(0, regs + S3C64XX_SPI_INT_EN);
 
-	writel(sci->src_clk_nr << S3C64XX_SPI_CLKSEL_SRCSHFT,
+	if (!sci->clk_from_cmu)
+		writel(sci->src_clk_nr << S3C64XX_SPI_CLKSEL_SRCSHFT,
 				regs + S3C64XX_SPI_CLK_CFG);
 	writel(0, regs + S3C64XX_SPI_MODE_CFG);
 	writel(0, regs + S3C64XX_SPI_PACKET_CNT);
-- 
1.6.2.5


------------------------------------------------------------------------------
This SF.net Dev2Dev email is sponsored by:

Show off your parallel programming skills.
Enter the Intel(R) Threading Challenge 2010.
http://p.sf.net/sfu/intel-thread-sfd

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH 2/2] SPI: S3C64XX: Consider the clk_from_cmu flag
       [not found] ` <1284016744-21655-1-git-send-email-jassi.brar-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
@ 2010-09-09 14:53   ` Grant Likely
  0 siblings, 0 replies; 2+ messages in thread
From: Grant Likely @ 2010-09-09 14:53 UTC (permalink / raw)
  To: Jassi Brar
  Cc: spi-devel-general-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f,
	dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f,
	broonie-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E

On Thu, Sep 09, 2010 at 04:19:04PM +0900, Jassi Brar wrote:
> Newer SoCs have the SPI clock scaling control in platform's
> clock management unit. Inorder for such SoCs to work, we need
> to check the flag clk_from_cmu before making any clock changes.
> 
> Signed-off-by: Jassi Brar <jassi.brar-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>

Thanks, applied.

g.

> ---
>  arch/arm/plat-samsung/include/plat/s3c64xx-spi.h |    3 +
>  drivers/spi/spi_s3c64xx.c                        |   94 +++++++++++++---------
>  2 files changed, 59 insertions(+), 38 deletions(-)
> 
> diff --git a/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h b/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h
> index 55852f4..76fce2a 100644
> --- a/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h
> +++ b/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h
> @@ -32,6 +32,8 @@ struct s3c64xx_spi_csinfo {
>   * struct s3c64xx_spi_info - SPI Controller defining structure
>   * @src_clk_nr: Clock source index for the CLK_CFG[SPI_CLKSEL] field.
>   * @src_clk_name: Platform name of the corresponding clock.
> + * @clk_from_cmu: If the SPI clock/prescalar control block is present
> + *     by the platform's clock-management-unit and not in SPI controller.
>   * @num_cs: Number of CS this controller emulates.
>   * @cfg_gpio: Configure pins for this SPI controller.
>   * @fifo_lvl_mask: All tx fifo_lvl fields start at offset-6
> @@ -41,6 +43,7 @@ struct s3c64xx_spi_csinfo {
>  struct s3c64xx_spi_info {
>  	int src_clk_nr;
>  	char *src_clk_name;
> +	bool clk_from_cmu;
>  
>  	int num_cs;
>  
> diff --git a/drivers/spi/spi_s3c64xx.c b/drivers/spi/spi_s3c64xx.c
> index 3ff335d..9343351 100644
> --- a/drivers/spi/spi_s3c64xx.c
> +++ b/drivers/spi/spi_s3c64xx.c
> @@ -429,13 +429,18 @@ static inline void disable_cs(struct s3c64xx_spi_driver_data *sdd,
>  
>  static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
>  {
> +	struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
>  	void __iomem *regs = sdd->regs;
>  	u32 val;
>  
>  	/* Disable Clock */
> -	val = readl(regs + S3C64XX_SPI_CLK_CFG);
> -	val &= ~S3C64XX_SPI_ENCLK_ENABLE;
> -	writel(val, regs + S3C64XX_SPI_CLK_CFG);
> +	if (sci->clk_from_cmu) {
> +		clk_disable(sdd->src_clk);
> +	} else {
> +		val = readl(regs + S3C64XX_SPI_CLK_CFG);
> +		val &= ~S3C64XX_SPI_ENCLK_ENABLE;
> +		writel(val, regs + S3C64XX_SPI_CLK_CFG);
> +	}
>  
>  	/* Set Polarity and Phase */
>  	val = readl(regs + S3C64XX_SPI_CH_CFG);
> @@ -473,17 +478,25 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
>  
>  	writel(val, regs + S3C64XX_SPI_MODE_CFG);
>  
> -	/* Configure Clock */
> -	val = readl(regs + S3C64XX_SPI_CLK_CFG);
> -	val &= ~S3C64XX_SPI_PSR_MASK;
> -	val |= ((clk_get_rate(sdd->src_clk) / sdd->cur_speed / 2 - 1)
> -			& S3C64XX_SPI_PSR_MASK);
> -	writel(val, regs + S3C64XX_SPI_CLK_CFG);
> -
> -	/* Enable Clock */
> -	val = readl(regs + S3C64XX_SPI_CLK_CFG);
> -	val |= S3C64XX_SPI_ENCLK_ENABLE;
> -	writel(val, regs + S3C64XX_SPI_CLK_CFG);
> +	if (sci->clk_from_cmu) {
> +		/* Configure Clock */
> +		/* There is half-multiplier before the SPI */
> +		clk_set_rate(sdd->src_clk, sdd->cur_speed * 2);
> +		/* Enable Clock */
> +		clk_enable(sdd->src_clk);
> +	} else {
> +		/* Configure Clock */
> +		val = readl(regs + S3C64XX_SPI_CLK_CFG);
> +		val &= ~S3C64XX_SPI_PSR_MASK;
> +		val |= ((clk_get_rate(sdd->src_clk) / sdd->cur_speed / 2 - 1)
> +				& S3C64XX_SPI_PSR_MASK);
> +		writel(val, regs + S3C64XX_SPI_CLK_CFG);
> +
> +		/* Enable Clock */
> +		val = readl(regs + S3C64XX_SPI_CLK_CFG);
> +		val |= S3C64XX_SPI_ENCLK_ENABLE;
> +		writel(val, regs + S3C64XX_SPI_CLK_CFG);
> +	}
>  }
>  
>  void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id,
> @@ -846,7 +859,6 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
>  	struct s3c64xx_spi_driver_data *sdd;
>  	struct s3c64xx_spi_info *sci;
>  	struct spi_message *msg;
> -	u32 psr, speed;
>  	unsigned long flags;
>  	int err = 0;
>  
> @@ -889,32 +901,37 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
>  	}
>  
>  	/* Check if we can provide the requested rate */
> -	speed = clk_get_rate(sdd->src_clk) / 2 / (0 + 1); /* Max possible */
> -
> -	if (spi->max_speed_hz > speed)
> -		spi->max_speed_hz = speed;
> -
> -	psr = clk_get_rate(sdd->src_clk) / 2 / spi->max_speed_hz - 1;
> -	psr &= S3C64XX_SPI_PSR_MASK;
> -	if (psr == S3C64XX_SPI_PSR_MASK)
> -		psr--;
> +	if (!sci->clk_from_cmu) {
> +		u32 psr, speed;
> +
> +		/* Max possible */
> +		speed = clk_get_rate(sdd->src_clk) / 2 / (0 + 1);
> +
> +		if (spi->max_speed_hz > speed)
> +			spi->max_speed_hz = speed;
> +
> +		psr = clk_get_rate(sdd->src_clk) / 2 / spi->max_speed_hz - 1;
> +		psr &= S3C64XX_SPI_PSR_MASK;
> +		if (psr == S3C64XX_SPI_PSR_MASK)
> +			psr--;
> +
> +		speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1);
> +		if (spi->max_speed_hz < speed) {
> +			if (psr+1 < S3C64XX_SPI_PSR_MASK) {
> +				psr++;
> +			} else {
> +				err = -EINVAL;
> +				goto setup_exit;
> +			}
> +		}
>  
> -	speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1);
> -	if (spi->max_speed_hz < speed) {
> -		if (psr+1 < S3C64XX_SPI_PSR_MASK) {
> -			psr++;
> -		} else {
> +		speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1);
> +		if (spi->max_speed_hz >= speed)
> +			spi->max_speed_hz = speed;
> +		else
>  			err = -EINVAL;
> -			goto setup_exit;
> -		}
>  	}
>  
> -	speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1);
> -	if (spi->max_speed_hz >= speed)
> -		spi->max_speed_hz = speed;
> -	else
> -		err = -EINVAL;
> -
>  setup_exit:
>  
>  	/* setup() returns with device de-selected */
> @@ -936,7 +953,8 @@ static void s3c64xx_spi_hwinit(struct s3c64xx_spi_driver_data *sdd, int channel)
>  	/* Disable Interrupts - we use Polling if not DMA mode */
>  	writel(0, regs + S3C64XX_SPI_INT_EN);
>  
> -	writel(sci->src_clk_nr << S3C64XX_SPI_CLKSEL_SRCSHFT,
> +	if (!sci->clk_from_cmu)
> +		writel(sci->src_clk_nr << S3C64XX_SPI_CLKSEL_SRCSHFT,
>  				regs + S3C64XX_SPI_CLK_CFG);
>  	writel(0, regs + S3C64XX_SPI_MODE_CFG);
>  	writel(0, regs + S3C64XX_SPI_PACKET_CNT);
> -- 
> 1.6.2.5
> 

------------------------------------------------------------------------------
This SF.net Dev2Dev email is sponsored by:

Show off your parallel programming skills.
Enter the Intel(R) Threading Challenge 2010.
http://p.sf.net/sfu/intel-thread-sfd

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2010-09-09 14:53 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-09-09  7:19 [PATCH 2/2] SPI: S3C64XX: Consider the clk_from_cmu flag Jassi Brar
     [not found] ` <1284016744-21655-1-git-send-email-jassi.brar-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2010-09-09 14:53   ` Grant Likely

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.