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