* [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.