Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 212294
b: refs/heads/master
c: b42a81c
h: refs/heads/master
v: v3
  • Loading branch information
Jassi Brar authored and Grant Likely committed Sep 29, 2010
1 parent dd35096 commit 82f6553
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 39 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: e02ddd442a532c73e547ae3735c8012e3bd719a5
refs/heads/master: b42a81ca0fa7b3b442a0731ffc4e7db44464b5f2
3 changes: 3 additions & 0 deletions trunk/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;

Expand Down
94 changes: 56 additions & 38 deletions trunk/drivers/spi/spi_s3c64xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
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);
Expand Down Expand Up @@ -441,17 +446,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);
}
}

static void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id,
Expand Down Expand Up @@ -806,7 +819,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;

Expand Down Expand Up @@ -849,32 +861,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 */
Expand All @@ -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 */
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);
Expand Down

0 comments on commit 82f6553

Please sign in to comment.