18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Copyright (c) 2010 Broadcom Corporation
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Permission to use, copy, modify, and/or distribute this software for any
58c2ecf20Sopenharmony_ci * purpose with or without fee is hereby granted, provided that the above
68c2ecf20Sopenharmony_ci * copyright notice and this permission notice appear in all copies.
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
98c2ecf20Sopenharmony_ci * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
108c2ecf20Sopenharmony_ci * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
118c2ecf20Sopenharmony_ci * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
128c2ecf20Sopenharmony_ci * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
138c2ecf20Sopenharmony_ci * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
148c2ecf20Sopenharmony_ci * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
158c2ecf20Sopenharmony_ci */
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci#ifndef	_BRCM_DMA_H_
188c2ecf20Sopenharmony_ci#define	_BRCM_DMA_H_
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci#include <linux/delay.h>
218c2ecf20Sopenharmony_ci#include <linux/skbuff.h>
228c2ecf20Sopenharmony_ci#include "types.h"		/* forward structure declarations */
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci/* map/unmap direction */
258c2ecf20Sopenharmony_ci#define	DMA_TX	1		/* TX direction for DMA */
268c2ecf20Sopenharmony_ci#define	DMA_RX	2		/* RX direction for DMA */
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci/* DMA structure:
298c2ecf20Sopenharmony_ci *  support two DMA engines: 32 bits address or 64 bit addressing
308c2ecf20Sopenharmony_ci *  basic DMA register set is per channel(transmit or receive)
318c2ecf20Sopenharmony_ci *  a pair of channels is defined for convenience
328c2ecf20Sopenharmony_ci */
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci/* 32 bits addressing */
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_cistruct dma32diag {	/* diag access */
378c2ecf20Sopenharmony_ci	u32 fifoaddr;	/* diag address */
388c2ecf20Sopenharmony_ci	u32 fifodatalow;	/* low 32bits of data */
398c2ecf20Sopenharmony_ci	u32 fifodatahigh;	/* high 32bits of data */
408c2ecf20Sopenharmony_ci	u32 pad;		/* reserved */
418c2ecf20Sopenharmony_ci};
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci/* 64 bits addressing */
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci/* dma registers per channel(xmt or rcv) */
468c2ecf20Sopenharmony_cistruct dma64regs {
478c2ecf20Sopenharmony_ci	u32 control;	/* enable, et al */
488c2ecf20Sopenharmony_ci	u32 ptr;	/* last descriptor posted to chip */
498c2ecf20Sopenharmony_ci	u32 addrlow;	/* desc ring base address low 32-bits (8K aligned) */
508c2ecf20Sopenharmony_ci	u32 addrhigh;	/* desc ring base address bits 63:32 (8K aligned) */
518c2ecf20Sopenharmony_ci	u32 status0;	/* current descriptor, xmt state */
528c2ecf20Sopenharmony_ci	u32 status1;	/* active descriptor, xmt error */
538c2ecf20Sopenharmony_ci};
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci/* range param for dma_getnexttxp() and dma_txreclaim */
568c2ecf20Sopenharmony_cienum txd_range {
578c2ecf20Sopenharmony_ci	DMA_RANGE_ALL = 1,
588c2ecf20Sopenharmony_ci	DMA_RANGE_TRANSMITTED,
598c2ecf20Sopenharmony_ci	DMA_RANGE_TRANSFERED
608c2ecf20Sopenharmony_ci};
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci/*
638c2ecf20Sopenharmony_ci * Exported data structure (read-only)
648c2ecf20Sopenharmony_ci */
658c2ecf20Sopenharmony_ci/* export structure */
668c2ecf20Sopenharmony_cistruct dma_pub {
678c2ecf20Sopenharmony_ci	uint txavail;		/* # free tx descriptors */
688c2ecf20Sopenharmony_ci	uint dmactrlflags;	/* dma control flags */
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci	/* rx error counters */
718c2ecf20Sopenharmony_ci	uint rxgiants;		/* rx giant frames */
728c2ecf20Sopenharmony_ci	uint rxnobuf;		/* rx out of dma descriptors */
738c2ecf20Sopenharmony_ci	/* tx error counters */
748c2ecf20Sopenharmony_ci	uint txnobuf;		/* tx out of dma descriptors */
758c2ecf20Sopenharmony_ci};
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ciextern struct dma_pub *dma_attach(char *name, struct brcms_c_info *wlc,
788c2ecf20Sopenharmony_ci				  uint txregbase, uint rxregbase,
798c2ecf20Sopenharmony_ci				  uint ntxd, uint nrxd,
808c2ecf20Sopenharmony_ci				  uint rxbufsize, int rxextheadroom,
818c2ecf20Sopenharmony_ci				  uint nrxpost, uint rxoffset);
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_civoid dma_rxinit(struct dma_pub *pub);
848c2ecf20Sopenharmony_ciint dma_rx(struct dma_pub *pub, struct sk_buff_head *skb_list);
858c2ecf20Sopenharmony_cibool dma_rxfill(struct dma_pub *pub);
868c2ecf20Sopenharmony_cibool dma_rxreset(struct dma_pub *pub);
878c2ecf20Sopenharmony_cibool dma_txreset(struct dma_pub *pub);
888c2ecf20Sopenharmony_civoid dma_txinit(struct dma_pub *pub);
898c2ecf20Sopenharmony_ciint dma_txfast(struct brcms_c_info *wlc, struct dma_pub *pub,
908c2ecf20Sopenharmony_ci	       struct sk_buff *p0);
918c2ecf20Sopenharmony_civoid dma_txflush(struct dma_pub *pub);
928c2ecf20Sopenharmony_ciint dma_txpending(struct dma_pub *pub);
938c2ecf20Sopenharmony_civoid dma_kick_tx(struct dma_pub *pub);
948c2ecf20Sopenharmony_civoid dma_txsuspend(struct dma_pub *pub);
958c2ecf20Sopenharmony_cibool dma_txsuspended(struct dma_pub *pub);
968c2ecf20Sopenharmony_civoid dma_txresume(struct dma_pub *pub);
978c2ecf20Sopenharmony_civoid dma_txreclaim(struct dma_pub *pub, enum txd_range range);
988c2ecf20Sopenharmony_civoid dma_rxreclaim(struct dma_pub *pub);
998c2ecf20Sopenharmony_civoid dma_detach(struct dma_pub *pub);
1008c2ecf20Sopenharmony_ciunsigned long dma_getvar(struct dma_pub *pub, const char *name);
1018c2ecf20Sopenharmony_cistruct sk_buff *dma_getnexttxp(struct dma_pub *pub, enum txd_range range);
1028c2ecf20Sopenharmony_civoid dma_counterreset(struct dma_pub *pub);
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_civoid dma_walk_packets(struct dma_pub *dmah, void (*callback_fnc)
1058c2ecf20Sopenharmony_ci		      (void *pkt, void *arg_a), void *arg_a);
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci/*
1088c2ecf20Sopenharmony_ci * DMA(Bug) on bcm47xx chips seems to declare that the packet is ready, but
1098c2ecf20Sopenharmony_ci * the packet length is not updated yet (by DMA) on the expected time.
1108c2ecf20Sopenharmony_ci * Workaround is to hold processor till DMA updates the length, and stay off
1118c2ecf20Sopenharmony_ci * the bus to allow DMA update the length in buffer
1128c2ecf20Sopenharmony_ci */
1138c2ecf20Sopenharmony_cistatic inline void dma_spin_for_len(uint len, struct sk_buff *head)
1148c2ecf20Sopenharmony_ci{
1158c2ecf20Sopenharmony_ci#if defined(CONFIG_BCM47XX)
1168c2ecf20Sopenharmony_ci	if (!len) {
1178c2ecf20Sopenharmony_ci		while (!(len = *(u16 *) KSEG1ADDR(head->data)))
1188c2ecf20Sopenharmony_ci			udelay(1);
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci		*(u16 *) (head->data) = cpu_to_le16((u16) len);
1218c2ecf20Sopenharmony_ci	}
1228c2ecf20Sopenharmony_ci#endif				/* defined(CONFIG_BCM47XX) */
1238c2ecf20Sopenharmony_ci}
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci#endif				/* _BRCM_DMA_H_ */
126