diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-14 19:43:47 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-14 19:43:47 -0500 |
commit | 6ae840e7cc4be0be3aa40d9f67c35c75cfc67d83 (patch) | |
tree | 9c83c87a8670ef678d95f8d6f76a07f24a09a49f /drivers/misc/carma/carma-fpga-program.c | |
parent | e6b5be2be4e30037eb551e0ed09dd97bd00d85d3 (diff) | |
parent | 91905b6f4afe51e23a3f58df93e4cdc5e49cf40c (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.c | 104 |
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 | ||
80 | static 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 | |||
111 | vmalloc_to_page_err: | ||
112 | vfree(priv->sglist); | ||
113 | priv->sglist = NULL; | ||
114 | vzalloc_err: | ||
115 | vfree(priv->vaddr); | ||
116 | priv->vaddr = NULL; | ||
117 | return -ENOMEM; | ||
118 | } | ||
119 | |||
120 | static 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 | |||
132 | static 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 | */ |
88 | static void fpga_drop_firmware_data(struct fpga_dev *priv) | 152 | static 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 | */ |
464 | static noinline int fpga_program_dma(struct fpga_dev *priv) | 529 | static 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) | |||
572 | out_disable_controller: | 636 | out_disable_controller: |
573 | fpga_programmer_disable(priv); | 637 | fpga_programmer_disable(priv); |
574 | out_dma_unmap: | 638 | out_dma_unmap: |
575 | videobuf_dma_unmap(priv->dev, vb); | 639 | fpga_dma_unmap(priv); |
576 | out_free_table: | 640 | out_free_table: |
577 | sg_free_table(&table); | 641 | sg_free_table(&table); |
578 | out_return: | 642 | out_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 | ||
756 | static loff_t fpga_llseek(struct file *filp, loff_t offset, int origin) | 820 | static 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 | ||
768 | static const struct file_operations fpga_fops = { | 831 | static 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); |