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 <[email protected]>
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
_______________________________________________
spi-devel-general mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/spi-devel-general