aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBoojin Kim <boojin.kim@samsung.com>2011-09-01 20:44:42 -0400
committerVinod Koul <vinod.koul@intel.com>2011-09-14 01:40:03 -0400
commit82ab8cd7ec32194757ac73a66633be73ba88ea69 (patch)
tree4ea8df22c9b235a9fd2da60c09bde2b1d58da1da
parent39d3e8074e44c1953928a0b91bc328f552c5fc79 (diff)
spi/s3c64xx: Merge dma control code
This patch modifies to merge the dma control code. Original s3c64xx spi driver has each dma control code for rx and tx channel. This patch merges these dma control codes into one. With this patch, a dma setup function and callback function handle for both rx and tx channel. Signed-off-by: Boojin Kim <boojin.kim@samsung.com> Acked-by: Linus Walleij <linus.walleij@linaro.org> Acked-by: Vinod Koul <vinod.koul@intel.com> Cc: Grant Likely <grant.likely@secretlab.ca> Signed-off-by: Kukjin Kim <kgene.kim@samsung.com> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
-rw-r--r--drivers/spi/spi-s3c64xx.c140
1 files changed, 76 insertions, 64 deletions
diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c
index 24f49032ec35..019a7163572f 100644
--- a/drivers/spi/spi-s3c64xx.c
+++ b/drivers/spi/spi-s3c64xx.c
@@ -131,6 +131,12 @@
131#define RXBUSY (1<<2) 131#define RXBUSY (1<<2)
132#define TXBUSY (1<<3) 132#define TXBUSY (1<<3)
133 133
134struct s3c64xx_spi_dma_data {
135 unsigned ch;
136 enum dma_data_direction direction;
137 enum dma_ch dmach;
138};
139
134/** 140/**
135 * struct s3c64xx_spi_driver_data - Runtime info holder for SPI driver. 141 * struct s3c64xx_spi_driver_data - Runtime info holder for SPI driver.
136 * @clk: Pointer to the spi clock. 142 * @clk: Pointer to the spi clock.
@@ -164,15 +170,13 @@ struct s3c64xx_spi_driver_data {
164 struct work_struct work; 170 struct work_struct work;
165 struct list_head queue; 171 struct list_head queue;
166 spinlock_t lock; 172 spinlock_t lock;
167 enum dma_ch rx_dmach;
168 enum dma_ch tx_dmach;
169 unsigned long sfr_start; 173 unsigned long sfr_start;
170 struct completion xfer_completion; 174 struct completion xfer_completion;
171 unsigned state; 175 unsigned state;
172 unsigned cur_mode, cur_bpw; 176 unsigned cur_mode, cur_bpw;
173 unsigned cur_speed; 177 unsigned cur_speed;
174 unsigned rx_ch; 178 struct s3c64xx_spi_dma_data rx_dma;
175 unsigned tx_ch; 179 struct s3c64xx_spi_dma_data tx_dma;
176 struct samsung_dma_ops *ops; 180 struct samsung_dma_ops *ops;
177}; 181};
178 182
@@ -229,36 +233,76 @@ static void flush_fifo(struct s3c64xx_spi_driver_data *sdd)
229 writel(val, regs + S3C64XX_SPI_CH_CFG); 233 writel(val, regs + S3C64XX_SPI_CH_CFG);
230} 234}
231 235
232static void s3c64xx_spi_dma_rxcb(void *data) 236static void s3c64xx_spi_dmacb(void *data)
233{ 237{
234 struct s3c64xx_spi_driver_data *sdd 238 struct s3c64xx_spi_driver_data *sdd;
235 = (struct s3c64xx_spi_driver_data *)data; 239 struct s3c64xx_spi_dma_data *dma = data;
236 unsigned long flags; 240 unsigned long flags;
237 241
242 if (dma->direction == DMA_FROM_DEVICE)
243 sdd = container_of(data,
244 struct s3c64xx_spi_driver_data, rx_dma);
245 else
246 sdd = container_of(data,
247 struct s3c64xx_spi_driver_data, tx_dma);
248
238 spin_lock_irqsave(&sdd->lock, flags); 249 spin_lock_irqsave(&sdd->lock, flags);
239 250
240 sdd->state &= ~RXBUSY; 251 if (dma->direction == DMA_FROM_DEVICE) {
241 /* If the other done */ 252 sdd->state &= ~RXBUSY;
242 if (!(sdd->state & TXBUSY)) 253 if (!(sdd->state & TXBUSY))
243 complete(&sdd->xfer_completion); 254 complete(&sdd->xfer_completion);
255 } else {
256 sdd->state &= ~TXBUSY;
257 if (!(sdd->state & RXBUSY))
258 complete(&sdd->xfer_completion);
259 }
244 260
245 spin_unlock_irqrestore(&sdd->lock, flags); 261 spin_unlock_irqrestore(&sdd->lock, flags);
246} 262}
247 263
248static void s3c64xx_spi_dma_txcb(void *data) 264static void prepare_dma(struct s3c64xx_spi_dma_data *dma,
265 unsigned len, dma_addr_t buf)
249{ 266{
250 struct s3c64xx_spi_driver_data *sdd 267 struct s3c64xx_spi_driver_data *sdd;
251 = (struct s3c64xx_spi_driver_data *)data; 268 struct samsung_dma_prep_info info;
252 unsigned long flags;
253 269
254 spin_lock_irqsave(&sdd->lock, flags); 270 if (dma->direction == DMA_FROM_DEVICE)
271 sdd = container_of((void *)dma,
272 struct s3c64xx_spi_driver_data, rx_dma);
273 else
274 sdd = container_of((void *)dma,
275 struct s3c64xx_spi_driver_data, tx_dma);
255 276
256 sdd->state &= ~TXBUSY; 277 info.cap = DMA_SLAVE;
257 /* If the other done */ 278 info.len = len;
258 if (!(sdd->state & RXBUSY)) 279 info.fp = s3c64xx_spi_dmacb;
259 complete(&sdd->xfer_completion); 280 info.fp_param = dma;
281 info.direction = dma->direction;
282 info.buf = buf;
283
284 sdd->ops->prepare(dma->ch, &info);
285 sdd->ops->trigger(dma->ch);
286}
260 287
261 spin_unlock_irqrestore(&sdd->lock, flags); 288static int acquire_dma(struct s3c64xx_spi_driver_data *sdd)
289{
290 struct samsung_dma_info info;
291
292 sdd->ops = samsung_dma_get_ops();
293
294 info.cap = DMA_SLAVE;
295 info.client = &s3c64xx_spi_dma_client;
296 info.width = sdd->cur_bpw / 8;
297
298 info.direction = sdd->rx_dma.direction;
299 info.fifo = sdd->sfr_start + S3C64XX_SPI_RX_DATA;
300 sdd->rx_dma.ch = sdd->ops->request(sdd->rx_dma.dmach, &info);
301 info.direction = sdd->tx_dma.direction;
302 info.fifo = sdd->sfr_start + S3C64XX_SPI_TX_DATA;
303 sdd->tx_dma.ch = sdd->ops->request(sdd->tx_dma.dmach, &info);
304
305 return 1;
262} 306}
263 307
264static void enable_datapath(struct s3c64xx_spi_driver_data *sdd, 308static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
@@ -268,7 +312,6 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
268 struct s3c64xx_spi_info *sci = sdd->cntrlr_info; 312 struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
269 void __iomem *regs = sdd->regs; 313 void __iomem *regs = sdd->regs;
270 u32 modecfg, chcfg; 314 u32 modecfg, chcfg;
271 struct samsung_dma_prep_info info;
272 315
273 modecfg = readl(regs + S3C64XX_SPI_MODE_CFG); 316 modecfg = readl(regs + S3C64XX_SPI_MODE_CFG);
274 modecfg &= ~(S3C64XX_SPI_MODE_TXDMA_ON | S3C64XX_SPI_MODE_RXDMA_ON); 317 modecfg &= ~(S3C64XX_SPI_MODE_TXDMA_ON | S3C64XX_SPI_MODE_RXDMA_ON);
@@ -294,14 +337,7 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
294 chcfg |= S3C64XX_SPI_CH_TXCH_ON; 337 chcfg |= S3C64XX_SPI_CH_TXCH_ON;
295 if (dma_mode) { 338 if (dma_mode) {
296 modecfg |= S3C64XX_SPI_MODE_TXDMA_ON; 339 modecfg |= S3C64XX_SPI_MODE_TXDMA_ON;
297 info.cap = DMA_SLAVE; 340 prepare_dma(&sdd->tx_dma, xfer->len, xfer->tx_dma);
298 info.direction = DMA_TO_DEVICE;
299 info.buf = xfer->tx_dma;
300 info.len = xfer->len;
301 info.fp = s3c64xx_spi_dma_txcb;
302 info.fp_param = sdd;
303 sdd->ops->prepare(sdd->tx_ch, &info);
304 sdd->ops->trigger(sdd->tx_ch);
305 } else { 341 } else {
306 switch (sdd->cur_bpw) { 342 switch (sdd->cur_bpw) {
307 case 32: 343 case 32:
@@ -333,14 +369,7 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
333 writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff) 369 writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff)
334 | S3C64XX_SPI_PACKET_CNT_EN, 370 | S3C64XX_SPI_PACKET_CNT_EN,
335 regs + S3C64XX_SPI_PACKET_CNT); 371 regs + S3C64XX_SPI_PACKET_CNT);
336 info.cap = DMA_SLAVE; 372 prepare_dma(&sdd->rx_dma, xfer->len, xfer->rx_dma);
337 info.direction = DMA_FROM_DEVICE;
338 info.buf = xfer->rx_dma;
339 info.len = xfer->len;
340 info.fp = s3c64xx_spi_dma_rxcb;
341 info.fp_param = sdd;
342 sdd->ops->prepare(sdd->rx_ch, &info);
343 sdd->ops->trigger(sdd->rx_ch);
344 } 373 }
345 } 374 }
346 375
@@ -700,10 +729,10 @@ static void handle_msg(struct s3c64xx_spi_driver_data *sdd,
700 if (use_dma) { 729 if (use_dma) {
701 if (xfer->tx_buf != NULL 730 if (xfer->tx_buf != NULL
702 && (sdd->state & TXBUSY)) 731 && (sdd->state & TXBUSY))
703 sdd->ops->stop(sdd->tx_ch); 732 sdd->ops->stop(sdd->tx_dma.ch);
704 if (xfer->rx_buf != NULL 733 if (xfer->rx_buf != NULL
705 && (sdd->state & RXBUSY)) 734 && (sdd->state & RXBUSY))
706 sdd->ops->stop(sdd->rx_ch); 735 sdd->ops->stop(sdd->rx_dma.ch);
707 } 736 }
708 737
709 goto out; 738 goto out;
@@ -741,25 +770,6 @@ out:
741 msg->complete(msg->context); 770 msg->complete(msg->context);
742} 771}
743 772
744static int acquire_dma(struct s3c64xx_spi_driver_data *sdd)
745{
746
747 struct samsung_dma_info info;
748 sdd->ops = samsung_dma_get_ops();
749
750 info.cap = DMA_SLAVE;
751 info.client = &s3c64xx_spi_dma_client;
752 info.direction = DMA_FROM_DEVICE;
753 info.fifo = sdd->sfr_start + S3C64XX_SPI_RX_DATA;
754 info.width = sdd->cur_bpw / 8;
755 sdd->rx_ch = sdd->ops->request(sdd->rx_dmach, &info);
756 info.direction = DMA_TO_DEVICE;
757 info.fifo = sdd->sfr_start + S3C64XX_SPI_TX_DATA;
758 sdd->tx_ch = sdd->ops->request(sdd->tx_dmach, &info);
759
760 return 1;
761}
762
763static void s3c64xx_spi_work(struct work_struct *work) 773static void s3c64xx_spi_work(struct work_struct *work)
764{ 774{
765 struct s3c64xx_spi_driver_data *sdd = container_of(work, 775 struct s3c64xx_spi_driver_data *sdd = container_of(work,
@@ -796,8 +806,8 @@ static void s3c64xx_spi_work(struct work_struct *work)
796 spin_unlock_irqrestore(&sdd->lock, flags); 806 spin_unlock_irqrestore(&sdd->lock, flags);
797 807
798 /* Free DMA channels */ 808 /* Free DMA channels */
799 sdd->ops->release(sdd->rx_ch, &s3c64xx_spi_dma_client); 809 sdd->ops->release(sdd->rx_dma.ch, &s3c64xx_spi_dma_client);
800 sdd->ops->release(sdd->tx_ch, &s3c64xx_spi_dma_client); 810 sdd->ops->release(sdd->tx_dma.ch, &s3c64xx_spi_dma_client);
801} 811}
802 812
803static int s3c64xx_spi_transfer(struct spi_device *spi, 813static int s3c64xx_spi_transfer(struct spi_device *spi,
@@ -1014,8 +1024,10 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
1014 sdd->cntrlr_info = sci; 1024 sdd->cntrlr_info = sci;
1015 sdd->pdev = pdev; 1025 sdd->pdev = pdev;
1016 sdd->sfr_start = mem_res->start; 1026 sdd->sfr_start = mem_res->start;
1017 sdd->tx_dmach = dmatx_res->start; 1027 sdd->tx_dma.dmach = dmatx_res->start;
1018 sdd->rx_dmach = dmarx_res->start; 1028 sdd->tx_dma.direction = DMA_TO_DEVICE;
1029 sdd->rx_dma.dmach = dmarx_res->start;
1030 sdd->rx_dma.direction = DMA_FROM_DEVICE;
1019 1031
1020 sdd->cur_bpw = 8; 1032 sdd->cur_bpw = 8;
1021 1033
@@ -1103,7 +1115,7 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
1103 pdev->id, master->num_chipselect); 1115 pdev->id, master->num_chipselect);
1104 dev_dbg(&pdev->dev, "\tIOmem=[0x%x-0x%x]\tDMA=[Rx-%d, Tx-%d]\n", 1116 dev_dbg(&pdev->dev, "\tIOmem=[0x%x-0x%x]\tDMA=[Rx-%d, Tx-%d]\n",
1105 mem_res->end, mem_res->start, 1117 mem_res->end, mem_res->start,
1106 sdd->rx_dmach, sdd->tx_dmach); 1118 sdd->rx_dma.dmach, sdd->tx_dma.dmach);
1107 1119
1108 return 0; 1120 return 0;
1109 1121