1/* 2 * Omnitek Scatter-Gather DMA Controller 3 * 4 * Copyright 2012-2015 Cisco Systems, Inc. and/or its affiliates. 5 * All rights reserved. 6 * 7 * This program is free software; you may redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; version 2 of the License. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 12 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 13 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 15 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 16 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 17 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 18 * SOFTWARE. 19 */ 20 21#include <linux/string.h> 22#include <linux/io.h> 23#include <linux/pci_regs.h> 24#include <linux/spinlock.h> 25 26#include "cobalt-driver.h" 27#include "cobalt-omnitek.h" 28 29/* descriptor */ 30#define END_OF_CHAIN (1 << 1) 31#define INTERRUPT_ENABLE (1 << 2) 32#define WRITE_TO_PCI (1 << 3) 33#define READ_FROM_PCI (0 << 3) 34#define DESCRIPTOR_FLAG_MSK (END_OF_CHAIN | INTERRUPT_ENABLE | WRITE_TO_PCI) 35#define NEXT_ADRS_MSK 0xffffffe0 36 37/* control/status register */ 38#define ENABLE (1 << 0) 39#define START (1 << 1) 40#define ABORT (1 << 2) 41#define DONE (1 << 4) 42#define SG_INTERRUPT (1 << 5) 43#define EVENT_INTERRUPT (1 << 6) 44#define SCATTER_GATHER_MODE (1 << 8) 45#define DISABLE_VIDEO_RESYNC (1 << 9) 46#define EVENT_INTERRUPT_ENABLE (1 << 10) 47#define DIRECTIONAL_MSK (3 << 16) 48#define INPUT_ONLY (0 << 16) 49#define OUTPUT_ONLY (1 << 16) 50#define BIDIRECTIONAL (2 << 16) 51#define DMA_TYPE_MEMORY (0 << 18) 52#define DMA_TYPE_FIFO (1 << 18) 53 54#define BASE (cobalt->bar0) 55#define CAPABILITY_HEADER (BASE) 56#define CAPABILITY_REGISTER (BASE + 0x04) 57#define PCI_64BIT (1 << 8) 58#define LOCAL_64BIT (1 << 9) 59#define INTERRUPT_STATUS (BASE + 0x08) 60#define PCI(c) (BASE + 0x40 + ((c) * 0x40)) 61#define SIZE(c) (BASE + 0x58 + ((c) * 0x40)) 62#define DESCRIPTOR(c) (BASE + 0x50 + ((c) * 0x40)) 63#define CS_REG(c) (BASE + 0x60 + ((c) * 0x40)) 64#define BYTES_TRANSFERRED(c) (BASE + 0x64 + ((c) * 0x40)) 65 66 67static char *get_dma_direction(u32 status) 68{ 69 switch (status & DIRECTIONAL_MSK) { 70 case INPUT_ONLY: return "Input"; 71 case OUTPUT_ONLY: return "Output"; 72 case BIDIRECTIONAL: return "Bidirectional"; 73 } 74 return ""; 75} 76 77static void show_dma_capability(struct cobalt *cobalt) 78{ 79 u32 header = ioread32(CAPABILITY_HEADER); 80 u32 capa = ioread32(CAPABILITY_REGISTER); 81 u32 i; 82 83 cobalt_info("Omnitek DMA capability: ID 0x%02x Version 0x%02x Next 0x%x Size 0x%x\n", 84 header & 0xff, (header >> 8) & 0xff, 85 (header >> 16) & 0xffff, (capa >> 24) & 0xff); 86 87 switch ((capa >> 8) & 0x3) { 88 case 0: 89 cobalt_info("Omnitek DMA: 32 bits PCIe and Local\n"); 90 break; 91 case 1: 92 cobalt_info("Omnitek DMA: 64 bits PCIe, 32 bits Local\n"); 93 break; 94 case 3: 95 cobalt_info("Omnitek DMA: 64 bits PCIe and Local\n"); 96 break; 97 } 98 99 for (i = 0; i < (capa & 0xf); i++) { 100 u32 status = ioread32(CS_REG(i)); 101 102 cobalt_info("Omnitek DMA channel #%d: %s %s\n", i, 103 status & DMA_TYPE_FIFO ? "FIFO" : "MEMORY", 104 get_dma_direction(status)); 105 } 106} 107 108void omni_sg_dma_start(struct cobalt_stream *s, struct sg_dma_desc_info *desc) 109{ 110 struct cobalt *cobalt = s->cobalt; 111 112 iowrite32((u32)((u64)desc->bus >> 32), DESCRIPTOR(s->dma_channel) + 4); 113 iowrite32((u32)desc->bus & NEXT_ADRS_MSK, DESCRIPTOR(s->dma_channel)); 114 iowrite32(ENABLE | SCATTER_GATHER_MODE | START, CS_REG(s->dma_channel)); 115} 116 117bool is_dma_done(struct cobalt_stream *s) 118{ 119 struct cobalt *cobalt = s->cobalt; 120 121 if (ioread32(CS_REG(s->dma_channel)) & DONE) 122 return true; 123 124 return false; 125} 126 127void omni_sg_dma_abort_channel(struct cobalt_stream *s) 128{ 129 struct cobalt *cobalt = s->cobalt; 130 131 if (is_dma_done(s) == false) 132 iowrite32(ABORT, CS_REG(s->dma_channel)); 133} 134 135int omni_sg_dma_init(struct cobalt *cobalt) 136{ 137 u32 capa = ioread32(CAPABILITY_REGISTER); 138 int i; 139 140 cobalt->first_fifo_channel = 0; 141 cobalt->dma_channels = capa & 0xf; 142 if (capa & PCI_64BIT) 143 cobalt->pci_32_bit = false; 144 else 145 cobalt->pci_32_bit = true; 146 147 for (i = 0; i < cobalt->dma_channels; i++) { 148 u32 status = ioread32(CS_REG(i)); 149 u32 ctrl = ioread32(CS_REG(i)); 150 151 if (!(ctrl & DONE)) 152 iowrite32(ABORT, CS_REG(i)); 153 154 if (!(status & DMA_TYPE_FIFO)) 155 cobalt->first_fifo_channel++; 156 } 157 show_dma_capability(cobalt); 158 return 0; 159} 160 161int descriptor_list_create(struct cobalt *cobalt, 162 struct scatterlist *scatter_list, bool to_pci, unsigned sglen, 163 unsigned size, unsigned width, unsigned stride, 164 struct sg_dma_desc_info *desc) 165{ 166 struct sg_dma_descriptor *d = (struct sg_dma_descriptor *)desc->virt; 167 dma_addr_t next = desc->bus; 168 unsigned offset = 0; 169 unsigned copy_bytes = width; 170 unsigned copied = 0; 171 bool first = true; 172 173 /* Must be 4-byte aligned */ 174 WARN_ON(sg_dma_address(scatter_list) & 3); 175 WARN_ON(size & 3); 176 WARN_ON(next & 3); 177 WARN_ON(stride & 3); 178 WARN_ON(stride < width); 179 if (width >= stride) 180 copy_bytes = stride = size; 181 182 while (size) { 183 dma_addr_t addr = sg_dma_address(scatter_list) + offset; 184 unsigned bytes; 185 186 if (addr == 0) 187 return -EFAULT; 188 if (cobalt->pci_32_bit) { 189 WARN_ON((u64)addr >> 32); 190 if ((u64)addr >> 32) 191 return -EFAULT; 192 } 193 194 /* PCIe address */ 195 d->pci_l = addr & 0xffffffff; 196 /* If dma_addr_t is 32 bits, then addr >> 32 is actually the 197 equivalent of addr >> 0 in gcc. So must cast to u64. */ 198 d->pci_h = (u64)addr >> 32; 199 200 /* Sync to start of streaming frame */ 201 d->local = 0; 202 d->reserved0 = 0; 203 204 /* Transfer bytes */ 205 bytes = min(sg_dma_len(scatter_list) - offset, 206 copy_bytes - copied); 207 208 if (first) { 209 if (to_pci) 210 d->local = 0x11111111; 211 first = false; 212 if (sglen == 1) { 213 /* Make sure there are always at least two 214 * descriptors */ 215 d->bytes = (bytes / 2) & ~3; 216 d->reserved1 = 0; 217 size -= d->bytes; 218 copied += d->bytes; 219 offset += d->bytes; 220 addr += d->bytes; 221 next += sizeof(struct sg_dma_descriptor); 222 d->next_h = (u32)((u64)next >> 32); 223 d->next_l = (u32)next | 224 (to_pci ? WRITE_TO_PCI : 0); 225 bytes -= d->bytes; 226 d++; 227 /* PCIe address */ 228 d->pci_l = addr & 0xffffffff; 229 /* If dma_addr_t is 32 bits, then addr >> 32 230 * is actually the equivalent of addr >> 0 in 231 * gcc. So must cast to u64. */ 232 d->pci_h = (u64)addr >> 32; 233 234 /* Sync to start of streaming frame */ 235 d->local = 0; 236 d->reserved0 = 0; 237 } 238 } 239 240 d->bytes = bytes; 241 d->reserved1 = 0; 242 size -= bytes; 243 copied += bytes; 244 offset += bytes; 245 246 if (copied == copy_bytes) { 247 while (copied < stride) { 248 bytes = min(sg_dma_len(scatter_list) - offset, 249 stride - copied); 250 copied += bytes; 251 offset += bytes; 252 size -= bytes; 253 if (sg_dma_len(scatter_list) == offset) { 254 offset = 0; 255 scatter_list = sg_next(scatter_list); 256 } 257 } 258 copied = 0; 259 } else { 260 offset = 0; 261 scatter_list = sg_next(scatter_list); 262 } 263 264 /* Next descriptor + control bits */ 265 next += sizeof(struct sg_dma_descriptor); 266 if (size == 0) { 267 /* Loopback to the first descriptor */ 268 d->next_h = (u32)((u64)desc->bus >> 32); 269 d->next_l = (u32)desc->bus | 270 (to_pci ? WRITE_TO_PCI : 0) | INTERRUPT_ENABLE; 271 if (!to_pci) 272 d->local = 0x22222222; 273 desc->last_desc_virt = d; 274 } else { 275 d->next_h = (u32)((u64)next >> 32); 276 d->next_l = (u32)next | (to_pci ? WRITE_TO_PCI : 0); 277 } 278 d++; 279 } 280 return 0; 281} 282 283void descriptor_list_chain(struct sg_dma_desc_info *this, 284 struct sg_dma_desc_info *next) 285{ 286 struct sg_dma_descriptor *d = this->last_desc_virt; 287 u32 direction = d->next_l & WRITE_TO_PCI; 288 289 if (next == NULL) { 290 d->next_h = 0; 291 d->next_l = direction | INTERRUPT_ENABLE | END_OF_CHAIN; 292 } else { 293 d->next_h = (u32)((u64)next->bus >> 32); 294 d->next_l = (u32)next->bus | direction | INTERRUPT_ENABLE; 295 } 296} 297 298void *descriptor_list_allocate(struct sg_dma_desc_info *desc, size_t bytes) 299{ 300 desc->size = bytes; 301 desc->virt = dma_alloc_coherent(desc->dev, bytes, 302 &desc->bus, GFP_KERNEL); 303 return desc->virt; 304} 305 306void descriptor_list_free(struct sg_dma_desc_info *desc) 307{ 308 if (desc->virt) 309 dma_free_coherent(desc->dev, desc->size, 310 desc->virt, desc->bus); 311 desc->virt = NULL; 312} 313 314void descriptor_list_interrupt_enable(struct sg_dma_desc_info *desc) 315{ 316 struct sg_dma_descriptor *d = desc->last_desc_virt; 317 318 d->next_l |= INTERRUPT_ENABLE; 319} 320 321void descriptor_list_interrupt_disable(struct sg_dma_desc_info *desc) 322{ 323 struct sg_dma_descriptor *d = desc->last_desc_virt; 324 325 d->next_l &= ~INTERRUPT_ENABLE; 326} 327 328void descriptor_list_loopback(struct sg_dma_desc_info *desc) 329{ 330 struct sg_dma_descriptor *d = desc->last_desc_virt; 331 332 d->next_h = (u32)((u64)desc->bus >> 32); 333 d->next_l = (u32)desc->bus | (d->next_l & DESCRIPTOR_FLAG_MSK); 334} 335 336void descriptor_list_end_of_chain(struct sg_dma_desc_info *desc) 337{ 338 struct sg_dma_descriptor *d = desc->last_desc_virt; 339 340 d->next_l |= END_OF_CHAIN; 341} 342