spi/s3c64xx: Consider the clk_from_cmu flag
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@samsung.com> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
This commit is contained in:
parent
e02ddd442a
commit
b42a81ca0f
|
@ -32,6 +32,8 @@ struct s3c64xx_spi_csinfo {
|
||||||
* struct s3c64xx_spi_info - SPI Controller defining structure
|
* struct s3c64xx_spi_info - SPI Controller defining structure
|
||||||
* @src_clk_nr: Clock source index for the CLK_CFG[SPI_CLKSEL] field.
|
* @src_clk_nr: Clock source index for the CLK_CFG[SPI_CLKSEL] field.
|
||||||
* @src_clk_name: Platform name of the corresponding clock.
|
* @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.
|
* @num_cs: Number of CS this controller emulates.
|
||||||
* @cfg_gpio: Configure pins for this SPI controller.
|
* @cfg_gpio: Configure pins for this SPI controller.
|
||||||
* @fifo_lvl_mask: All tx fifo_lvl fields start at offset-6
|
* @fifo_lvl_mask: All tx fifo_lvl fields start at offset-6
|
||||||
|
@ -41,6 +43,7 @@ struct s3c64xx_spi_csinfo {
|
||||||
struct s3c64xx_spi_info {
|
struct s3c64xx_spi_info {
|
||||||
int src_clk_nr;
|
int src_clk_nr;
|
||||||
char *src_clk_name;
|
char *src_clk_name;
|
||||||
|
bool clk_from_cmu;
|
||||||
|
|
||||||
int num_cs;
|
int num_cs;
|
||||||
|
|
||||||
|
|
|
@ -399,13 +399,18 @@ static inline void disable_cs(struct s3c64xx_spi_driver_data *sdd,
|
||||||
|
|
||||||
static void s3c64xx_spi_config(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;
|
void __iomem *regs = sdd->regs;
|
||||||
u32 val;
|
u32 val;
|
||||||
|
|
||||||
/* Disable Clock */
|
/* Disable Clock */
|
||||||
|
if (sci->clk_from_cmu) {
|
||||||
|
clk_disable(sdd->src_clk);
|
||||||
|
} else {
|
||||||
val = readl(regs + S3C64XX_SPI_CLK_CFG);
|
val = readl(regs + S3C64XX_SPI_CLK_CFG);
|
||||||
val &= ~S3C64XX_SPI_ENCLK_ENABLE;
|
val &= ~S3C64XX_SPI_ENCLK_ENABLE;
|
||||||
writel(val, regs + S3C64XX_SPI_CLK_CFG);
|
writel(val, regs + S3C64XX_SPI_CLK_CFG);
|
||||||
|
}
|
||||||
|
|
||||||
/* Set Polarity and Phase */
|
/* Set Polarity and Phase */
|
||||||
val = readl(regs + S3C64XX_SPI_CH_CFG);
|
val = readl(regs + S3C64XX_SPI_CH_CFG);
|
||||||
|
@ -441,6 +446,13 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
|
||||||
|
|
||||||
writel(val, regs + S3C64XX_SPI_MODE_CFG);
|
writel(val, regs + S3C64XX_SPI_MODE_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 */
|
/* Configure Clock */
|
||||||
val = readl(regs + S3C64XX_SPI_CLK_CFG);
|
val = readl(regs + S3C64XX_SPI_CLK_CFG);
|
||||||
val &= ~S3C64XX_SPI_PSR_MASK;
|
val &= ~S3C64XX_SPI_PSR_MASK;
|
||||||
|
@ -452,6 +464,7 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
|
||||||
val = readl(regs + S3C64XX_SPI_CLK_CFG);
|
val = readl(regs + S3C64XX_SPI_CLK_CFG);
|
||||||
val |= S3C64XX_SPI_ENCLK_ENABLE;
|
val |= S3C64XX_SPI_ENCLK_ENABLE;
|
||||||
writel(val, regs + S3C64XX_SPI_CLK_CFG);
|
writel(val, regs + S3C64XX_SPI_CLK_CFG);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id,
|
static void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id,
|
||||||
|
@ -806,7 +819,6 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
|
||||||
struct s3c64xx_spi_driver_data *sdd;
|
struct s3c64xx_spi_driver_data *sdd;
|
||||||
struct s3c64xx_spi_info *sci;
|
struct s3c64xx_spi_info *sci;
|
||||||
struct spi_message *msg;
|
struct spi_message *msg;
|
||||||
u32 psr, speed;
|
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
|
@ -849,7 +861,11 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if we can provide the requested rate */
|
/* Check if we can provide the requested rate */
|
||||||
speed = clk_get_rate(sdd->src_clk) / 2 / (0 + 1); /* Max possible */
|
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)
|
if (spi->max_speed_hz > speed)
|
||||||
spi->max_speed_hz = speed;
|
spi->max_speed_hz = speed;
|
||||||
|
@ -874,6 +890,7 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
|
||||||
spi->max_speed_hz = speed;
|
spi->max_speed_hz = speed;
|
||||||
else
|
else
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
setup_exit:
|
setup_exit:
|
||||||
|
|
||||||
|
@ -896,6 +913,7 @@ static void s3c64xx_spi_hwinit(struct s3c64xx_spi_driver_data *sdd, int channel)
|
||||||
/* Disable Interrupts - we use Polling if not DMA mode */
|
/* Disable Interrupts - we use Polling if not DMA mode */
|
||||||
writel(0, regs + S3C64XX_SPI_INT_EN);
|
writel(0, regs + S3C64XX_SPI_INT_EN);
|
||||||
|
|
||||||
|
if (!sci->clk_from_cmu)
|
||||||
writel(sci->src_clk_nr << S3C64XX_SPI_CLKSEL_SRCSHFT,
|
writel(sci->src_clk_nr << S3C64XX_SPI_CLKSEL_SRCSHFT,
|
||||||
regs + S3C64XX_SPI_CLK_CFG);
|
regs + S3C64XX_SPI_CLK_CFG);
|
||||||
writel(0, regs + S3C64XX_SPI_MODE_CFG);
|
writel(0, regs + S3C64XX_SPI_MODE_CFG);
|
||||||
|
|
Loading…
Reference in New Issue