Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  Driver for the NXP SAA7164 PCIe bridge
0004  *
0005  *  Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.com>
0006  */
0007 
0008 #include <linux/slab.h>
0009 
0010 #include "saa7164.h"
0011 
0012 /* The PCI address space for buffer handling looks like this:
0013  *
0014  * +-u32 wide-------------+
0015  * |                      +
0016  * +-u64 wide------------------------------------+
0017  * +                                             +
0018  * +----------------------+
0019  * | CurrentBufferPtr     + Pointer to current PCI buffer >-+
0020  * +----------------------+                                 |
0021  * | Unused               +                                 |
0022  * +----------------------+                                 |
0023  * | Pitch                + = 188 (bytes)                   |
0024  * +----------------------+                                 |
0025  * | PCI buffer size      + = pitch * number of lines (312) |
0026  * +----------------------+                                 |
0027  * |0| Buf0 Write Offset  +                                 |
0028  * +----------------------+                                 v
0029  * |1| Buf1 Write Offset  +                                 |
0030  * +----------------------+                                 |
0031  * |2| Buf2 Write Offset  +                                 |
0032  * +----------------------+                                 |
0033  * |3| Buf3 Write Offset  +                                 |
0034  * +----------------------+                                 |
0035  * ... More write offsets                                   |
0036  * +---------------------------------------------+          |
0037  * +0| set of ptrs to PCI pagetables             +          |
0038  * +---------------------------------------------+          |
0039  * +1| set of ptrs to PCI pagetables             + <--------+
0040  * +---------------------------------------------+
0041  * +2| set of ptrs to PCI pagetables             +
0042  * +---------------------------------------------+
0043  * +3| set of ptrs to PCI pagetables             + >--+
0044  * +---------------------------------------------+    |
0045  * ... More buffer pointers                           |  +----------------+
0046  *                          +->| pt[0] TS data  |
0047  *                          |  +----------------+
0048  *                          |
0049  *                          |  +----------------+
0050  *                          +->| pt[1] TS data  |
0051  *                          |  +----------------+
0052  *                          | etc
0053  */
0054 
0055 void saa7164_buffer_display(struct saa7164_buffer *buf)
0056 {
0057     struct saa7164_dev *dev = buf->port->dev;
0058     int i;
0059 
0060     dprintk(DBGLVL_BUF, "%s()   buffer @ 0x%p nr=%d\n",
0061         __func__, buf, buf->idx);
0062     dprintk(DBGLVL_BUF, "  pci_cpu @ 0x%p    dma @ 0x%08llx len = 0x%x\n",
0063         buf->cpu, (long long)buf->dma, buf->pci_size);
0064     dprintk(DBGLVL_BUF, "   pt_cpu @ 0x%p pt_dma @ 0x%08llx len = 0x%x\n",
0065         buf->pt_cpu, (long long)buf->pt_dma, buf->pt_size);
0066 
0067     /* Format the Page Table Entries to point into the data buffer */
0068     for (i = 0 ; i < SAA7164_PT_ENTRIES; i++) {
0069 
0070         dprintk(DBGLVL_BUF, "    pt[%02d] = 0x%p -> 0x%llx\n",
0071             i, buf->pt_cpu, (u64)*(buf->pt_cpu));
0072 
0073     }
0074 }
0075 /* Allocate a new buffer structure and associated PCI space in bytes.
0076  * len must be a multiple of sizeof(u64)
0077  */
0078 struct saa7164_buffer *saa7164_buffer_alloc(struct saa7164_port *port,
0079     u32 len)
0080 {
0081     struct tmHWStreamParameters *params = &port->hw_streamingparams;
0082     struct saa7164_buffer *buf = NULL;
0083     struct saa7164_dev *dev = port->dev;
0084     int i;
0085 
0086     if ((len == 0) || (len >= 65536) || (len % sizeof(u64))) {
0087         log_warn("%s() SAA_ERR_BAD_PARAMETER\n", __func__);
0088         goto ret;
0089     }
0090 
0091     buf = kzalloc(sizeof(*buf), GFP_KERNEL);
0092     if (!buf)
0093         goto ret;
0094 
0095     buf->idx = -1;
0096     buf->port = port;
0097     buf->flags = SAA7164_BUFFER_FREE;
0098     buf->pos = 0;
0099     buf->actual_size = params->pitch * params->numberoflines;
0100     buf->crc = 0;
0101     /* TODO: arg len is being ignored */
0102     buf->pci_size = SAA7164_PT_ENTRIES * 0x1000;
0103     buf->pt_size = (SAA7164_PT_ENTRIES * sizeof(u64)) + 0x1000;
0104 
0105     /* Allocate contiguous memory */
0106     buf->cpu = dma_alloc_coherent(&port->dev->pci->dev, buf->pci_size,
0107                       &buf->dma, GFP_KERNEL);
0108     if (!buf->cpu)
0109         goto fail1;
0110 
0111     buf->pt_cpu = dma_alloc_coherent(&port->dev->pci->dev, buf->pt_size,
0112                      &buf->pt_dma, GFP_KERNEL);
0113     if (!buf->pt_cpu)
0114         goto fail2;
0115 
0116     /* init the buffers to a known pattern, easier during debugging */
0117     memset(buf->cpu, 0xff, buf->pci_size);
0118     buf->crc = crc32(0, buf->cpu, buf->actual_size);
0119     memset(buf->pt_cpu, 0xff, buf->pt_size);
0120 
0121     dprintk(DBGLVL_BUF, "%s()   allocated buffer @ 0x%p (%d pageptrs)\n",
0122         __func__, buf, params->numpagetables);
0123     dprintk(DBGLVL_BUF, "  pci_cpu @ 0x%p    dma @ 0x%08lx len = 0x%x\n",
0124         buf->cpu, (long)buf->dma, buf->pci_size);
0125     dprintk(DBGLVL_BUF, "   pt_cpu @ 0x%p pt_dma @ 0x%08lx len = 0x%x\n",
0126         buf->pt_cpu, (long)buf->pt_dma, buf->pt_size);
0127 
0128     /* Format the Page Table Entries to point into the data buffer */
0129     for (i = 0 ; i < params->numpagetables; i++) {
0130 
0131         *(buf->pt_cpu + i) = buf->dma + (i * 0x1000); /* TODO */
0132         dprintk(DBGLVL_BUF, "    pt[%02d] = 0x%p -> 0x%llx\n",
0133             i, buf->pt_cpu, (u64)*(buf->pt_cpu));
0134 
0135     }
0136 
0137     goto ret;
0138 
0139 fail2:
0140     dma_free_coherent(&port->dev->pci->dev, buf->pci_size, buf->cpu,
0141               buf->dma);
0142 fail1:
0143     kfree(buf);
0144 
0145     buf = NULL;
0146 ret:
0147     return buf;
0148 }
0149 
0150 int saa7164_buffer_dealloc(struct saa7164_buffer *buf)
0151 {
0152     struct saa7164_dev *dev;
0153 
0154     if (!buf || !buf->port)
0155         return SAA_ERR_BAD_PARAMETER;
0156     dev = buf->port->dev;
0157 
0158     dprintk(DBGLVL_BUF, "%s() deallocating buffer @ 0x%p\n",
0159         __func__, buf);
0160 
0161     if (buf->flags != SAA7164_BUFFER_FREE)
0162         log_warn(" freeing a non-free buffer\n");
0163 
0164     dma_free_coherent(&dev->pci->dev, buf->pci_size, buf->cpu, buf->dma);
0165     dma_free_coherent(&dev->pci->dev, buf->pt_size, buf->pt_cpu,
0166               buf->pt_dma);
0167 
0168     kfree(buf);
0169 
0170     return SAA_OK;
0171 }
0172 
0173 int saa7164_buffer_zero_offsets(struct saa7164_port *port, int i)
0174 {
0175     struct saa7164_dev *dev = port->dev;
0176 
0177     if ((i < 0) || (i >= port->hwcfg.buffercount))
0178         return -EINVAL;
0179 
0180     dprintk(DBGLVL_BUF, "%s(idx = %d)\n", __func__, i);
0181 
0182     saa7164_writel(port->bufoffset + (sizeof(u32) * i), 0);
0183 
0184     return 0;
0185 }
0186 
0187 /* Write a buffer into the hardware */
0188 int saa7164_buffer_activate(struct saa7164_buffer *buf, int i)
0189 {
0190     struct saa7164_port *port = buf->port;
0191     struct saa7164_dev *dev = port->dev;
0192 
0193     if ((i < 0) || (i >= port->hwcfg.buffercount))
0194         return -EINVAL;
0195 
0196     dprintk(DBGLVL_BUF, "%s(idx = %d)\n", __func__, i);
0197 
0198     buf->idx = i; /* Note of which buffer list index position we occupy */
0199     buf->flags = SAA7164_BUFFER_BUSY;
0200     buf->pos = 0;
0201 
0202     /* TODO: Review this in light of 32v64 assignments */
0203     saa7164_writel(port->bufoffset + (sizeof(u32) * i), 0);
0204     saa7164_writel(port->bufptr32h + ((sizeof(u32) * 2) * i), buf->pt_dma);
0205     saa7164_writel(port->bufptr32l + ((sizeof(u32) * 2) * i), 0);
0206 
0207     dprintk(DBGLVL_BUF, "   buf[%d] offset 0x%llx (0x%x) buf 0x%llx/%llx (0x%x/%x) nr=%d\n",
0208         buf->idx,
0209         (u64)port->bufoffset + (i * sizeof(u32)),
0210         saa7164_readl(port->bufoffset + (sizeof(u32) * i)),
0211         (u64)port->bufptr32h + ((sizeof(u32) * 2) * i),
0212         (u64)port->bufptr32l + ((sizeof(u32) * 2) * i),
0213         saa7164_readl(port->bufptr32h + ((sizeof(u32) * i) * 2)),
0214         saa7164_readl(port->bufptr32l + ((sizeof(u32) * i) * 2)),
0215         buf->idx);
0216 
0217     return 0;
0218 }
0219 
0220 int saa7164_buffer_cfg_port(struct saa7164_port *port)
0221 {
0222     struct tmHWStreamParameters *params = &port->hw_streamingparams;
0223     struct saa7164_dev *dev = port->dev;
0224     struct saa7164_buffer *buf;
0225     struct list_head *c, *n;
0226     int i = 0;
0227 
0228     dprintk(DBGLVL_BUF, "%s(port=%d)\n", __func__, port->nr);
0229 
0230     saa7164_writel(port->bufcounter, 0);
0231     saa7164_writel(port->pitch, params->pitch);
0232     saa7164_writel(port->bufsize, params->pitch * params->numberoflines);
0233 
0234     dprintk(DBGLVL_BUF, " configured:\n");
0235     dprintk(DBGLVL_BUF, "   lmmio       0x%p\n", dev->lmmio);
0236     dprintk(DBGLVL_BUF, "   bufcounter  0x%x = 0x%x\n", port->bufcounter,
0237         saa7164_readl(port->bufcounter));
0238 
0239     dprintk(DBGLVL_BUF, "   pitch       0x%x = %d\n", port->pitch,
0240         saa7164_readl(port->pitch));
0241 
0242     dprintk(DBGLVL_BUF, "   bufsize     0x%x = %d\n", port->bufsize,
0243         saa7164_readl(port->bufsize));
0244 
0245     dprintk(DBGLVL_BUF, "   buffercount = %d\n", port->hwcfg.buffercount);
0246     dprintk(DBGLVL_BUF, "   bufoffset = 0x%x\n", port->bufoffset);
0247     dprintk(DBGLVL_BUF, "   bufptr32h = 0x%x\n", port->bufptr32h);
0248     dprintk(DBGLVL_BUF, "   bufptr32l = 0x%x\n", port->bufptr32l);
0249 
0250     /* Poke the buffers and offsets into PCI space */
0251     mutex_lock(&port->dmaqueue_lock);
0252     list_for_each_safe(c, n, &port->dmaqueue.list) {
0253         buf = list_entry(c, struct saa7164_buffer, list);
0254 
0255         BUG_ON(buf->flags != SAA7164_BUFFER_FREE);
0256 
0257         /* Place the buffer in the h/w queue */
0258         saa7164_buffer_activate(buf, i);
0259 
0260         /* Don't exceed the device maximum # bufs */
0261         BUG_ON(i > port->hwcfg.buffercount);
0262         i++;
0263 
0264     }
0265     mutex_unlock(&port->dmaqueue_lock);
0266 
0267     return 0;
0268 }
0269 
0270 struct saa7164_user_buffer *saa7164_buffer_alloc_user(struct saa7164_dev *dev,
0271     u32 len)
0272 {
0273     struct saa7164_user_buffer *buf;
0274 
0275     buf = kzalloc(sizeof(*buf), GFP_KERNEL);
0276     if (!buf)
0277         return NULL;
0278 
0279     buf->data = kzalloc(len, GFP_KERNEL);
0280 
0281     if (!buf->data) {
0282         kfree(buf);
0283         return NULL;
0284     }
0285 
0286     buf->actual_size = len;
0287     buf->pos = 0;
0288     buf->crc = 0;
0289 
0290     dprintk(DBGLVL_BUF, "%s()   allocated user buffer @ 0x%p\n",
0291         __func__, buf);
0292 
0293     return buf;
0294 }
0295 
0296 void saa7164_buffer_dealloc_user(struct saa7164_user_buffer *buf)
0297 {
0298     if (!buf)
0299         return;
0300 
0301     kfree(buf->data);
0302     buf->data = NULL;
0303 
0304     kfree(buf);
0305 }