18ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson/* 28ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * Copyright (C) 2006-2007 PA Semi, Inc 38ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * 48ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * Common functions for DMA access on PA Semi PWRficient 58ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * 68ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * This program is free software; you can redistribute it and/or modify 78ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * it under the terms of the GNU General Public License version 2 as 88ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * published by the Free Software Foundation. 98ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * 108ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * This program is distributed in the hope that it will be useful, 118ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * but WITHOUT ANY WARRANTY; without even the implied warranty of 128ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 138ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * GNU General Public License for more details. 148ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * 158ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * You should have received a copy of the GNU General Public License 168ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * along with this program; if not, write to the Free Software 178ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 188ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson */ 198ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 20afea3278f73c14271ee60ca7593ad74b7a946486Olof Johansson#include <linux/kernel.h> 214b16f8e2d6d64249f0ed3ca7fe2a319d0dde2719Paul Gortmaker#include <linux/export.h> 228ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson#include <linux/pci.h> 235a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 248ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson#include <linux/of.h> 2562fe91bba2325593e00698f902b3201629dad571Paul Gortmaker#include <linux/sched.h> 268ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 278ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson#include <asm/pasemi_dma.h> 288ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 298ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson#define MAX_TXCH 64 308ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson#define MAX_RXCH 64 31f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson#define MAX_FLAGS 64 32dda56df08a28404004bca313d2a1ba1597acd755Olof Johansson#define MAX_FUN 8 338ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 348ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johanssonstatic struct pasdma_status *dma_status; 358ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 368ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johanssonstatic void __iomem *iob_regs; 378ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johanssonstatic void __iomem *mac_regs[6]; 388ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johanssonstatic void __iomem *dma_regs; 398ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 408ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johanssonstatic int base_hw_irq; 418ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 428ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johanssonstatic int num_txch, num_rxch; 438ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 448ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johanssonstatic struct pci_dev *dma_pdev; 458ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 468ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson/* Bitmaps to handle allocation of channels */ 478ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 488ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johanssonstatic DECLARE_BITMAP(txch_free, MAX_TXCH); 498ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johanssonstatic DECLARE_BITMAP(rxch_free, MAX_RXCH); 50f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johanssonstatic DECLARE_BITMAP(flags_free, MAX_FLAGS); 51dda56df08a28404004bca313d2a1ba1597acd755Olof Johanssonstatic DECLARE_BITMAP(fun_free, MAX_FUN); 528ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 538ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson/* pasemi_read_iob_reg - read IOB register 548ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * @reg: Register to read (offset into PCI CFG space) 558ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson */ 568ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johanssonunsigned int pasemi_read_iob_reg(unsigned int reg) 578ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson{ 588ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson return in_le32(iob_regs+reg); 598ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson} 608ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof JohanssonEXPORT_SYMBOL(pasemi_read_iob_reg); 618ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 628ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson/* pasemi_write_iob_reg - write IOB register 638ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * @reg: Register to write to (offset into PCI CFG space) 648ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * @val: Value to write 658ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson */ 668ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johanssonvoid pasemi_write_iob_reg(unsigned int reg, unsigned int val) 678ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson{ 688ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson out_le32(iob_regs+reg, val); 698ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson} 708ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof JohanssonEXPORT_SYMBOL(pasemi_write_iob_reg); 718ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 728ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson/* pasemi_read_mac_reg - read MAC register 738ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * @intf: MAC interface 748ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * @reg: Register to read (offset into PCI CFG space) 758ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson */ 768ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johanssonunsigned int pasemi_read_mac_reg(int intf, unsigned int reg) 778ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson{ 788ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson return in_le32(mac_regs[intf]+reg); 798ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson} 808ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof JohanssonEXPORT_SYMBOL(pasemi_read_mac_reg); 818ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 828ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson/* pasemi_write_mac_reg - write MAC register 838ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * @intf: MAC interface 848ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * @reg: Register to write to (offset into PCI CFG space) 858ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * @val: Value to write 868ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson */ 878ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johanssonvoid pasemi_write_mac_reg(int intf, unsigned int reg, unsigned int val) 888ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson{ 898ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson out_le32(mac_regs[intf]+reg, val); 908ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson} 918ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof JohanssonEXPORT_SYMBOL(pasemi_write_mac_reg); 928ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 938ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson/* pasemi_read_dma_reg - read DMA register 948ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * @reg: Register to read (offset into PCI CFG space) 958ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson */ 968ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johanssonunsigned int pasemi_read_dma_reg(unsigned int reg) 978ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson{ 988ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson return in_le32(dma_regs+reg); 998ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson} 1008ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof JohanssonEXPORT_SYMBOL(pasemi_read_dma_reg); 1018ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 1028ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson/* pasemi_write_dma_reg - write DMA register 1038ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * @reg: Register to write to (offset into PCI CFG space) 1048ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * @val: Value to write 1058ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson */ 1068ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johanssonvoid pasemi_write_dma_reg(unsigned int reg, unsigned int val) 1078ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson{ 1088ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson out_le32(dma_regs+reg, val); 1098ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson} 1108ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof JohanssonEXPORT_SYMBOL(pasemi_write_dma_reg); 1118ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 1128ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johanssonstatic int pasemi_alloc_tx_chan(enum pasemi_dmachan_type type) 1138ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson{ 1148ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson int bit; 1158ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson int start, limit; 1168ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 1178ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson switch (type & (TXCHAN_EVT0|TXCHAN_EVT1)) { 1188ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson case TXCHAN_EVT0: 1198ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson start = 0; 1208ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson limit = 10; 1218ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson break; 1228ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson case TXCHAN_EVT1: 1238ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson start = 10; 1248ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson limit = MAX_TXCH; 1258ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson break; 1268ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson default: 1278ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson start = 0; 1288ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson limit = MAX_TXCH; 1298ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson break; 1308ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson } 1318ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johanssonretry: 1328ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson bit = find_next_bit(txch_free, MAX_TXCH, start); 1338ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson if (bit >= limit) 1348ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson return -ENOSPC; 1358ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson if (!test_and_clear_bit(bit, txch_free)) 1368ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson goto retry; 1378ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 1388ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson return bit; 1398ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson} 1408ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 1418ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johanssonstatic void pasemi_free_tx_chan(int chan) 1428ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson{ 1438ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson BUG_ON(test_bit(chan, txch_free)); 1448ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson set_bit(chan, txch_free); 1458ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson} 1468ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 1478ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johanssonstatic int pasemi_alloc_rx_chan(void) 1488ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson{ 1498ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson int bit; 1508ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johanssonretry: 1518ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson bit = find_first_bit(rxch_free, MAX_RXCH); 1528ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson if (bit >= MAX_TXCH) 1538ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson return -ENOSPC; 1548ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson if (!test_and_clear_bit(bit, rxch_free)) 1558ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson goto retry; 1568ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 1578ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson return bit; 1588ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson} 1598ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 1608ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johanssonstatic void pasemi_free_rx_chan(int chan) 1618ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson{ 1628ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson BUG_ON(test_bit(chan, rxch_free)); 1638ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson set_bit(chan, rxch_free); 1648ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson} 1658ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 1668ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson/* pasemi_dma_alloc_chan - Allocate a DMA channel 1678ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * @type: Type of channel to allocate 1688ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * @total_size: Total size of structure to allocate (to allow for more 1698ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * room behind the structure to be used by the client) 1708ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * @offset: Offset in bytes from start of the total structure to the beginning 1718ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * of struct pasemi_dmachan. Needed when struct pasemi_dmachan is 1728ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * not the first member of the client structure. 1738ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * 1748ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * pasemi_dma_alloc_chan allocates a DMA channel for use by a client. The 1758ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * type argument specifies whether it's a RX or TX channel, and in the case 1768ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * of TX channels which group it needs to belong to (if any). 1778ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * 1788ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * Returns a pointer to the total structure allocated on success, NULL 1798ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * on failure. 1808ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson */ 1818ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johanssonvoid *pasemi_dma_alloc_chan(enum pasemi_dmachan_type type, 1828ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson int total_size, int offset) 1838ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson{ 1848ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson void *buf; 1858ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson struct pasemi_dmachan *chan; 1868ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson int chno; 1878ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 1888ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson BUG_ON(total_size < sizeof(struct pasemi_dmachan)); 1898ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 1908ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson buf = kzalloc(total_size, GFP_KERNEL); 1918ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 1928ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson if (!buf) 1938ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson return NULL; 1948ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson chan = buf + offset; 1958ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 1968ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson chan->priv = buf; 1978ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 1988ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson switch (type & (TXCHAN|RXCHAN)) { 1998ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson case RXCHAN: 2008ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson chno = pasemi_alloc_rx_chan(); 2018ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson chan->chno = chno; 2028ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson chan->irq = irq_create_mapping(NULL, 2038ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson base_hw_irq + num_txch + chno); 2048ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson chan->status = &dma_status->rx_sta[chno]; 2058ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson break; 2068ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson case TXCHAN: 2078ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson chno = pasemi_alloc_tx_chan(type); 2088ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson chan->chno = chno; 2098ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson chan->irq = irq_create_mapping(NULL, base_hw_irq + chno); 2108ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson chan->status = &dma_status->tx_sta[chno]; 2118ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson break; 2128ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson } 2138ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 2148ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson chan->chan_type = type; 2158ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 2168ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson return chan; 2178ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson} 2188ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof JohanssonEXPORT_SYMBOL(pasemi_dma_alloc_chan); 2198ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 2208ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson/* pasemi_dma_free_chan - Free a previously allocated channel 2218ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * @chan: Channel to free 2228ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * 2238ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * Frees a previously allocated channel. It will also deallocate any 2248ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * descriptor ring associated with the channel, if allocated. 2258ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson */ 2268ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johanssonvoid pasemi_dma_free_chan(struct pasemi_dmachan *chan) 2278ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson{ 2288ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson if (chan->ring_virt) 2298ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson pasemi_dma_free_ring(chan); 2308ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 2318ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson switch (chan->chan_type & (RXCHAN|TXCHAN)) { 2328ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson case RXCHAN: 2338ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson pasemi_free_rx_chan(chan->chno); 2348ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson break; 2358ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson case TXCHAN: 2368ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson pasemi_free_tx_chan(chan->chno); 2378ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson break; 2388ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson } 2398ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 2408ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson kfree(chan->priv); 2418ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson} 2428ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof JohanssonEXPORT_SYMBOL(pasemi_dma_free_chan); 2438ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 2448ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson/* pasemi_dma_alloc_ring - Allocate descriptor ring for a channel 2458ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * @chan: Channel for which to allocate 2468ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * @ring_size: Ring size in 64-bit (8-byte) words 2478ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * 2488ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * Allocate a descriptor ring for a channel. Returns 0 on success, errno 2498ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * on failure. The passed in struct pasemi_dmachan is updated with the 2508ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * virtual and DMA addresses of the ring. 2518ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson */ 2528ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johanssonint pasemi_dma_alloc_ring(struct pasemi_dmachan *chan, int ring_size) 2538ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson{ 2548ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson BUG_ON(chan->ring_virt); 2558ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 2568ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson chan->ring_size = ring_size; 2578ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 2588ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson chan->ring_virt = dma_alloc_coherent(&dma_pdev->dev, 2598ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson ring_size * sizeof(u64), 2608ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson &chan->ring_dma, GFP_KERNEL); 2618ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 2628ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson if (!chan->ring_virt) 2638ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson return -ENOMEM; 2648ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 2658ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson memset(chan->ring_virt, 0, ring_size * sizeof(u64)); 2668ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 2678ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson return 0; 2688ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson} 2698ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof JohanssonEXPORT_SYMBOL(pasemi_dma_alloc_ring); 2708ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 2718ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson/* pasemi_dma_free_ring - Free an allocated descriptor ring for a channel 2728ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * @chan: Channel for which to free the descriptor ring 2738ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * 2748ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * Frees a previously allocated descriptor ring for a channel. 2758ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson */ 2768ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johanssonvoid pasemi_dma_free_ring(struct pasemi_dmachan *chan) 2778ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson{ 2788ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson BUG_ON(!chan->ring_virt); 2798ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 2808ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson dma_free_coherent(&dma_pdev->dev, chan->ring_size * sizeof(u64), 2818ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson chan->ring_virt, chan->ring_dma); 2828ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson chan->ring_virt = NULL; 2838ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson chan->ring_size = 0; 2848ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson chan->ring_dma = 0; 2858ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson} 2868ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof JohanssonEXPORT_SYMBOL(pasemi_dma_free_ring); 2878ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 2888ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson/* pasemi_dma_start_chan - Start a DMA channel 2898ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * @chan: Channel to start 2908ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * @cmdsta: Additional CCMDSTA/TCMDSTA bits to write 2918ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * 2928ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * Enables (starts) a DMA channel with optional additional arguments. 2938ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson */ 2948ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johanssonvoid pasemi_dma_start_chan(const struct pasemi_dmachan *chan, const u32 cmdsta) 2958ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson{ 2968ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson if (chan->chan_type == RXCHAN) 2978ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson pasemi_write_dma_reg(PAS_DMA_RXCHAN_CCMDSTA(chan->chno), 2988ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson cmdsta | PAS_DMA_RXCHAN_CCMDSTA_EN); 2998ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson else 3008ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson pasemi_write_dma_reg(PAS_DMA_TXCHAN_TCMDSTA(chan->chno), 3018ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson cmdsta | PAS_DMA_TXCHAN_TCMDSTA_EN); 3028ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson} 3038ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof JohanssonEXPORT_SYMBOL(pasemi_dma_start_chan); 3048ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 3058ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson/* pasemi_dma_stop_chan - Stop a DMA channel 3068ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * @chan: Channel to stop 3078ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * 3088ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * Stops (disables) a DMA channel. This is done by setting the ST bit in the 3098ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * CMDSTA register and waiting on the ACT (active) bit to clear, then 3108ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * finally disabling the whole channel. 3118ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * 3128ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * This function will only try for a short while for the channel to stop, if 3138ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * it doesn't it will return failure. 3148ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * 3158ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * Returns 1 on success, 0 on failure. 3168ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson */ 3178ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson#define MAX_RETRIES 5000 3188ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johanssonint pasemi_dma_stop_chan(const struct pasemi_dmachan *chan) 3198ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson{ 3208ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson int reg, retries; 3218ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson u32 sta; 3228ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 3238ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson if (chan->chan_type == RXCHAN) { 3248ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson reg = PAS_DMA_RXCHAN_CCMDSTA(chan->chno); 3258ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson pasemi_write_dma_reg(reg, PAS_DMA_RXCHAN_CCMDSTA_ST); 3268ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson for (retries = 0; retries < MAX_RETRIES; retries++) { 3278ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson sta = pasemi_read_dma_reg(reg); 3288ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson if (!(sta & PAS_DMA_RXCHAN_CCMDSTA_ACT)) { 3298ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson pasemi_write_dma_reg(reg, 0); 3308ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson return 1; 3318ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson } 3328ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson cond_resched(); 3338ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson } 3348ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson } else { 3358ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson reg = PAS_DMA_TXCHAN_TCMDSTA(chan->chno); 3368ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson pasemi_write_dma_reg(reg, PAS_DMA_TXCHAN_TCMDSTA_ST); 3378ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson for (retries = 0; retries < MAX_RETRIES; retries++) { 3388ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson sta = pasemi_read_dma_reg(reg); 3398ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson if (!(sta & PAS_DMA_TXCHAN_TCMDSTA_ACT)) { 3408ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson pasemi_write_dma_reg(reg, 0); 3418ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson return 1; 3428ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson } 3438ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson cond_resched(); 3448ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson } 3458ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson } 3468ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 3478ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson return 0; 3488ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson} 3498ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof JohanssonEXPORT_SYMBOL(pasemi_dma_stop_chan); 3508ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 3518ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson/* pasemi_dma_alloc_buf - Allocate a buffer to use for DMA 3528ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * @chan: Channel to allocate for 3538ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * @size: Size of buffer in bytes 3548ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * @handle: DMA handle 3558ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * 3568ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * Allocate a buffer to be used by the DMA engine for read/write, 3578ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * similar to dma_alloc_coherent(). 3588ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * 3598ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * Returns the virtual address of the buffer, or NULL in case of failure. 3608ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson */ 3618ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johanssonvoid *pasemi_dma_alloc_buf(struct pasemi_dmachan *chan, int size, 3628ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson dma_addr_t *handle) 3638ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson{ 3648ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson return dma_alloc_coherent(&dma_pdev->dev, size, handle, GFP_KERNEL); 3658ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson} 3668ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof JohanssonEXPORT_SYMBOL(pasemi_dma_alloc_buf); 3678ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 3688ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson/* pasemi_dma_free_buf - Free a buffer used for DMA 3698ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * @chan: Channel the buffer was allocated for 3708ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * @size: Size of buffer in bytes 3718ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * @handle: DMA handle 3728ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * 3738ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * Frees a previously allocated buffer. 3748ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson */ 3758ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johanssonvoid pasemi_dma_free_buf(struct pasemi_dmachan *chan, int size, 3768ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson dma_addr_t *handle) 3778ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson{ 3788ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson dma_free_coherent(&dma_pdev->dev, size, handle, GFP_KERNEL); 3798ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson} 3808ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof JohanssonEXPORT_SYMBOL(pasemi_dma_free_buf); 3818ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 38225985edcedea6396277003854657b5f3cb31a628Lucas De Marchi/* pasemi_dma_alloc_flag - Allocate a flag (event) for channel synchronization 383f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson * 38425985edcedea6396277003854657b5f3cb31a628Lucas De Marchi * Allocates a flag for use with channel synchronization (event descriptors). 385f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson * Returns allocated flag (0-63), < 0 on error. 386f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson */ 387f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johanssonint pasemi_dma_alloc_flag(void) 388f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson{ 389f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson int bit; 390f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson 391f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johanssonretry: 392f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson bit = find_next_bit(flags_free, MAX_FLAGS, 0); 393f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson if (bit >= MAX_FLAGS) 394f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson return -ENOSPC; 395f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson if (!test_and_clear_bit(bit, flags_free)) 396f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson goto retry; 397f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson 398f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson return bit; 399f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson} 400f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof JohanssonEXPORT_SYMBOL(pasemi_dma_alloc_flag); 401f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson 402f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson 403f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson/* pasemi_dma_free_flag - Deallocates a flag (event) 404f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson * @flag: Flag number to deallocate 405f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson * 406f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson * Frees up a flag so it can be reused for other purposes. 407f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson */ 408f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johanssonvoid pasemi_dma_free_flag(int flag) 409f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson{ 410f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson BUG_ON(test_bit(flag, flags_free)); 411f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson BUG_ON(flag >= MAX_FLAGS); 412f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson set_bit(flag, flags_free); 413f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson} 414f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof JohanssonEXPORT_SYMBOL(pasemi_dma_free_flag); 415f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson 416f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson 417f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson/* pasemi_dma_set_flag - Sets a flag (event) to 1 418f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson * @flag: Flag number to set active 419f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson * 420f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson * Sets the flag provided to 1. 421f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson */ 422f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johanssonvoid pasemi_dma_set_flag(int flag) 423f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson{ 424f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson BUG_ON(flag >= MAX_FLAGS); 425f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson if (flag < 32) 426f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson pasemi_write_dma_reg(PAS_DMA_TXF_SFLG0, 1 << flag); 427f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson else 428f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson pasemi_write_dma_reg(PAS_DMA_TXF_SFLG1, 1 << flag); 429f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson} 430f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof JohanssonEXPORT_SYMBOL(pasemi_dma_set_flag); 431f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson 432f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson/* pasemi_dma_clear_flag - Sets a flag (event) to 0 433f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson * @flag: Flag number to set inactive 434f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson * 435f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson * Sets the flag provided to 0. 436f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson */ 437f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johanssonvoid pasemi_dma_clear_flag(int flag) 438f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson{ 439f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson BUG_ON(flag >= MAX_FLAGS); 440f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson if (flag < 32) 441f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson pasemi_write_dma_reg(PAS_DMA_TXF_CFLG0, 1 << flag); 442f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson else 443f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson pasemi_write_dma_reg(PAS_DMA_TXF_CFLG1, 1 << flag); 444f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson} 445f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof JohanssonEXPORT_SYMBOL(pasemi_dma_clear_flag); 446f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson 447dda56df08a28404004bca313d2a1ba1597acd755Olof Johansson/* pasemi_dma_alloc_fun - Allocate a function engine 448dda56df08a28404004bca313d2a1ba1597acd755Olof Johansson * 449dda56df08a28404004bca313d2a1ba1597acd755Olof Johansson * Allocates a function engine to use for crypto/checksum offload 450dda56df08a28404004bca313d2a1ba1597acd755Olof Johansson * Returns allocated engine (0-8), < 0 on error. 451dda56df08a28404004bca313d2a1ba1597acd755Olof Johansson */ 452dda56df08a28404004bca313d2a1ba1597acd755Olof Johanssonint pasemi_dma_alloc_fun(void) 453dda56df08a28404004bca313d2a1ba1597acd755Olof Johansson{ 454dda56df08a28404004bca313d2a1ba1597acd755Olof Johansson int bit; 455dda56df08a28404004bca313d2a1ba1597acd755Olof Johansson 456dda56df08a28404004bca313d2a1ba1597acd755Olof Johanssonretry: 457dda56df08a28404004bca313d2a1ba1597acd755Olof Johansson bit = find_next_bit(fun_free, MAX_FLAGS, 0); 458dda56df08a28404004bca313d2a1ba1597acd755Olof Johansson if (bit >= MAX_FLAGS) 459dda56df08a28404004bca313d2a1ba1597acd755Olof Johansson return -ENOSPC; 460dda56df08a28404004bca313d2a1ba1597acd755Olof Johansson if (!test_and_clear_bit(bit, fun_free)) 461dda56df08a28404004bca313d2a1ba1597acd755Olof Johansson goto retry; 462dda56df08a28404004bca313d2a1ba1597acd755Olof Johansson 463dda56df08a28404004bca313d2a1ba1597acd755Olof Johansson return bit; 464dda56df08a28404004bca313d2a1ba1597acd755Olof Johansson} 465dda56df08a28404004bca313d2a1ba1597acd755Olof JohanssonEXPORT_SYMBOL(pasemi_dma_alloc_fun); 466dda56df08a28404004bca313d2a1ba1597acd755Olof Johansson 467dda56df08a28404004bca313d2a1ba1597acd755Olof Johansson 468dda56df08a28404004bca313d2a1ba1597acd755Olof Johansson/* pasemi_dma_free_fun - Deallocates a function engine 469dda56df08a28404004bca313d2a1ba1597acd755Olof Johansson * @flag: Engine number to deallocate 470dda56df08a28404004bca313d2a1ba1597acd755Olof Johansson * 471dda56df08a28404004bca313d2a1ba1597acd755Olof Johansson * Frees up a function engine so it can be used for other purposes. 472dda56df08a28404004bca313d2a1ba1597acd755Olof Johansson */ 473dda56df08a28404004bca313d2a1ba1597acd755Olof Johanssonvoid pasemi_dma_free_fun(int fun) 474dda56df08a28404004bca313d2a1ba1597acd755Olof Johansson{ 475dda56df08a28404004bca313d2a1ba1597acd755Olof Johansson BUG_ON(test_bit(fun, fun_free)); 476dda56df08a28404004bca313d2a1ba1597acd755Olof Johansson BUG_ON(fun >= MAX_FLAGS); 477dda56df08a28404004bca313d2a1ba1597acd755Olof Johansson set_bit(fun, fun_free); 478dda56df08a28404004bca313d2a1ba1597acd755Olof Johansson} 479dda56df08a28404004bca313d2a1ba1597acd755Olof JohanssonEXPORT_SYMBOL(pasemi_dma_free_fun); 480dda56df08a28404004bca313d2a1ba1597acd755Olof Johansson 481dda56df08a28404004bca313d2a1ba1597acd755Olof Johansson 4828ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johanssonstatic void *map_onedev(struct pci_dev *p, int index) 4838ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson{ 4848ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson struct device_node *dn; 4858ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson void __iomem *ret; 4868ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 4878ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson dn = pci_device_to_OF_node(p); 4888ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson if (!dn) 4898ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson goto fallback; 4908ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 4918ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson ret = of_iomap(dn, index); 4928ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson if (!ret) 4938ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson goto fallback; 4948ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 4958ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson return ret; 4968ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johanssonfallback: 4978ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson /* This is hardcoded and ugly, but we have some firmware versions 4988ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * that don't provide the register space in the device tree. Luckily 4998ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * they are at well-known locations so we can just do the math here. 5008ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson */ 5018ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson return ioremap(0xe0000000 + (p->devfn << 12), 0x2000); 5028ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson} 5038ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 5048ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson/* pasemi_dma_init - Initialize the PA Semi DMA library 5058ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * 5068ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * This function initializes the DMA library. It must be called before 5078ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * any other function in the library. 5088ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * 5098ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson * Returns 0 on success, errno on failure. 5108ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson */ 5118ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johanssonint pasemi_dma_init(void) 5128ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson{ 5131d5bc03a8183d12c7daf4e7c69cce8d9c4b9a86bJulia Lawall static DEFINE_SPINLOCK(init_lock); 5148ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson struct pci_dev *iob_pdev; 5158ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson struct pci_dev *pdev; 5168ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson struct resource res; 5178ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson struct device_node *dn; 5188ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson int i, intf, err = 0; 519afea3278f73c14271ee60ca7593ad74b7a946486Olof Johansson unsigned long timeout; 5208ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson u32 tmp; 5218ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 5228ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson if (!machine_is(pasemi)) 5238ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson return -ENODEV; 5248ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 5258ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson spin_lock(&init_lock); 5268ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 5278ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson /* Make sure we haven't already initialized */ 5288ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson if (dma_pdev) 5298ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson goto out; 5308ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 5318ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson iob_pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa001, NULL); 5328ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson if (!iob_pdev) { 5338ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson BUG(); 5348ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson printk(KERN_WARNING "Can't find I/O Bridge\n"); 5358ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson err = -ENODEV; 5368ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson goto out; 5378ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson } 5388ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson iob_regs = map_onedev(iob_pdev, 0); 5398ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 5408ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson dma_pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa007, NULL); 5418ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson if (!dma_pdev) { 5428ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson BUG(); 5438ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson printk(KERN_WARNING "Can't find DMA controller\n"); 5448ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson err = -ENODEV; 5458ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson goto out; 5468ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson } 5478ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson dma_regs = map_onedev(dma_pdev, 0); 5488ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson base_hw_irq = virq_to_hw(dma_pdev->irq); 5498ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 5508ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson pci_read_config_dword(dma_pdev, PAS_DMA_CAP_TXCH, &tmp); 5518ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson num_txch = (tmp & PAS_DMA_CAP_TXCH_TCHN_M) >> PAS_DMA_CAP_TXCH_TCHN_S; 5528ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 5538ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson pci_read_config_dword(dma_pdev, PAS_DMA_CAP_RXCH, &tmp); 5548ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson num_rxch = (tmp & PAS_DMA_CAP_RXCH_RCHN_M) >> PAS_DMA_CAP_RXCH_RCHN_S; 5558ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 5568ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson intf = 0; 5578ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson for (pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa006, NULL); 5588ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson pdev; 5598ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa006, pdev)) 5608ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson mac_regs[intf++] = map_onedev(pdev, 0); 5618ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 5628ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson pci_dev_put(pdev); 5638ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 5648ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson for (pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa005, NULL); 5658ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson pdev; 5668ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa005, pdev)) 5678ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson mac_regs[intf++] = map_onedev(pdev, 0); 5688ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 5698ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson pci_dev_put(pdev); 5708ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 5718ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson dn = pci_device_to_OF_node(iob_pdev); 5728ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson if (dn) 5738ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson err = of_address_to_resource(dn, 1, &res); 5748ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson if (!dn || err) { 5758ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson /* Fallback for old firmware */ 5768ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson res.start = 0xfd800000; 5778ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson res.end = res.start + 0x1000; 5788ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson } 57928f65c11f2ffb3957259dece647a24f8ad2e241bJoe Perches dma_status = __ioremap(res.start, resource_size(&res), 0); 5808ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson pci_dev_put(iob_pdev); 5818ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 5828ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson for (i = 0; i < MAX_TXCH; i++) 5838ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson __set_bit(i, txch_free); 5848ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 5858ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson for (i = 0; i < MAX_RXCH; i++) 5868ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson __set_bit(i, rxch_free); 5878ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 588afea3278f73c14271ee60ca7593ad74b7a946486Olof Johansson timeout = jiffies + HZ; 589afea3278f73c14271ee60ca7593ad74b7a946486Olof Johansson pasemi_write_dma_reg(PAS_DMA_COM_RXCMD, 0); 590afea3278f73c14271ee60ca7593ad74b7a946486Olof Johansson while (pasemi_read_dma_reg(PAS_DMA_COM_RXSTA) & 1) { 591afea3278f73c14271ee60ca7593ad74b7a946486Olof Johansson if (time_after(jiffies, timeout)) { 592afea3278f73c14271ee60ca7593ad74b7a946486Olof Johansson pr_warning("Warning: Could not disable RX section\n"); 593afea3278f73c14271ee60ca7593ad74b7a946486Olof Johansson break; 594afea3278f73c14271ee60ca7593ad74b7a946486Olof Johansson } 595afea3278f73c14271ee60ca7593ad74b7a946486Olof Johansson } 596afea3278f73c14271ee60ca7593ad74b7a946486Olof Johansson 597afea3278f73c14271ee60ca7593ad74b7a946486Olof Johansson timeout = jiffies + HZ; 598afea3278f73c14271ee60ca7593ad74b7a946486Olof Johansson pasemi_write_dma_reg(PAS_DMA_COM_TXCMD, 0); 599afea3278f73c14271ee60ca7593ad74b7a946486Olof Johansson while (pasemi_read_dma_reg(PAS_DMA_COM_TXSTA) & 1) { 600afea3278f73c14271ee60ca7593ad74b7a946486Olof Johansson if (time_after(jiffies, timeout)) { 601afea3278f73c14271ee60ca7593ad74b7a946486Olof Johansson pr_warning("Warning: Could not disable TX section\n"); 602afea3278f73c14271ee60ca7593ad74b7a946486Olof Johansson break; 603afea3278f73c14271ee60ca7593ad74b7a946486Olof Johansson } 604afea3278f73c14271ee60ca7593ad74b7a946486Olof Johansson } 605afea3278f73c14271ee60ca7593ad74b7a946486Olof Johansson 606afea3278f73c14271ee60ca7593ad74b7a946486Olof Johansson /* setup resource allocations for the different DMA sections */ 607afea3278f73c14271ee60ca7593ad74b7a946486Olof Johansson tmp = pasemi_read_dma_reg(PAS_DMA_COM_CFG); 608afea3278f73c14271ee60ca7593ad74b7a946486Olof Johansson pasemi_write_dma_reg(PAS_DMA_COM_CFG, tmp | 0x18000000); 609afea3278f73c14271ee60ca7593ad74b7a946486Olof Johansson 610afea3278f73c14271ee60ca7593ad74b7a946486Olof Johansson /* enable tx section */ 611afea3278f73c14271ee60ca7593ad74b7a946486Olof Johansson pasemi_write_dma_reg(PAS_DMA_COM_TXCMD, PAS_DMA_COM_TXCMD_EN); 612afea3278f73c14271ee60ca7593ad74b7a946486Olof Johansson 613afea3278f73c14271ee60ca7593ad74b7a946486Olof Johansson /* enable rx section */ 614afea3278f73c14271ee60ca7593ad74b7a946486Olof Johansson pasemi_write_dma_reg(PAS_DMA_COM_RXCMD, PAS_DMA_COM_RXCMD_EN); 615afea3278f73c14271ee60ca7593ad74b7a946486Olof Johansson 616f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson for (i = 0; i < MAX_FLAGS; i++) 617f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson __set_bit(i, flags_free); 618f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson 619dda56df08a28404004bca313d2a1ba1597acd755Olof Johansson for (i = 0; i < MAX_FUN; i++) 620dda56df08a28404004bca313d2a1ba1597acd755Olof Johansson __set_bit(i, fun_free); 621dda56df08a28404004bca313d2a1ba1597acd755Olof Johansson 622f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson /* clear all status flags */ 623f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson pasemi_write_dma_reg(PAS_DMA_TXF_CFLG0, 0xffffffff); 624f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson pasemi_write_dma_reg(PAS_DMA_TXF_CFLG1, 0xffffffff); 625f37203b5ccaf6d58cb5ca6b1840e40f3b587109cOlof Johansson 6268ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson printk(KERN_INFO "PA Semi PWRficient DMA library initialized " 6278ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson "(%d tx, %d rx channels)\n", num_txch, num_rxch); 6288ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson 6298ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johanssonout: 6308ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson spin_unlock(&init_lock); 6318ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson return err; 6328ee9d85779356c1dc2ba87aca27fbf9414f2d82bOlof Johansson} 63306daa168b681797c91ce1fd567d706b9b84738e2Olof JohanssonEXPORT_SYMBOL(pasemi_dma_init); 634