Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2006-2007 PA Semi, Inc
0004  *
0005  * Common functions for DMA access on PA Semi PWRficient
0006  */
0007 
0008 #include <linux/kernel.h>
0009 #include <linux/export.h>
0010 #include <linux/pci.h>
0011 #include <linux/slab.h>
0012 #include <linux/of.h>
0013 #include <linux/of_address.h>
0014 #include <linux/of_irq.h>
0015 #include <linux/sched.h>
0016 
0017 #include <asm/pasemi_dma.h>
0018 
0019 #define MAX_TXCH 64
0020 #define MAX_RXCH 64
0021 #define MAX_FLAGS 64
0022 #define MAX_FUN 8
0023 
0024 static struct pasdma_status *dma_status;
0025 
0026 static void __iomem *iob_regs;
0027 static void __iomem *mac_regs[6];
0028 static void __iomem *dma_regs;
0029 
0030 static int base_hw_irq;
0031 
0032 static int num_txch, num_rxch;
0033 
0034 static struct pci_dev *dma_pdev;
0035 
0036 /* Bitmaps to handle allocation of channels */
0037 
0038 static DECLARE_BITMAP(txch_free, MAX_TXCH);
0039 static DECLARE_BITMAP(rxch_free, MAX_RXCH);
0040 static DECLARE_BITMAP(flags_free, MAX_FLAGS);
0041 static DECLARE_BITMAP(fun_free, MAX_FUN);
0042 
0043 /* pasemi_read_iob_reg - read IOB register
0044  * @reg: Register to read (offset into PCI CFG space)
0045  */
0046 unsigned int pasemi_read_iob_reg(unsigned int reg)
0047 {
0048     return in_le32(iob_regs+reg);
0049 }
0050 EXPORT_SYMBOL(pasemi_read_iob_reg);
0051 
0052 /* pasemi_write_iob_reg - write IOB register
0053  * @reg: Register to write to (offset into PCI CFG space)
0054  * @val: Value to write
0055  */
0056 void pasemi_write_iob_reg(unsigned int reg, unsigned int val)
0057 {
0058     out_le32(iob_regs+reg, val);
0059 }
0060 EXPORT_SYMBOL(pasemi_write_iob_reg);
0061 
0062 /* pasemi_read_mac_reg - read MAC register
0063  * @intf: MAC interface
0064  * @reg: Register to read (offset into PCI CFG space)
0065  */
0066 unsigned int pasemi_read_mac_reg(int intf, unsigned int reg)
0067 {
0068     return in_le32(mac_regs[intf]+reg);
0069 }
0070 EXPORT_SYMBOL(pasemi_read_mac_reg);
0071 
0072 /* pasemi_write_mac_reg - write MAC register
0073  * @intf: MAC interface
0074  * @reg: Register to write to (offset into PCI CFG space)
0075  * @val: Value to write
0076  */
0077 void pasemi_write_mac_reg(int intf, unsigned int reg, unsigned int val)
0078 {
0079     out_le32(mac_regs[intf]+reg, val);
0080 }
0081 EXPORT_SYMBOL(pasemi_write_mac_reg);
0082 
0083 /* pasemi_read_dma_reg - read DMA register
0084  * @reg: Register to read (offset into PCI CFG space)
0085  */
0086 unsigned int pasemi_read_dma_reg(unsigned int reg)
0087 {
0088     return in_le32(dma_regs+reg);
0089 }
0090 EXPORT_SYMBOL(pasemi_read_dma_reg);
0091 
0092 /* pasemi_write_dma_reg - write DMA register
0093  * @reg: Register to write to (offset into PCI CFG space)
0094  * @val: Value to write
0095  */
0096 void pasemi_write_dma_reg(unsigned int reg, unsigned int val)
0097 {
0098     out_le32(dma_regs+reg, val);
0099 }
0100 EXPORT_SYMBOL(pasemi_write_dma_reg);
0101 
0102 static int pasemi_alloc_tx_chan(enum pasemi_dmachan_type type)
0103 {
0104     int bit;
0105     int start, limit;
0106 
0107     switch (type & (TXCHAN_EVT0|TXCHAN_EVT1)) {
0108     case TXCHAN_EVT0:
0109         start = 0;
0110         limit = 10;
0111         break;
0112     case TXCHAN_EVT1:
0113         start = 10;
0114         limit = MAX_TXCH;
0115         break;
0116     default:
0117         start = 0;
0118         limit = MAX_TXCH;
0119         break;
0120     }
0121 retry:
0122     bit = find_next_bit(txch_free, MAX_TXCH, start);
0123     if (bit >= limit)
0124         return -ENOSPC;
0125     if (!test_and_clear_bit(bit, txch_free))
0126         goto retry;
0127 
0128     return bit;
0129 }
0130 
0131 static void pasemi_free_tx_chan(int chan)
0132 {
0133     BUG_ON(test_bit(chan, txch_free));
0134     set_bit(chan, txch_free);
0135 }
0136 
0137 static int pasemi_alloc_rx_chan(void)
0138 {
0139     int bit;
0140 retry:
0141     bit = find_first_bit(rxch_free, MAX_RXCH);
0142     if (bit >= MAX_TXCH)
0143         return -ENOSPC;
0144     if (!test_and_clear_bit(bit, rxch_free))
0145         goto retry;
0146 
0147     return bit;
0148 }
0149 
0150 static void pasemi_free_rx_chan(int chan)
0151 {
0152     BUG_ON(test_bit(chan, rxch_free));
0153     set_bit(chan, rxch_free);
0154 }
0155 
0156 /* pasemi_dma_alloc_chan - Allocate a DMA channel
0157  * @type: Type of channel to allocate
0158  * @total_size: Total size of structure to allocate (to allow for more
0159  *      room behind the structure to be used by the client)
0160  * @offset: Offset in bytes from start of the total structure to the beginning
0161  *      of struct pasemi_dmachan. Needed when struct pasemi_dmachan is
0162  *      not the first member of the client structure.
0163  *
0164  * pasemi_dma_alloc_chan allocates a DMA channel for use by a client. The
0165  * type argument specifies whether it's a RX or TX channel, and in the case
0166  * of TX channels which group it needs to belong to (if any).
0167  *
0168  * Returns a pointer to the total structure allocated on success, NULL
0169  * on failure.
0170  */
0171 void *pasemi_dma_alloc_chan(enum pasemi_dmachan_type type,
0172                 int total_size, int offset)
0173 {
0174     void *buf;
0175     struct pasemi_dmachan *chan;
0176     int chno;
0177 
0178     BUG_ON(total_size < sizeof(struct pasemi_dmachan));
0179 
0180     buf = kzalloc(total_size, GFP_KERNEL);
0181 
0182     if (!buf)
0183         return NULL;
0184     chan = buf + offset;
0185 
0186     chan->priv = buf;
0187 
0188     switch (type & (TXCHAN|RXCHAN)) {
0189     case RXCHAN:
0190         chno = pasemi_alloc_rx_chan();
0191         chan->chno = chno;
0192         chan->irq = irq_create_mapping(NULL,
0193                            base_hw_irq + num_txch + chno);
0194         chan->status = &dma_status->rx_sta[chno];
0195         break;
0196     case TXCHAN:
0197         chno = pasemi_alloc_tx_chan(type);
0198         chan->chno = chno;
0199         chan->irq = irq_create_mapping(NULL, base_hw_irq + chno);
0200         chan->status = &dma_status->tx_sta[chno];
0201         break;
0202     }
0203 
0204     chan->chan_type = type;
0205 
0206     return chan;
0207 }
0208 EXPORT_SYMBOL(pasemi_dma_alloc_chan);
0209 
0210 /* pasemi_dma_free_chan - Free a previously allocated channel
0211  * @chan: Channel to free
0212  *
0213  * Frees a previously allocated channel. It will also deallocate any
0214  * descriptor ring associated with the channel, if allocated.
0215  */
0216 void pasemi_dma_free_chan(struct pasemi_dmachan *chan)
0217 {
0218     if (chan->ring_virt)
0219         pasemi_dma_free_ring(chan);
0220 
0221     switch (chan->chan_type & (RXCHAN|TXCHAN)) {
0222     case RXCHAN:
0223         pasemi_free_rx_chan(chan->chno);
0224         break;
0225     case TXCHAN:
0226         pasemi_free_tx_chan(chan->chno);
0227         break;
0228     }
0229 
0230     kfree(chan->priv);
0231 }
0232 EXPORT_SYMBOL(pasemi_dma_free_chan);
0233 
0234 /* pasemi_dma_alloc_ring - Allocate descriptor ring for a channel
0235  * @chan: Channel for which to allocate
0236  * @ring_size: Ring size in 64-bit (8-byte) words
0237  *
0238  * Allocate a descriptor ring for a channel. Returns 0 on success, errno
0239  * on failure. The passed in struct pasemi_dmachan is updated with the
0240  * virtual and DMA addresses of the ring.
0241  */
0242 int pasemi_dma_alloc_ring(struct pasemi_dmachan *chan, int ring_size)
0243 {
0244     BUG_ON(chan->ring_virt);
0245 
0246     chan->ring_size = ring_size;
0247 
0248     chan->ring_virt = dma_alloc_coherent(&dma_pdev->dev,
0249                          ring_size * sizeof(u64),
0250                          &chan->ring_dma, GFP_KERNEL);
0251 
0252     if (!chan->ring_virt)
0253         return -ENOMEM;
0254 
0255     return 0;
0256 }
0257 EXPORT_SYMBOL(pasemi_dma_alloc_ring);
0258 
0259 /* pasemi_dma_free_ring - Free an allocated descriptor ring for a channel
0260  * @chan: Channel for which to free the descriptor ring
0261  *
0262  * Frees a previously allocated descriptor ring for a channel.
0263  */
0264 void pasemi_dma_free_ring(struct pasemi_dmachan *chan)
0265 {
0266     BUG_ON(!chan->ring_virt);
0267 
0268     dma_free_coherent(&dma_pdev->dev, chan->ring_size * sizeof(u64),
0269               chan->ring_virt, chan->ring_dma);
0270     chan->ring_virt = NULL;
0271     chan->ring_size = 0;
0272     chan->ring_dma = 0;
0273 }
0274 EXPORT_SYMBOL(pasemi_dma_free_ring);
0275 
0276 /* pasemi_dma_start_chan - Start a DMA channel
0277  * @chan: Channel to start
0278  * @cmdsta: Additional CCMDSTA/TCMDSTA bits to write
0279  *
0280  * Enables (starts) a DMA channel with optional additional arguments.
0281  */
0282 void pasemi_dma_start_chan(const struct pasemi_dmachan *chan, const u32 cmdsta)
0283 {
0284     if (chan->chan_type == RXCHAN)
0285         pasemi_write_dma_reg(PAS_DMA_RXCHAN_CCMDSTA(chan->chno),
0286                      cmdsta | PAS_DMA_RXCHAN_CCMDSTA_EN);
0287     else
0288         pasemi_write_dma_reg(PAS_DMA_TXCHAN_TCMDSTA(chan->chno),
0289                      cmdsta | PAS_DMA_TXCHAN_TCMDSTA_EN);
0290 }
0291 EXPORT_SYMBOL(pasemi_dma_start_chan);
0292 
0293 /* pasemi_dma_stop_chan - Stop a DMA channel
0294  * @chan: Channel to stop
0295  *
0296  * Stops (disables) a DMA channel. This is done by setting the ST bit in the
0297  * CMDSTA register and waiting on the ACT (active) bit to clear, then
0298  * finally disabling the whole channel.
0299  *
0300  * This function will only try for a short while for the channel to stop, if
0301  * it doesn't it will return failure.
0302  *
0303  * Returns 1 on success, 0 on failure.
0304  */
0305 #define MAX_RETRIES 5000
0306 int pasemi_dma_stop_chan(const struct pasemi_dmachan *chan)
0307 {
0308     int reg, retries;
0309     u32 sta;
0310 
0311     if (chan->chan_type == RXCHAN) {
0312         reg = PAS_DMA_RXCHAN_CCMDSTA(chan->chno);
0313         pasemi_write_dma_reg(reg, PAS_DMA_RXCHAN_CCMDSTA_ST);
0314         for (retries = 0; retries < MAX_RETRIES; retries++) {
0315             sta = pasemi_read_dma_reg(reg);
0316             if (!(sta & PAS_DMA_RXCHAN_CCMDSTA_ACT)) {
0317                 pasemi_write_dma_reg(reg, 0);
0318                 return 1;
0319             }
0320             cond_resched();
0321         }
0322     } else {
0323         reg = PAS_DMA_TXCHAN_TCMDSTA(chan->chno);
0324         pasemi_write_dma_reg(reg, PAS_DMA_TXCHAN_TCMDSTA_ST);
0325         for (retries = 0; retries < MAX_RETRIES; retries++) {
0326             sta = pasemi_read_dma_reg(reg);
0327             if (!(sta & PAS_DMA_TXCHAN_TCMDSTA_ACT)) {
0328                 pasemi_write_dma_reg(reg, 0);
0329                 return 1;
0330             }
0331             cond_resched();
0332         }
0333     }
0334 
0335     return 0;
0336 }
0337 EXPORT_SYMBOL(pasemi_dma_stop_chan);
0338 
0339 /* pasemi_dma_alloc_buf - Allocate a buffer to use for DMA
0340  * @chan: Channel to allocate for
0341  * @size: Size of buffer in bytes
0342  * @handle: DMA handle
0343  *
0344  * Allocate a buffer to be used by the DMA engine for read/write,
0345  * similar to dma_alloc_coherent().
0346  *
0347  * Returns the virtual address of the buffer, or NULL in case of failure.
0348  */
0349 void *pasemi_dma_alloc_buf(struct pasemi_dmachan *chan, int size,
0350                dma_addr_t *handle)
0351 {
0352     return dma_alloc_coherent(&dma_pdev->dev, size, handle, GFP_KERNEL);
0353 }
0354 EXPORT_SYMBOL(pasemi_dma_alloc_buf);
0355 
0356 /* pasemi_dma_free_buf - Free a buffer used for DMA
0357  * @chan: Channel the buffer was allocated for
0358  * @size: Size of buffer in bytes
0359  * @handle: DMA handle
0360  *
0361  * Frees a previously allocated buffer.
0362  */
0363 void pasemi_dma_free_buf(struct pasemi_dmachan *chan, int size,
0364              dma_addr_t *handle)
0365 {
0366     dma_free_coherent(&dma_pdev->dev, size, handle, GFP_KERNEL);
0367 }
0368 EXPORT_SYMBOL(pasemi_dma_free_buf);
0369 
0370 /* pasemi_dma_alloc_flag - Allocate a flag (event) for channel synchronization
0371  *
0372  * Allocates a flag for use with channel synchronization (event descriptors).
0373  * Returns allocated flag (0-63), < 0 on error.
0374  */
0375 int pasemi_dma_alloc_flag(void)
0376 {
0377     int bit;
0378 
0379 retry:
0380     bit = find_first_bit(flags_free, MAX_FLAGS);
0381     if (bit >= MAX_FLAGS)
0382         return -ENOSPC;
0383     if (!test_and_clear_bit(bit, flags_free))
0384         goto retry;
0385 
0386     return bit;
0387 }
0388 EXPORT_SYMBOL(pasemi_dma_alloc_flag);
0389 
0390 
0391 /* pasemi_dma_free_flag - Deallocates a flag (event)
0392  * @flag: Flag number to deallocate
0393  *
0394  * Frees up a flag so it can be reused for other purposes.
0395  */
0396 void pasemi_dma_free_flag(int flag)
0397 {
0398     BUG_ON(test_bit(flag, flags_free));
0399     BUG_ON(flag >= MAX_FLAGS);
0400     set_bit(flag, flags_free);
0401 }
0402 EXPORT_SYMBOL(pasemi_dma_free_flag);
0403 
0404 
0405 /* pasemi_dma_set_flag - Sets a flag (event) to 1
0406  * @flag: Flag number to set active
0407  *
0408  * Sets the flag provided to 1.
0409  */
0410 void pasemi_dma_set_flag(int flag)
0411 {
0412     BUG_ON(flag >= MAX_FLAGS);
0413     if (flag < 32)
0414         pasemi_write_dma_reg(PAS_DMA_TXF_SFLG0, 1 << flag);
0415     else
0416         pasemi_write_dma_reg(PAS_DMA_TXF_SFLG1, 1 << flag);
0417 }
0418 EXPORT_SYMBOL(pasemi_dma_set_flag);
0419 
0420 /* pasemi_dma_clear_flag - Sets a flag (event) to 0
0421  * @flag: Flag number to set inactive
0422  *
0423  * Sets the flag provided to 0.
0424  */
0425 void pasemi_dma_clear_flag(int flag)
0426 {
0427     BUG_ON(flag >= MAX_FLAGS);
0428     if (flag < 32)
0429         pasemi_write_dma_reg(PAS_DMA_TXF_CFLG0, 1 << flag);
0430     else
0431         pasemi_write_dma_reg(PAS_DMA_TXF_CFLG1, 1 << flag);
0432 }
0433 EXPORT_SYMBOL(pasemi_dma_clear_flag);
0434 
0435 /* pasemi_dma_alloc_fun - Allocate a function engine
0436  *
0437  * Allocates a function engine to use for crypto/checksum offload
0438  * Returns allocated engine (0-8), < 0 on error.
0439  */
0440 int pasemi_dma_alloc_fun(void)
0441 {
0442     int bit;
0443 
0444 retry:
0445     bit = find_first_bit(fun_free, MAX_FLAGS);
0446     if (bit >= MAX_FLAGS)
0447         return -ENOSPC;
0448     if (!test_and_clear_bit(bit, fun_free))
0449         goto retry;
0450 
0451     return bit;
0452 }
0453 EXPORT_SYMBOL(pasemi_dma_alloc_fun);
0454 
0455 
0456 /* pasemi_dma_free_fun - Deallocates a function engine
0457  * @flag: Engine number to deallocate
0458  *
0459  * Frees up a function engine so it can be used for other purposes.
0460  */
0461 void pasemi_dma_free_fun(int fun)
0462 {
0463     BUG_ON(test_bit(fun, fun_free));
0464     BUG_ON(fun >= MAX_FLAGS);
0465     set_bit(fun, fun_free);
0466 }
0467 EXPORT_SYMBOL(pasemi_dma_free_fun);
0468 
0469 
0470 static void *map_onedev(struct pci_dev *p, int index)
0471 {
0472     struct device_node *dn;
0473     void __iomem *ret;
0474 
0475     dn = pci_device_to_OF_node(p);
0476     if (!dn)
0477         goto fallback;
0478 
0479     ret = of_iomap(dn, index);
0480     if (!ret)
0481         goto fallback;
0482 
0483     return ret;
0484 fallback:
0485     /* This is hardcoded and ugly, but we have some firmware versions
0486      * that don't provide the register space in the device tree. Luckily
0487      * they are at well-known locations so we can just do the math here.
0488      */
0489     return ioremap(0xe0000000 + (p->devfn << 12), 0x2000);
0490 }
0491 
0492 /* pasemi_dma_init - Initialize the PA Semi DMA library
0493  *
0494  * This function initializes the DMA library. It must be called before
0495  * any other function in the library.
0496  *
0497  * Returns 0 on success, errno on failure.
0498  */
0499 int pasemi_dma_init(void)
0500 {
0501     static DEFINE_SPINLOCK(init_lock);
0502     struct pci_dev *iob_pdev;
0503     struct pci_dev *pdev;
0504     struct resource res;
0505     struct device_node *dn;
0506     int i, intf, err = 0;
0507     unsigned long timeout;
0508     u32 tmp;
0509 
0510     if (!machine_is(pasemi))
0511         return -ENODEV;
0512 
0513     spin_lock(&init_lock);
0514 
0515     /* Make sure we haven't already initialized */
0516     if (dma_pdev)
0517         goto out;
0518 
0519     iob_pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa001, NULL);
0520     if (!iob_pdev) {
0521         BUG();
0522         pr_warn("Can't find I/O Bridge\n");
0523         err = -ENODEV;
0524         goto out;
0525     }
0526     iob_regs = map_onedev(iob_pdev, 0);
0527 
0528     dma_pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa007, NULL);
0529     if (!dma_pdev) {
0530         BUG();
0531         pr_warn("Can't find DMA controller\n");
0532         err = -ENODEV;
0533         goto out;
0534     }
0535     dma_regs = map_onedev(dma_pdev, 0);
0536     base_hw_irq = virq_to_hw(dma_pdev->irq);
0537 
0538     pci_read_config_dword(dma_pdev, PAS_DMA_CAP_TXCH, &tmp);
0539     num_txch = (tmp & PAS_DMA_CAP_TXCH_TCHN_M) >> PAS_DMA_CAP_TXCH_TCHN_S;
0540 
0541     pci_read_config_dword(dma_pdev, PAS_DMA_CAP_RXCH, &tmp);
0542     num_rxch = (tmp & PAS_DMA_CAP_RXCH_RCHN_M) >> PAS_DMA_CAP_RXCH_RCHN_S;
0543 
0544     intf = 0;
0545     for (pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa006, NULL);
0546          pdev;
0547          pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa006, pdev))
0548         mac_regs[intf++] = map_onedev(pdev, 0);
0549 
0550     pci_dev_put(pdev);
0551 
0552     for (pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa005, NULL);
0553          pdev;
0554          pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa005, pdev))
0555         mac_regs[intf++] = map_onedev(pdev, 0);
0556 
0557     pci_dev_put(pdev);
0558 
0559     dn = pci_device_to_OF_node(iob_pdev);
0560     if (dn)
0561         err = of_address_to_resource(dn, 1, &res);
0562     if (!dn || err) {
0563         /* Fallback for old firmware */
0564         res.start = 0xfd800000;
0565         res.end = res.start + 0x1000;
0566     }
0567     dma_status = ioremap_cache(res.start, resource_size(&res));
0568     pci_dev_put(iob_pdev);
0569 
0570     for (i = 0; i < MAX_TXCH; i++)
0571         __set_bit(i, txch_free);
0572 
0573     for (i = 0; i < MAX_RXCH; i++)
0574         __set_bit(i, rxch_free);
0575 
0576     timeout = jiffies + HZ;
0577     pasemi_write_dma_reg(PAS_DMA_COM_RXCMD, 0);
0578     while (pasemi_read_dma_reg(PAS_DMA_COM_RXSTA) & 1) {
0579         if (time_after(jiffies, timeout)) {
0580             pr_warn("Warning: Could not disable RX section\n");
0581             break;
0582         }
0583     }
0584 
0585     timeout = jiffies + HZ;
0586     pasemi_write_dma_reg(PAS_DMA_COM_TXCMD, 0);
0587     while (pasemi_read_dma_reg(PAS_DMA_COM_TXSTA) & 1) {
0588         if (time_after(jiffies, timeout)) {
0589             pr_warn("Warning: Could not disable TX section\n");
0590             break;
0591         }
0592     }
0593 
0594     /* setup resource allocations for the different DMA sections */
0595     tmp = pasemi_read_dma_reg(PAS_DMA_COM_CFG);
0596     pasemi_write_dma_reg(PAS_DMA_COM_CFG, tmp | 0x18000000);
0597 
0598     /* enable tx section */
0599     pasemi_write_dma_reg(PAS_DMA_COM_TXCMD, PAS_DMA_COM_TXCMD_EN);
0600 
0601     /* enable rx section */
0602     pasemi_write_dma_reg(PAS_DMA_COM_RXCMD, PAS_DMA_COM_RXCMD_EN);
0603 
0604     for (i = 0; i < MAX_FLAGS; i++)
0605         __set_bit(i, flags_free);
0606 
0607     for (i = 0; i < MAX_FUN; i++)
0608         __set_bit(i, fun_free);
0609 
0610     /* clear all status flags */
0611     pasemi_write_dma_reg(PAS_DMA_TXF_CFLG0, 0xffffffff);
0612     pasemi_write_dma_reg(PAS_DMA_TXF_CFLG1, 0xffffffff);
0613 
0614     pr_info("PA Semi PWRficient DMA library initialized "
0615         "(%d tx, %d rx channels)\n", num_txch, num_rxch);
0616 
0617 out:
0618     spin_unlock(&init_lock);
0619     return err;
0620 }
0621 EXPORT_SYMBOL(pasemi_dma_init);