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