aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/carma/carma-fpga-program.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-12-14 19:43:47 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-12-14 19:43:47 -0500
commit6ae840e7cc4be0be3aa40d9f67c35c75cfc67d83 (patch)
tree9c83c87a8670ef678d95f8d6f76a07f24a09a49f /drivers/misc/carma/carma-fpga-program.c
parente6b5be2be4e30037eb551e0ed09dd97bd00d85d3 (diff)
parent91905b6f4afe51e23a3f58df93e4cdc5e49cf40c (diff)
Merge tag 'char-misc-3.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char/misc driver updates from Greg KH: "Here's the big char/misc driver update for 3.19-rc1 Lots of little things all over the place in different drivers, and a new subsystem, "coresight" has been added. Full details are in the shortlog" * tag 'char-misc-3.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (73 commits) parport: parport_pc, do not remove parent devices early spmi: Remove shutdown/suspend/resume kernel-doc carma-fpga-program: drop videobuf dependency carma-fpga: drop videobuf dependency carma-fpga-program.c: fix compile errors i8k: Fix temperature bug handling in i8k_get_temp() cxl: Name interrupts in /proc/interrupt CXL: Return error to PSL if IRQ demultiplexing fails & print clearer warning coresight-replicator: remove .owner field for driver coresight: fixed comments in coresight.h coresight: fix typo in comment in coresight-priv.h coresight: bindings for coresight drivers coresight: Adding ABI documentation w1: support auto-load of w1_bq27000 module. w1: avoid potential u16 overflow cn: verify msg->len before making callback mei: export fw status registers through sysfs mei: read and print all six FW status registers mei: txe: add cherrytrail device id mei: kill cached host and me csr values ...
Diffstat (limited to 'drivers/misc/carma/carma-fpga-program.c')
-rw-r--r--drivers/misc/carma/carma-fpga-program.c104
1 files changed, 83 insertions, 21 deletions
diff --git a/drivers/misc/carma/carma-fpga-program.c b/drivers/misc/carma/carma-fpga-program.c
index 6fa52f71f51c..06166ac000e0 100644
--- a/drivers/misc/carma/carma-fpga-program.c
+++ b/drivers/misc/carma/carma-fpga-program.c
@@ -19,6 +19,7 @@
19#include <linux/fsldma.h> 19#include <linux/fsldma.h>
20#include <linux/interrupt.h> 20#include <linux/interrupt.h>
21#include <linux/highmem.h> 21#include <linux/highmem.h>
22#include <linux/vmalloc.h>
22#include <linux/kernel.h> 23#include <linux/kernel.h>
23#include <linux/module.h> 24#include <linux/module.h>
24#include <linux/mutex.h> 25#include <linux/mutex.h>
@@ -30,8 +31,6 @@
30#include <linux/fs.h> 31#include <linux/fs.h>
31#include <linux/io.h> 32#include <linux/io.h>
32 33
33#include <media/videobuf-dma-sg.h>
34
35/* MPC8349EMDS specific get_immrbase() */ 34/* MPC8349EMDS specific get_immrbase() */
36#include <sysdev/fsl_soc.h> 35#include <sysdev/fsl_soc.h>
37 36
@@ -67,14 +66,79 @@ struct fpga_dev {
67 /* FPGA Bitfile */ 66 /* FPGA Bitfile */
68 struct mutex lock; 67 struct mutex lock;
69 68
70 struct videobuf_dmabuf vb; 69 void *vaddr;
71 bool vb_allocated; 70 struct scatterlist *sglist;
71 int sglen;
72 int nr_pages;
73 bool buf_allocated;
72 74
73 /* max size and written bytes */ 75 /* max size and written bytes */
74 size_t fw_size; 76 size_t fw_size;
75 size_t bytes; 77 size_t bytes;
76}; 78};
77 79
80static int fpga_dma_init(struct fpga_dev *priv, int nr_pages)
81{
82 struct page *pg;
83 int i;
84
85 priv->vaddr = vmalloc_32(nr_pages << PAGE_SHIFT);
86 if (NULL == priv->vaddr) {
87 pr_debug("vmalloc_32(%d pages) failed\n", nr_pages);
88 return -ENOMEM;
89 }
90
91 pr_debug("vmalloc is at addr 0x%08lx, size=%d\n",
92 (unsigned long)priv->vaddr,
93 nr_pages << PAGE_SHIFT);
94
95 memset(priv->vaddr, 0, nr_pages << PAGE_SHIFT);
96 priv->nr_pages = nr_pages;
97
98 priv->sglist = vzalloc(priv->nr_pages * sizeof(*priv->sglist));
99 if (NULL == priv->sglist)
100 goto vzalloc_err;
101
102 sg_init_table(priv->sglist, priv->nr_pages);
103 for (i = 0; i < priv->nr_pages; i++) {
104 pg = vmalloc_to_page(priv->vaddr + i * PAGE_SIZE);
105 if (NULL == pg)
106 goto vmalloc_to_page_err;
107 sg_set_page(&priv->sglist[i], pg, PAGE_SIZE, 0);
108 }
109 return 0;
110
111vmalloc_to_page_err:
112 vfree(priv->sglist);
113 priv->sglist = NULL;
114vzalloc_err:
115 vfree(priv->vaddr);
116 priv->vaddr = NULL;
117 return -ENOMEM;
118}
119
120static int fpga_dma_map(struct fpga_dev *priv)
121{
122 priv->sglen = dma_map_sg(priv->dev, priv->sglist,
123 priv->nr_pages, DMA_TO_DEVICE);
124
125 if (0 == priv->sglen) {
126 pr_warn("%s: dma_map_sg failed\n", __func__);
127 return -ENOMEM;
128 }
129 return 0;
130}
131
132static int fpga_dma_unmap(struct fpga_dev *priv)
133{
134 if (!priv->sglen)
135 return 0;
136
137 dma_unmap_sg(priv->dev, priv->sglist, priv->sglen, DMA_TO_DEVICE);
138 priv->sglen = 0;
139 return 0;
140}
141
78/* 142/*
79 * FPGA Bitfile Helpers 143 * FPGA Bitfile Helpers
80 */ 144 */
@@ -87,8 +151,9 @@ struct fpga_dev {
87 */ 151 */
88static void fpga_drop_firmware_data(struct fpga_dev *priv) 152static void fpga_drop_firmware_data(struct fpga_dev *priv)
89{ 153{
90 videobuf_dma_free(&priv->vb); 154 vfree(priv->sglist);
91 priv->vb_allocated = false; 155 vfree(priv->vaddr);
156 priv->buf_allocated = false;
92 priv->bytes = 0; 157 priv->bytes = 0;
93} 158}
94 159
@@ -427,7 +492,7 @@ static noinline int fpga_program_cpu(struct fpga_dev *priv)
427 dev_dbg(priv->dev, "enabled the controller\n"); 492 dev_dbg(priv->dev, "enabled the controller\n");
428 493
429 /* Write each chunk of the FPGA bitfile to FPGA programmer */ 494 /* Write each chunk of the FPGA bitfile to FPGA programmer */
430 ret = fpga_program_block(priv, priv->vb.vaddr, priv->bytes); 495 ret = fpga_program_block(priv, priv->vaddr, priv->bytes);
431 if (ret) 496 if (ret)
432 goto out_disable_controller; 497 goto out_disable_controller;
433 498
@@ -463,7 +528,6 @@ out_disable_controller:
463 */ 528 */
464static noinline int fpga_program_dma(struct fpga_dev *priv) 529static noinline int fpga_program_dma(struct fpga_dev *priv)
465{ 530{
466 struct videobuf_dmabuf *vb = &priv->vb;
467 struct dma_chan *chan = priv->chan; 531 struct dma_chan *chan = priv->chan;
468 struct dma_async_tx_descriptor *tx; 532 struct dma_async_tx_descriptor *tx;
469 size_t num_pages, len, avail = 0; 533 size_t num_pages, len, avail = 0;
@@ -505,7 +569,7 @@ static noinline int fpga_program_dma(struct fpga_dev *priv)
505 } 569 }
506 570
507 /* Map the buffer for DMA */ 571 /* Map the buffer for DMA */
508 ret = videobuf_dma_map(priv->dev, &priv->vb); 572 ret = fpga_dma_map(priv);
509 if (ret) { 573 if (ret) {
510 dev_err(priv->dev, "Unable to map buffer for DMA\n"); 574 dev_err(priv->dev, "Unable to map buffer for DMA\n");
511 goto out_free_table; 575 goto out_free_table;
@@ -525,7 +589,7 @@ static noinline int fpga_program_dma(struct fpga_dev *priv)
525 goto out_dma_unmap; 589 goto out_dma_unmap;
526 } 590 }
527 591
528 ret = fsl_dma_external_start(chan, 1) 592 ret = fsl_dma_external_start(chan, 1);
529 if (ret) { 593 if (ret) {
530 dev_err(priv->dev, "DMA external control setup failed\n"); 594 dev_err(priv->dev, "DMA external control setup failed\n");
531 goto out_dma_unmap; 595 goto out_dma_unmap;
@@ -534,7 +598,7 @@ static noinline int fpga_program_dma(struct fpga_dev *priv)
534 /* setup and submit the DMA transaction */ 598 /* setup and submit the DMA transaction */
535 599
536 tx = dmaengine_prep_dma_sg(chan, table.sgl, num_pages, 600 tx = dmaengine_prep_dma_sg(chan, table.sgl, num_pages,
537 vb->sglist, vb->sglen, 0); 601 priv->sglist, priv->sglen, 0);
538 if (!tx) { 602 if (!tx) {
539 dev_err(priv->dev, "Unable to prep DMA transaction\n"); 603 dev_err(priv->dev, "Unable to prep DMA transaction\n");
540 ret = -ENOMEM; 604 ret = -ENOMEM;
@@ -572,7 +636,7 @@ static noinline int fpga_program_dma(struct fpga_dev *priv)
572out_disable_controller: 636out_disable_controller:
573 fpga_programmer_disable(priv); 637 fpga_programmer_disable(priv);
574out_dma_unmap: 638out_dma_unmap:
575 videobuf_dma_unmap(priv->dev, vb); 639 fpga_dma_unmap(priv);
576out_free_table: 640out_free_table:
577 sg_free_table(&table); 641 sg_free_table(&table);
578out_return: 642out_return:
@@ -702,12 +766,12 @@ static int fpga_open(struct inode *inode, struct file *filp)
702 priv->bytes = 0; 766 priv->bytes = 0;
703 767
704 /* Check if we have already allocated a buffer */ 768 /* Check if we have already allocated a buffer */
705 if (priv->vb_allocated) 769 if (priv->buf_allocated)
706 return 0; 770 return 0;
707 771
708 /* Allocate a buffer to hold enough data for the bitfile */ 772 /* Allocate a buffer to hold enough data for the bitfile */
709 nr_pages = DIV_ROUND_UP(priv->fw_size, PAGE_SIZE); 773 nr_pages = DIV_ROUND_UP(priv->fw_size, PAGE_SIZE);
710 ret = videobuf_dma_init_kernel(&priv->vb, DMA_TO_DEVICE, nr_pages); 774 ret = fpga_dma_init(priv, nr_pages);
711 if (ret) { 775 if (ret) {
712 dev_err(priv->dev, "unable to allocate data buffer\n"); 776 dev_err(priv->dev, "unable to allocate data buffer\n");
713 mutex_unlock(&priv->lock); 777 mutex_unlock(&priv->lock);
@@ -715,7 +779,7 @@ static int fpga_open(struct inode *inode, struct file *filp)
715 return ret; 779 return ret;
716 } 780 }
717 781
718 priv->vb_allocated = true; 782 priv->buf_allocated = true;
719 return 0; 783 return 0;
720} 784}
721 785
@@ -738,7 +802,7 @@ static ssize_t fpga_write(struct file *filp, const char __user *buf,
738 return -ENOSPC; 802 return -ENOSPC;
739 803
740 count = min_t(size_t, priv->fw_size - priv->bytes, count); 804 count = min_t(size_t, priv->fw_size - priv->bytes, count);
741 if (copy_from_user(priv->vb.vaddr + priv->bytes, buf, count)) 805 if (copy_from_user(priv->vaddr + priv->bytes, buf, count))
742 return -EFAULT; 806 return -EFAULT;
743 807
744 priv->bytes += count; 808 priv->bytes += count;
@@ -749,20 +813,19 @@ static ssize_t fpga_read(struct file *filp, char __user *buf, size_t count,
749 loff_t *f_pos) 813 loff_t *f_pos)
750{ 814{
751 struct fpga_dev *priv = filp->private_data; 815 struct fpga_dev *priv = filp->private_data;
752 return simple_read_from_buffer(buf, count, ppos, 816 return simple_read_from_buffer(buf, count, f_pos,
753 priv->vb.vaddr, priv->bytes); 817 priv->vaddr, priv->bytes);
754} 818}
755 819
756static loff_t fpga_llseek(struct file *filp, loff_t offset, int origin) 820static loff_t fpga_llseek(struct file *filp, loff_t offset, int origin)
757{ 821{
758 struct fpga_dev *priv = filp->private_data; 822 struct fpga_dev *priv = filp->private_data;
759 loff_t newpos;
760 823
761 /* only read-only opens are allowed to seek */ 824 /* only read-only opens are allowed to seek */
762 if ((filp->f_flags & O_ACCMODE) != O_RDONLY) 825 if ((filp->f_flags & O_ACCMODE) != O_RDONLY)
763 return -EINVAL; 826 return -EINVAL;
764 827
765 return fixed_size_llseek(file, offset, origin, priv->fw_size); 828 return fixed_size_llseek(filp, offset, origin, priv->fw_size);
766} 829}
767 830
768static const struct file_operations fpga_fops = { 831static const struct file_operations fpga_fops = {
@@ -953,7 +1016,6 @@ static int fpga_of_probe(struct platform_device *op)
953 priv->dev = &op->dev; 1016 priv->dev = &op->dev;
954 mutex_init(&priv->lock); 1017 mutex_init(&priv->lock);
955 init_completion(&priv->completion); 1018 init_completion(&priv->completion);
956 videobuf_dma_init(&priv->vb);
957 1019
958 dev_set_drvdata(priv->dev, priv); 1020 dev_set_drvdata(priv->dev, priv);
959 dma_cap_zero(mask); 1021 dma_cap_zero(mask);