162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * Copyright (c) 2010 Broadcom Corporation
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Permission to use, copy, modify, and/or distribute this software for any
562306a36Sopenharmony_ci * purpose with or without fee is hereby granted, provided that the above
662306a36Sopenharmony_ci * copyright notice and this permission notice appear in all copies.
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
962306a36Sopenharmony_ci * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1062306a36Sopenharmony_ci * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
1162306a36Sopenharmony_ci * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1262306a36Sopenharmony_ci * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
1362306a36Sopenharmony_ci * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
1462306a36Sopenharmony_ci * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1562306a36Sopenharmony_ci */
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#ifndef	_BRCM_DMA_H_
1862306a36Sopenharmony_ci#define	_BRCM_DMA_H_
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci#include <linux/delay.h>
2162306a36Sopenharmony_ci#include <linux/skbuff.h>
2262306a36Sopenharmony_ci#include "types.h"		/* forward structure declarations */
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci/* map/unmap direction */
2562306a36Sopenharmony_ci#define	DMA_TX	1		/* TX direction for DMA */
2662306a36Sopenharmony_ci#define	DMA_RX	2		/* RX direction for DMA */
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci/* DMA structure:
2962306a36Sopenharmony_ci *  support two DMA engines: 32 bits address or 64 bit addressing
3062306a36Sopenharmony_ci *  basic DMA register set is per channel(transmit or receive)
3162306a36Sopenharmony_ci *  a pair of channels is defined for convenience
3262306a36Sopenharmony_ci */
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci/* 32 bits addressing */
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_cistruct dma32diag {	/* diag access */
3762306a36Sopenharmony_ci	u32 fifoaddr;	/* diag address */
3862306a36Sopenharmony_ci	u32 fifodatalow;	/* low 32bits of data */
3962306a36Sopenharmony_ci	u32 fifodatahigh;	/* high 32bits of data */
4062306a36Sopenharmony_ci	u32 pad;		/* reserved */
4162306a36Sopenharmony_ci};
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci/* 64 bits addressing */
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci/* dma registers per channel(xmt or rcv) */
4662306a36Sopenharmony_cistruct dma64regs {
4762306a36Sopenharmony_ci	u32 control;	/* enable, et al */
4862306a36Sopenharmony_ci	u32 ptr;	/* last descriptor posted to chip */
4962306a36Sopenharmony_ci	u32 addrlow;	/* desc ring base address low 32-bits (8K aligned) */
5062306a36Sopenharmony_ci	u32 addrhigh;	/* desc ring base address bits 63:32 (8K aligned) */
5162306a36Sopenharmony_ci	u32 status0;	/* current descriptor, xmt state */
5262306a36Sopenharmony_ci	u32 status1;	/* active descriptor, xmt error */
5362306a36Sopenharmony_ci};
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci/* range param for dma_getnexttxp() and dma_txreclaim */
5662306a36Sopenharmony_cienum txd_range {
5762306a36Sopenharmony_ci	DMA_RANGE_ALL = 1,
5862306a36Sopenharmony_ci	DMA_RANGE_TRANSMITTED,
5962306a36Sopenharmony_ci	DMA_RANGE_TRANSFERED
6062306a36Sopenharmony_ci};
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci/*
6362306a36Sopenharmony_ci * Exported data structure (read-only)
6462306a36Sopenharmony_ci */
6562306a36Sopenharmony_ci/* export structure */
6662306a36Sopenharmony_cistruct dma_pub {
6762306a36Sopenharmony_ci	uint txavail;		/* # free tx descriptors */
6862306a36Sopenharmony_ci	uint dmactrlflags;	/* dma control flags */
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci	/* rx error counters */
7162306a36Sopenharmony_ci	uint rxgiants;		/* rx giant frames */
7262306a36Sopenharmony_ci	uint rxnobuf;		/* rx out of dma descriptors */
7362306a36Sopenharmony_ci	/* tx error counters */
7462306a36Sopenharmony_ci	uint txnobuf;		/* tx out of dma descriptors */
7562306a36Sopenharmony_ci};
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ciextern struct dma_pub *dma_attach(char *name, struct brcms_c_info *wlc,
7862306a36Sopenharmony_ci				  uint txregbase, uint rxregbase,
7962306a36Sopenharmony_ci				  uint ntxd, uint nrxd,
8062306a36Sopenharmony_ci				  uint rxbufsize, int rxextheadroom,
8162306a36Sopenharmony_ci				  uint nrxpost, uint rxoffset);
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_civoid dma_rxinit(struct dma_pub *pub);
8462306a36Sopenharmony_ciint dma_rx(struct dma_pub *pub, struct sk_buff_head *skb_list);
8562306a36Sopenharmony_cibool dma_rxfill(struct dma_pub *pub);
8662306a36Sopenharmony_cibool dma_rxreset(struct dma_pub *pub);
8762306a36Sopenharmony_cibool dma_txreset(struct dma_pub *pub);
8862306a36Sopenharmony_civoid dma_txinit(struct dma_pub *pub);
8962306a36Sopenharmony_ciint dma_txfast(struct brcms_c_info *wlc, struct dma_pub *pub,
9062306a36Sopenharmony_ci	       struct sk_buff *p0);
9162306a36Sopenharmony_civoid dma_txflush(struct dma_pub *pub);
9262306a36Sopenharmony_ciint dma_txpending(struct dma_pub *pub);
9362306a36Sopenharmony_civoid dma_kick_tx(struct dma_pub *pub);
9462306a36Sopenharmony_civoid dma_txsuspend(struct dma_pub *pub);
9562306a36Sopenharmony_cibool dma_txsuspended(struct dma_pub *pub);
9662306a36Sopenharmony_civoid dma_txresume(struct dma_pub *pub);
9762306a36Sopenharmony_civoid dma_txreclaim(struct dma_pub *pub, enum txd_range range);
9862306a36Sopenharmony_civoid dma_rxreclaim(struct dma_pub *pub);
9962306a36Sopenharmony_civoid dma_detach(struct dma_pub *pub);
10062306a36Sopenharmony_ciunsigned long dma_getvar(struct dma_pub *pub, const char *name);
10162306a36Sopenharmony_cistruct sk_buff *dma_getnexttxp(struct dma_pub *pub, enum txd_range range);
10262306a36Sopenharmony_civoid dma_counterreset(struct dma_pub *pub);
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_civoid dma_walk_packets(struct dma_pub *dmah, void (*callback_fnc)
10562306a36Sopenharmony_ci		      (void *pkt, void *arg_a), void *arg_a);
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci/*
10862306a36Sopenharmony_ci * DMA(Bug) on bcm47xx chips seems to declare that the packet is ready, but
10962306a36Sopenharmony_ci * the packet length is not updated yet (by DMA) on the expected time.
11062306a36Sopenharmony_ci * Workaround is to hold processor till DMA updates the length, and stay off
11162306a36Sopenharmony_ci * the bus to allow DMA update the length in buffer
11262306a36Sopenharmony_ci */
11362306a36Sopenharmony_cistatic inline void dma_spin_for_len(uint len, struct sk_buff *head)
11462306a36Sopenharmony_ci{
11562306a36Sopenharmony_ci#if defined(CONFIG_BCM47XX)
11662306a36Sopenharmony_ci	if (!len) {
11762306a36Sopenharmony_ci		while (!(len = *(u16 *) KSEG1ADDR(head->data)))
11862306a36Sopenharmony_ci			udelay(1);
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci		*(u16 *) (head->data) = cpu_to_le16((u16) len);
12162306a36Sopenharmony_ci	}
12262306a36Sopenharmony_ci#endif				/* defined(CONFIG_BCM47XX) */
12362306a36Sopenharmony_ci}
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci#endif				/* _BRCM_DMA_H_ */
126