|
@@ -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 */
|
|
- 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 */
|
|
/* Set Polarity and Phase */
|
|
val = readl(regs + S3C64XX_SPI_CH_CFG);
|
|
val = readl(regs + S3C64XX_SPI_CH_CFG);
|
|
@@ -441,17 +446,25 @@ 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);
|
|
|
|
|
|
- /* 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);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
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,32 +861,37 @@ 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 (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;
|
|
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_exit:
|
|
|
|
|
|
/* setup() returns with device de-selected */
|
|
/* setup() returns with device de-selected */
|
|
@@ -896,7 +913,8 @@ 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);
|
|
|
|
|
|
- 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);
|
|
regs + S3C64XX_SPI_CLK_CFG);
|
|
writel(0, regs + S3C64XX_SPI_MODE_CFG);
|
|
writel(0, regs + S3C64XX_SPI_MODE_CFG);
|
|
writel(0, regs + S3C64XX_SPI_PACKET_CNT);
|
|
writel(0, regs + S3C64XX_SPI_PACKET_CNT);
|