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