Manu Abraham | 41e840b | 2009-12-02 21:57:10 -0300 | [diff] [blame] | 1 | /* |
| 2 | Mantis PCI bridge driver |
| 3 | |
Manu Abraham | 8825a09 | 2009-12-15 09:13:49 -0300 | [diff] [blame] | 4 | Copyright (C) Manu Abraham (abraham.manu@gmail.com) |
Manu Abraham | 41e840b | 2009-12-02 21:57:10 -0300 | [diff] [blame] | 5 | |
| 6 | This program is free software; you can redistribute it and/or modify |
| 7 | it under the terms of the GNU General Public License as published by |
| 8 | the Free Software Foundation; either version 2 of the License, or |
| 9 | (at your option) any later version. |
| 10 | |
| 11 | This program is distributed in the hope that it will be useful, |
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | GNU General Public License for more details. |
| 15 | |
| 16 | You should have received a copy of the GNU General Public License |
| 17 | along with this program; if not, write to the Free Software |
| 18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 19 | */ |
| 20 | |
Manu Abraham | b3b9614 | 2009-12-04 05:41:11 -0300 | [diff] [blame] | 21 | #include <linux/kernel.h> |
Manu Abraham | 41e840b | 2009-12-02 21:57:10 -0300 | [diff] [blame] | 22 | #include <asm/page.h> |
| 23 | #include <linux/vmalloc.h> |
Manu Abraham | b3b9614 | 2009-12-04 05:41:11 -0300 | [diff] [blame] | 24 | #include <linux/pci.h> |
| 25 | |
| 26 | #include <asm/irq.h> |
| 27 | #include <linux/signal.h> |
| 28 | #include <linux/sched.h> |
| 29 | #include <linux/interrupt.h> |
| 30 | |
| 31 | #include "dmxdev.h" |
| 32 | #include "dvbdev.h" |
| 33 | #include "dvb_demux.h" |
| 34 | #include "dvb_frontend.h" |
| 35 | #include "dvb_net.h" |
| 36 | |
Manu Abraham | 41e840b | 2009-12-02 21:57:10 -0300 | [diff] [blame] | 37 | #include "mantis_common.h" |
Manu Abraham | b3b9614 | 2009-12-04 05:41:11 -0300 | [diff] [blame] | 38 | #include "mantis_reg.h" |
| 39 | #include "mantis_dma.h" |
Manu Abraham | 41e840b | 2009-12-02 21:57:10 -0300 | [diff] [blame] | 40 | |
| 41 | #define RISC_WRITE (0x01 << 28) |
| 42 | #define RISC_JUMP (0x07 << 28) |
| 43 | #define RISC_IRQ (0x01 << 24) |
| 44 | |
| 45 | #define RISC_STATUS(status) ((((~status) & 0x0f) << 20) | ((status & 0x0f) << 16)) |
Marko Ristola | 79d06d4 | 2010-08-07 08:16:15 -0300 | [diff] [blame] | 46 | #define RISC_FLUSH(risc_pos) (risc_pos = 0) |
| 47 | #define RISC_INSTR(risc_pos, opcode) (mantis->risc_cpu[risc_pos++] = cpu_to_le32(opcode)) |
Manu Abraham | 41e840b | 2009-12-02 21:57:10 -0300 | [diff] [blame] | 48 | |
Manu Abraham | f5ae4f6 | 2009-12-15 08:47:21 -0300 | [diff] [blame] | 49 | #define MANTIS_BUF_SIZE (64 * 1024) |
Marko Ristola | 79d06d4 | 2010-08-07 08:16:15 -0300 | [diff] [blame] | 50 | #define MANTIS_BLOCK_BYTES (MANTIS_BUF_SIZE / 4) |
| 51 | #define MANTIS_DMA_TR_BYTES (2 * 1024) /* upper limit: 4095 bytes. */ |
| 52 | #define MANTIS_BLOCK_COUNT (MANTIS_BUF_SIZE / MANTIS_BLOCK_BYTES) |
| 53 | |
| 54 | #define MANTIS_DMA_TR_UNITS (MANTIS_BLOCK_BYTES / MANTIS_DMA_TR_BYTES) |
| 55 | /* MANTIS_BUF_SIZE / MANTIS_DMA_TR_UNITS must not exceed MANTIS_RISC_SIZE (4k RISC cmd buffer) */ |
| 56 | #define MANTIS_RISC_SIZE PAGE_SIZE /* RISC program must fit here. */ |
Manu Abraham | 41e840b | 2009-12-02 21:57:10 -0300 | [diff] [blame] | 57 | |
| 58 | int mantis_dma_exit(struct mantis_pci *mantis) |
| 59 | { |
| 60 | if (mantis->buf_cpu) { |
Manu Abraham | b3b9614 | 2009-12-04 05:41:11 -0300 | [diff] [blame] | 61 | dprintk(MANTIS_ERROR, 1, |
Manu Abraham | 41e840b | 2009-12-02 21:57:10 -0300 | [diff] [blame] | 62 | "DMA=0x%lx cpu=0x%p size=%d", |
| 63 | (unsigned long) mantis->buf_dma, |
| 64 | mantis->buf_cpu, |
| 65 | MANTIS_BUF_SIZE); |
| 66 | |
| 67 | pci_free_consistent(mantis->pdev, MANTIS_BUF_SIZE, |
| 68 | mantis->buf_cpu, mantis->buf_dma); |
| 69 | |
| 70 | mantis->buf_cpu = NULL; |
| 71 | } |
| 72 | if (mantis->risc_cpu) { |
Manu Abraham | b3b9614 | 2009-12-04 05:41:11 -0300 | [diff] [blame] | 73 | dprintk(MANTIS_ERROR, 1, |
Manu Abraham | 41e840b | 2009-12-02 21:57:10 -0300 | [diff] [blame] | 74 | "RISC=0x%lx cpu=0x%p size=%lx", |
| 75 | (unsigned long) mantis->risc_dma, |
| 76 | mantis->risc_cpu, |
| 77 | MANTIS_RISC_SIZE); |
| 78 | |
| 79 | pci_free_consistent(mantis->pdev, MANTIS_RISC_SIZE, |
| 80 | mantis->risc_cpu, mantis->risc_dma); |
| 81 | |
| 82 | mantis->risc_cpu = NULL; |
| 83 | } |
| 84 | |
| 85 | return 0; |
| 86 | } |
Manu Abraham | b3b9614 | 2009-12-04 05:41:11 -0300 | [diff] [blame] | 87 | EXPORT_SYMBOL_GPL(mantis_dma_exit); |
Manu Abraham | 41e840b | 2009-12-02 21:57:10 -0300 | [diff] [blame] | 88 | |
| 89 | static inline int mantis_alloc_buffers(struct mantis_pci *mantis) |
| 90 | { |
| 91 | if (!mantis->buf_cpu) { |
| 92 | mantis->buf_cpu = pci_alloc_consistent(mantis->pdev, |
| 93 | MANTIS_BUF_SIZE, |
| 94 | &mantis->buf_dma); |
| 95 | if (!mantis->buf_cpu) { |
Manu Abraham | b3b9614 | 2009-12-04 05:41:11 -0300 | [diff] [blame] | 96 | dprintk(MANTIS_ERROR, 1, |
Manu Abraham | 41e840b | 2009-12-02 21:57:10 -0300 | [diff] [blame] | 97 | "DMA buffer allocation failed"); |
| 98 | |
| 99 | goto err; |
| 100 | } |
Manu Abraham | b3b9614 | 2009-12-04 05:41:11 -0300 | [diff] [blame] | 101 | dprintk(MANTIS_ERROR, 1, |
Manu Abraham | 41e840b | 2009-12-02 21:57:10 -0300 | [diff] [blame] | 102 | "DMA=0x%lx cpu=0x%p size=%d", |
| 103 | (unsigned long) mantis->buf_dma, |
| 104 | mantis->buf_cpu, MANTIS_BUF_SIZE); |
| 105 | } |
| 106 | if (!mantis->risc_cpu) { |
| 107 | mantis->risc_cpu = pci_alloc_consistent(mantis->pdev, |
| 108 | MANTIS_RISC_SIZE, |
| 109 | &mantis->risc_dma); |
| 110 | |
| 111 | if (!mantis->risc_cpu) { |
Manu Abraham | b3b9614 | 2009-12-04 05:41:11 -0300 | [diff] [blame] | 112 | dprintk(MANTIS_ERROR, 1, |
Manu Abraham | 41e840b | 2009-12-02 21:57:10 -0300 | [diff] [blame] | 113 | "RISC program allocation failed"); |
| 114 | |
| 115 | mantis_dma_exit(mantis); |
| 116 | |
| 117 | goto err; |
| 118 | } |
Manu Abraham | b3b9614 | 2009-12-04 05:41:11 -0300 | [diff] [blame] | 119 | dprintk(MANTIS_ERROR, 1, |
Manu Abraham | 41e840b | 2009-12-02 21:57:10 -0300 | [diff] [blame] | 120 | "RISC=0x%lx cpu=0x%p size=%lx", |
| 121 | (unsigned long) mantis->risc_dma, |
| 122 | mantis->risc_cpu, MANTIS_RISC_SIZE); |
| 123 | } |
| 124 | |
| 125 | return 0; |
| 126 | err: |
Manu Abraham | b3b9614 | 2009-12-04 05:41:11 -0300 | [diff] [blame] | 127 | dprintk(MANTIS_ERROR, 1, "Out of memory (?) ....."); |
Manu Abraham | 41e840b | 2009-12-02 21:57:10 -0300 | [diff] [blame] | 128 | return -ENOMEM; |
| 129 | } |
| 130 | |
Manu Abraham | 41e840b | 2009-12-02 21:57:10 -0300 | [diff] [blame] | 131 | int mantis_dma_init(struct mantis_pci *mantis) |
| 132 | { |
| 133 | int err = 0; |
| 134 | |
Manu Abraham | b3b9614 | 2009-12-04 05:41:11 -0300 | [diff] [blame] | 135 | dprintk(MANTIS_DEBUG, 1, "Mantis DMA init"); |
Manu Abraham | 41e840b | 2009-12-02 21:57:10 -0300 | [diff] [blame] | 136 | if (mantis_alloc_buffers(mantis) < 0) { |
Manu Abraham | b3b9614 | 2009-12-04 05:41:11 -0300 | [diff] [blame] | 137 | dprintk(MANTIS_ERROR, 1, "Error allocating DMA buffer"); |
Manu Abraham | 41e840b | 2009-12-02 21:57:10 -0300 | [diff] [blame] | 138 | |
Manu Abraham | 3e978a8 | 2009-12-04 05:56:35 -0300 | [diff] [blame] | 139 | /* Stop RISC Engine */ |
Manu Abraham | 41e840b | 2009-12-02 21:57:10 -0300 | [diff] [blame] | 140 | mmwrite(0, MANTIS_DMA_CTL); |
| 141 | |
| 142 | goto err; |
| 143 | } |
Manu Abraham | 41e840b | 2009-12-02 21:57:10 -0300 | [diff] [blame] | 144 | |
| 145 | return 0; |
| 146 | err: |
| 147 | return err; |
| 148 | } |
Manu Abraham | b3b9614 | 2009-12-04 05:41:11 -0300 | [diff] [blame] | 149 | EXPORT_SYMBOL_GPL(mantis_dma_init); |
Manu Abraham | 41e840b | 2009-12-02 21:57:10 -0300 | [diff] [blame] | 150 | |
Manu Abraham | 41e840b | 2009-12-02 21:57:10 -0300 | [diff] [blame] | 151 | static inline void mantis_risc_program(struct mantis_pci *mantis) |
| 152 | { |
| 153 | u32 buf_pos = 0; |
Marko Ristola | 79d06d4 | 2010-08-07 08:16:15 -0300 | [diff] [blame] | 154 | u32 line, step; |
| 155 | u32 risc_pos; |
Manu Abraham | 41e840b | 2009-12-02 21:57:10 -0300 | [diff] [blame] | 156 | |
Manu Abraham | b3b9614 | 2009-12-04 05:41:11 -0300 | [diff] [blame] | 157 | dprintk(MANTIS_DEBUG, 1, "Mantis create RISC program"); |
Marko Ristola | 79d06d4 | 2010-08-07 08:16:15 -0300 | [diff] [blame] | 158 | RISC_FLUSH(risc_pos); |
Manu Abraham | 41e840b | 2009-12-02 21:57:10 -0300 | [diff] [blame] | 159 | |
Marko Ristola | 79d06d4 | 2010-08-07 08:16:15 -0300 | [diff] [blame] | 160 | dprintk(MANTIS_DEBUG, 1, "risc len lines %u, bytes per line %u, bytes per DMA tr %u", |
| 161 | MANTIS_BLOCK_COUNT, MANTIS_BLOCK_BYTES, MANTIS_DMA_TR_BYTES); |
Manu Abraham | 41e840b | 2009-12-02 21:57:10 -0300 | [diff] [blame] | 162 | |
Marko Ristola | 79d06d4 | 2010-08-07 08:16:15 -0300 | [diff] [blame] | 163 | for (line = 0; line < MANTIS_BLOCK_COUNT; line++) { |
| 164 | for (step = 0; step < MANTIS_DMA_TR_UNITS; step++) { |
| 165 | dprintk(MANTIS_DEBUG, 1, "RISC PROG line=[%d], step=[%d]", line, step); |
| 166 | if (step == 0) { |
| 167 | RISC_INSTR(risc_pos, RISC_WRITE | |
| 168 | RISC_IRQ | |
| 169 | RISC_STATUS(line) | |
| 170 | MANTIS_DMA_TR_BYTES); |
| 171 | } else { |
| 172 | RISC_INSTR(risc_pos, RISC_WRITE | MANTIS_DMA_TR_BYTES); |
| 173 | } |
| 174 | RISC_INSTR(risc_pos, mantis->buf_dma + buf_pos); |
| 175 | buf_pos += MANTIS_DMA_TR_BYTES; |
| 176 | } |
Manu Abraham | 41e840b | 2009-12-02 21:57:10 -0300 | [diff] [blame] | 177 | } |
Marko Ristola | 79d06d4 | 2010-08-07 08:16:15 -0300 | [diff] [blame] | 178 | RISC_INSTR(risc_pos, RISC_JUMP); |
| 179 | RISC_INSTR(risc_pos, mantis->risc_dma); |
Manu Abraham | 41e840b | 2009-12-02 21:57:10 -0300 | [diff] [blame] | 180 | } |
| 181 | |
| 182 | void mantis_dma_start(struct mantis_pci *mantis) |
| 183 | { |
Manu Abraham | b3b9614 | 2009-12-04 05:41:11 -0300 | [diff] [blame] | 184 | dprintk(MANTIS_DEBUG, 1, "Mantis Start DMA engine"); |
Manu Abraham | 41e840b | 2009-12-02 21:57:10 -0300 | [diff] [blame] | 185 | |
| 186 | mantis_risc_program(mantis); |
David Woodhouse | 4170368 | 2009-12-03 05:47:11 -0300 | [diff] [blame] | 187 | mmwrite(mantis->risc_dma, MANTIS_RISC_START); |
Sigmund Augdal | a0c5906 | 2009-12-04 05:13:21 -0300 | [diff] [blame] | 188 | mmwrite(mmread(MANTIS_GPIF_ADDR) | MANTIS_GPIF_HIFRDWRN, MANTIS_GPIF_ADDR); |
Manu Abraham | 41e840b | 2009-12-02 21:57:10 -0300 | [diff] [blame] | 189 | |
| 190 | mmwrite(0, MANTIS_DMA_CTL); |
Marko Ristola | 79d06d4 | 2010-08-07 08:16:15 -0300 | [diff] [blame] | 191 | mantis->last_block = mantis->busy_block = 0; |
Manu Abraham | 41e840b | 2009-12-02 21:57:10 -0300 | [diff] [blame] | 192 | |
| 193 | mmwrite(mmread(MANTIS_INT_MASK) | MANTIS_INT_RISCI, MANTIS_INT_MASK); |
| 194 | |
| 195 | mmwrite(MANTIS_FIFO_EN | MANTIS_DCAP_EN |
| 196 | | MANTIS_RISC_EN, MANTIS_DMA_CTL); |
| 197 | |
| 198 | } |
| 199 | |
| 200 | void mantis_dma_stop(struct mantis_pci *mantis) |
| 201 | { |
Manu Abraham | b3b9614 | 2009-12-04 05:41:11 -0300 | [diff] [blame] | 202 | dprintk(MANTIS_DEBUG, 1, "Mantis Stop DMA engine"); |
Manu Abraham | 41e840b | 2009-12-02 21:57:10 -0300 | [diff] [blame] | 203 | |
Sigmund Augdal | a0c5906 | 2009-12-04 05:13:21 -0300 | [diff] [blame] | 204 | mmwrite((mmread(MANTIS_GPIF_ADDR) & (~(MANTIS_GPIF_HIFRDWRN))), MANTIS_GPIF_ADDR); |
Marko Ristola | e4deee0 | 2009-12-03 05:39:22 -0300 | [diff] [blame] | 205 | |
Manu Abraham | 41e840b | 2009-12-02 21:57:10 -0300 | [diff] [blame] | 206 | mmwrite((mmread(MANTIS_DMA_CTL) & ~(MANTIS_FIFO_EN | |
| 207 | MANTIS_DCAP_EN | |
| 208 | MANTIS_RISC_EN)), MANTIS_DMA_CTL); |
| 209 | |
| 210 | mmwrite(mmread(MANTIS_INT_STAT), MANTIS_INT_STAT); |
| 211 | |
| 212 | mmwrite(mmread(MANTIS_INT_MASK) & ~(MANTIS_INT_RISCI | |
| 213 | MANTIS_INT_RISCEN), MANTIS_INT_MASK); |
| 214 | } |
| 215 | |
| 216 | |
| 217 | void mantis_dma_xfer(unsigned long data) |
| 218 | { |
| 219 | struct mantis_pci *mantis = (struct mantis_pci *) data; |
Manu Abraham | 33c7963 | 2009-12-03 05:44:38 -0300 | [diff] [blame] | 220 | struct mantis_hwconfig *config = mantis->hwconfig; |
Manu Abraham | 41e840b | 2009-12-02 21:57:10 -0300 | [diff] [blame] | 221 | |
Marko Ristola | 79d06d4 | 2010-08-07 08:16:15 -0300 | [diff] [blame] | 222 | while (mantis->last_block != mantis->busy_block) { |
Manu Abraham | b3b9614 | 2009-12-04 05:41:11 -0300 | [diff] [blame] | 223 | dprintk(MANTIS_DEBUG, 1, "last block=[%d] finished block=[%d]", |
Marko Ristola | 79d06d4 | 2010-08-07 08:16:15 -0300 | [diff] [blame] | 224 | mantis->last_block, mantis->busy_block); |
Manu Abraham | 41e840b | 2009-12-02 21:57:10 -0300 | [diff] [blame] | 225 | |
Manu Abraham | f5ae4f6 | 2009-12-15 08:47:21 -0300 | [diff] [blame] | 226 | (config->ts_size ? dvb_dmx_swfilter_204 : dvb_dmx_swfilter) |
Manu Abraham | 41e840b | 2009-12-02 21:57:10 -0300 | [diff] [blame] | 227 | (&mantis->demux, &mantis->buf_cpu[mantis->last_block * MANTIS_BLOCK_BYTES], MANTIS_BLOCK_BYTES); |
| 228 | mantis->last_block = (mantis->last_block + 1) % MANTIS_BLOCK_COUNT; |
| 229 | } |
| 230 | } |