aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi
diff options
context:
space:
mode:
authorcodeworkx <daniel.hillenbrand@codeworkx.de>2012-06-02 13:09:29 +0200
committercodeworkx <daniel.hillenbrand@codeworkx.de>2012-06-02 13:09:29 +0200
commitc6da2cfeb05178a11c6d062a06f8078150ee492f (patch)
treef3b4021d252c52d6463a9b3c1bb7245e399b009c /drivers/spi
parentc6d7c4dbff353eac7919342ae6b3299a378160a6 (diff)
downloadkernel_samsung_smdk4412-c6da2cfeb05178a11c6d062a06f8078150ee492f.zip
kernel_samsung_smdk4412-c6da2cfeb05178a11c6d062a06f8078150ee492f.tar.gz
kernel_samsung_smdk4412-c6da2cfeb05178a11c6d062a06f8078150ee492f.tar.bz2
samsung update 1
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/Kconfig2
-rw-r--r--drivers/spi/spi_s3c64xx.c66
2 files changed, 65 insertions, 3 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index de35c3a..00584bd 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -340,7 +340,7 @@ config SPI_S3C24XX_GPIO
config SPI_S3C64XX
tristate "Samsung S3C64XX series type SPI"
- depends on (ARCH_S3C64XX || ARCH_S5P64X0)
+ depends on (ARCH_S3C64XX || ARCH_S5P64X0 || ARCH_EXYNOS4 || ARCH_EXYNOS5)
select S3C64XX_DMA if ARCH_S3C64XX
help
SPI driver for Samsung S3C64XX and newer SoCs.
diff --git a/drivers/spi/spi_s3c64xx.c b/drivers/spi/spi_s3c64xx.c
index 8945e20..fa534d3 100644
--- a/drivers/spi/spi_s3c64xx.c
+++ b/drivers/spi/spi_s3c64xx.c
@@ -56,7 +56,7 @@
#define S3C64XX_SPI_CLKSEL_SRCMSK (3<<9)
#define S3C64XX_SPI_CLKSEL_SRCSHFT 9
#define S3C64XX_SPI_ENCLK_ENABLE (1<<8)
-#define S3C64XX_SPI_PSR_MASK 0xff
+#define S3C64XX_SPI_PSR_MASK 0xff
#define S3C64XX_SPI_MODE_CH_TSZ_BYTE (0<<29)
#define S3C64XX_SPI_MODE_CH_TSZ_HALFWORD (1<<29)
@@ -172,6 +172,10 @@ struct s3c64xx_spi_driver_data {
unsigned state;
unsigned cur_mode, cur_bpw;
unsigned cur_speed;
+#if defined(CONFIG_MACH_M0_CMCC)
+ int rx_cnt;
+ int tx_cnt;
+#endif
};
static struct s3c2410_dma_client s3c64xx_spi_dma_client = {
@@ -185,6 +189,13 @@ static void flush_fifo(struct s3c64xx_spi_driver_data *sdd)
unsigned long loops;
u32 val;
+#if defined(CONFIG_TDMB) || defined(CONFIG_TDMB_MODULE) || \
+ defined(CONFIG_PHONE_IPC_SPI)
+ val = readl(regs + S3C64XX_SPI_CH_CFG);
+ val &= ~(S3C64XX_SPI_CH_RXCH_ON | S3C64XX_SPI_CH_TXCH_ON);
+ writel(val, regs + S3C64XX_SPI_CH_CFG);
+#endif
+
writel(0, regs + S3C64XX_SPI_PACKET_CNT);
val = readl(regs + S3C64XX_SPI_CH_CFG);
@@ -262,6 +273,9 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
s3c2410_dma_config(sdd->tx_dmach, sdd->cur_bpw / 8);
s3c2410_dma_enqueue(sdd->tx_dmach, (void *)sdd,
xfer->tx_dma, xfer->len);
+#if defined(CONFIG_MACH_M0_CMCC)
+ sdd->tx_cnt++;
+#endif
s3c2410_dma_ctrl(sdd->tx_dmach, S3C2410_DMAOP_START);
} else {
switch (sdd->cur_bpw) {
@@ -297,6 +311,9 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
s3c2410_dma_config(sdd->rx_dmach, sdd->cur_bpw / 8);
s3c2410_dma_enqueue(sdd->rx_dmach, (void *)sdd,
xfer->rx_dma, xfer->len);
+#if defined(CONFIG_MACH_M0_CMCC)
+ sdd->rx_cnt++;
+#endif
s3c2410_dma_ctrl(sdd->rx_dmach, S3C2410_DMAOP_START);
}
}
@@ -501,6 +518,10 @@ static void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id,
complete(&sdd->xfer_completion);
spin_unlock_irqrestore(&sdd->lock, flags);
+#if defined(CONFIG_MACH_M0_CMCC)
+ sdd->rx_cnt--;
+#endif
+
}
static void s3c64xx_spi_dma_txcb(struct s3c2410_dma_chan *chan, void *buf_id,
@@ -521,6 +542,10 @@ static void s3c64xx_spi_dma_txcb(struct s3c2410_dma_chan *chan, void *buf_id,
complete(&sdd->xfer_completion);
spin_unlock_irqrestore(&sdd->lock, flags);
+#if defined(CONFIG_MACH_M0_CMCC)
+ sdd->tx_cnt--;
+#endif
+
}
#define XFER_DMAADDR_INVALID DMA_BIT_MASK(32)
@@ -748,6 +773,9 @@ static int acquire_dma(struct s3c64xx_spi_driver_data *sdd)
return 0;
}
s3c2410_dma_set_buffdone_fn(sdd->rx_dmach, s3c64xx_spi_dma_rxcb);
+#if defined(CONFIG_MACH_M0_CMCC)
+ sdd->rx_cnt = 0;
+#endif
s3c2410_dma_devconfig(sdd->rx_dmach, S3C2410_DMASRC_HW,
sdd->sfr_start + S3C64XX_SPI_RX_DATA);
@@ -758,6 +786,9 @@ static int acquire_dma(struct s3c64xx_spi_driver_data *sdd)
return 0;
}
s3c2410_dma_set_buffdone_fn(sdd->tx_dmach, s3c64xx_spi_dma_txcb);
+#if defined(CONFIG_MACH_M0_CMCC)
+ sdd->tx_cnt = 0;
+#endif
s3c2410_dma_devconfig(sdd->tx_dmach, S3C2410_DMASRC_MEM,
sdd->sfr_start + S3C64XX_SPI_TX_DATA);
@@ -774,6 +805,10 @@ static void s3c64xx_spi_work(struct work_struct *work)
while (!acquire_dma(sdd))
msleep(10);
+ /* Enable the clock */
+ clk_enable(sdd->src_clk);
+ clk_enable(sdd->clk);
+
spin_lock_irqsave(&sdd->lock, flags);
while (!list_empty(&sdd->queue)
@@ -799,9 +834,29 @@ static void s3c64xx_spi_work(struct work_struct *work)
spin_unlock_irqrestore(&sdd->lock, flags);
+#if defined(CONFIG_MACH_M0_CMCC)
+ if ((sdd->rx_cnt == 0) && (sdd->tx_cnt == 0)) {
+ /* Disable the clock */
+ clk_disable(sdd->src_clk);
+ clk_disable(sdd->clk);
+
+ /* Free DMA channels */
+ s3c2410_dma_free(sdd->tx_dmach, &s3c64xx_spi_dma_client);
+ s3c2410_dma_free(sdd->rx_dmach, &s3c64xx_spi_dma_client);
+ } else {
+ printk(KERN_ERR "[andro.yoon] DMA is not free!!!!\n");
+ printk(KERN_ERR "[andro.yoon] tx_cnt = %d, rx_cnt = %d\n",
+ sdd->tx_cnt, sdd->rx_cnt);
+ }
+#else
+ /* Disable the clock */
+ clk_disable(sdd->src_clk);
+ clk_disable(sdd->clk);
+
/* Free DMA channels */
s3c2410_dma_free(sdd->tx_dmach, &s3c64xx_spi_dma_client);
s3c2410_dma_free(sdd->rx_dmach, &s3c64xx_spi_dma_client);
+#endif
}
static int s3c64xx_spi_transfer(struct spi_device *spi,
@@ -932,6 +987,10 @@ static void s3c64xx_spi_hwinit(struct s3c64xx_spi_driver_data *sdd, int channel)
sdd->cur_speed = 0;
+#if defined(CONFIG_MACH_M0_CMCC)
+ sdd->tx_cnt = 0;
+ sdd->rx_cnt = 0;
+#endif
S3C64XX_SPI_DEACT(sdd);
/* Disable Interrupts - we use Polling if not DMA mode */
@@ -1108,6 +1167,9 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "\tIOmem=[0x%x-0x%x]\tDMA=[Rx-%d, Tx-%d]\n",
mem_res->end, mem_res->start,
sdd->rx_dmach, sdd->tx_dmach);
+ /* Disable the clock */
+ clk_disable(sdd->src_clk);
+ clk_disable(sdd->clk);
return 0;
@@ -1233,7 +1295,7 @@ static int __init s3c64xx_spi_init(void)
{
return platform_driver_probe(&s3c64xx_spi_driver, s3c64xx_spi_probe);
}
-subsys_initcall(s3c64xx_spi_init);
+module_init(s3c64xx_spi_init);
static void __exit s3c64xx_spi_exit(void)
{