18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 28c2ecf20Sopenharmony_ci/* ZD1211 USB-WLAN driver for Linux 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de> 58c2ecf20Sopenharmony_ci * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org> 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#ifndef _ZD_USB_H 98c2ecf20Sopenharmony_ci#define _ZD_USB_H 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/completion.h> 128c2ecf20Sopenharmony_ci#include <linux/netdevice.h> 138c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 148c2ecf20Sopenharmony_ci#include <linux/skbuff.h> 158c2ecf20Sopenharmony_ci#include <linux/usb.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include "zd_def.h" 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#define ZD_USB_TX_HIGH 5 208c2ecf20Sopenharmony_ci#define ZD_USB_TX_LOW 2 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#define ZD_TX_TIMEOUT (HZ * 5) 238c2ecf20Sopenharmony_ci#define ZD_TX_WATCHDOG_INTERVAL round_jiffies_relative(HZ) 248c2ecf20Sopenharmony_ci#define ZD_RX_IDLE_INTERVAL round_jiffies_relative(30 * HZ) 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_cienum devicetype { 278c2ecf20Sopenharmony_ci DEVICE_ZD1211 = 0, 288c2ecf20Sopenharmony_ci DEVICE_ZD1211B = 1, 298c2ecf20Sopenharmony_ci DEVICE_INSTALLER = 2, 308c2ecf20Sopenharmony_ci}; 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_cienum endpoints { 338c2ecf20Sopenharmony_ci EP_CTRL = 0, 348c2ecf20Sopenharmony_ci EP_DATA_OUT = 1, 358c2ecf20Sopenharmony_ci EP_DATA_IN = 2, 368c2ecf20Sopenharmony_ci EP_INT_IN = 3, 378c2ecf20Sopenharmony_ci EP_REGS_OUT = 4, 388c2ecf20Sopenharmony_ci}; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_cienum { 418c2ecf20Sopenharmony_ci USB_MAX_TRANSFER_SIZE = 4096, /* bytes */ 428c2ecf20Sopenharmony_ci /* FIXME: The original driver uses this value. We have to check, 438c2ecf20Sopenharmony_ci * whether the MAX_TRANSFER_SIZE is sufficient and this needs only be 448c2ecf20Sopenharmony_ci * used if one combined frame is split over two USB transactions. 458c2ecf20Sopenharmony_ci */ 468c2ecf20Sopenharmony_ci USB_MAX_RX_SIZE = 4800, /* bytes */ 478c2ecf20Sopenharmony_ci USB_MAX_IOWRITE16_COUNT = 15, 488c2ecf20Sopenharmony_ci USB_MAX_IOWRITE32_COUNT = USB_MAX_IOWRITE16_COUNT/2, 498c2ecf20Sopenharmony_ci USB_MAX_IOREAD16_COUNT = 15, 508c2ecf20Sopenharmony_ci USB_MAX_IOREAD32_COUNT = USB_MAX_IOREAD16_COUNT/2, 518c2ecf20Sopenharmony_ci USB_MIN_RFWRITE_BIT_COUNT = 16, 528c2ecf20Sopenharmony_ci USB_MAX_RFWRITE_BIT_COUNT = 28, 538c2ecf20Sopenharmony_ci USB_MAX_EP_INT_BUFFER = 64, 548c2ecf20Sopenharmony_ci USB_ZD1211B_BCD_DEVICE = 0x4810, 558c2ecf20Sopenharmony_ci}; 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_cienum control_requests { 588c2ecf20Sopenharmony_ci USB_REQ_WRITE_REGS = 0x21, 598c2ecf20Sopenharmony_ci USB_REQ_READ_REGS = 0x22, 608c2ecf20Sopenharmony_ci USB_REQ_WRITE_RF = 0x23, 618c2ecf20Sopenharmony_ci USB_REQ_PROG_FLASH = 0x24, 628c2ecf20Sopenharmony_ci USB_REQ_EEPROM_START = 0x0128, /* ? request is a byte */ 638c2ecf20Sopenharmony_ci USB_REQ_EEPROM_MID = 0x28, 648c2ecf20Sopenharmony_ci USB_REQ_EEPROM_END = 0x0228, /* ? request is a byte */ 658c2ecf20Sopenharmony_ci USB_REQ_FIRMWARE_DOWNLOAD = 0x30, 668c2ecf20Sopenharmony_ci USB_REQ_FIRMWARE_CONFIRM = 0x31, 678c2ecf20Sopenharmony_ci USB_REQ_FIRMWARE_READ_DATA = 0x32, 688c2ecf20Sopenharmony_ci}; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_cistruct usb_req_read_regs { 718c2ecf20Sopenharmony_ci __le16 id; 728c2ecf20Sopenharmony_ci __le16 addr[]; 738c2ecf20Sopenharmony_ci} __packed; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_cistruct reg_data { 768c2ecf20Sopenharmony_ci __le16 addr; 778c2ecf20Sopenharmony_ci __le16 value; 788c2ecf20Sopenharmony_ci} __packed; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_cistruct usb_req_write_regs { 818c2ecf20Sopenharmony_ci __le16 id; 828c2ecf20Sopenharmony_ci struct reg_data reg_writes[]; 838c2ecf20Sopenharmony_ci} __packed; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_cienum { 868c2ecf20Sopenharmony_ci RF_IF_LE = 0x02, 878c2ecf20Sopenharmony_ci RF_CLK = 0x04, 888c2ecf20Sopenharmony_ci RF_DATA = 0x08, 898c2ecf20Sopenharmony_ci}; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_cistruct usb_req_rfwrite { 928c2ecf20Sopenharmony_ci __le16 id; 938c2ecf20Sopenharmony_ci __le16 value; 948c2ecf20Sopenharmony_ci /* 1: 3683a */ 958c2ecf20Sopenharmony_ci /* 2: other (default) */ 968c2ecf20Sopenharmony_ci __le16 bits; 978c2ecf20Sopenharmony_ci /* RF2595: 24 */ 988c2ecf20Sopenharmony_ci __le16 bit_values[]; 998c2ecf20Sopenharmony_ci /* (ZD_CR203 & ~(RF_IF_LE | RF_CLK | RF_DATA)) | (bit ? RF_DATA : 0) */ 1008c2ecf20Sopenharmony_ci} __packed; 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci/* USB interrupt */ 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_cienum usb_int_id { 1058c2ecf20Sopenharmony_ci USB_INT_TYPE = 0x01, 1068c2ecf20Sopenharmony_ci USB_INT_ID_REGS = 0x90, 1078c2ecf20Sopenharmony_ci USB_INT_ID_RETRY_FAILED = 0xa0, 1088c2ecf20Sopenharmony_ci}; 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_cienum usb_int_flags { 1118c2ecf20Sopenharmony_ci USB_INT_READ_REGS_EN = 0x01, 1128c2ecf20Sopenharmony_ci}; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_cistruct usb_int_header { 1158c2ecf20Sopenharmony_ci u8 type; /* must always be 1 */ 1168c2ecf20Sopenharmony_ci u8 id; 1178c2ecf20Sopenharmony_ci} __packed; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_cistruct usb_int_regs { 1208c2ecf20Sopenharmony_ci struct usb_int_header hdr; 1218c2ecf20Sopenharmony_ci struct reg_data regs[]; 1228c2ecf20Sopenharmony_ci} __packed; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_cistruct usb_int_retry_fail { 1258c2ecf20Sopenharmony_ci struct usb_int_header hdr; 1268c2ecf20Sopenharmony_ci u8 new_rate; 1278c2ecf20Sopenharmony_ci u8 _dummy; 1288c2ecf20Sopenharmony_ci u8 addr[ETH_ALEN]; 1298c2ecf20Sopenharmony_ci u8 ibss_wakeup_dest; 1308c2ecf20Sopenharmony_ci} __packed; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_cistruct read_regs_int { 1338c2ecf20Sopenharmony_ci struct completion completion; 1348c2ecf20Sopenharmony_ci struct usb_req_read_regs *req; 1358c2ecf20Sopenharmony_ci unsigned int req_count; 1368c2ecf20Sopenharmony_ci /* Stores the USB int structure and contains the USB address of the 1378c2ecf20Sopenharmony_ci * first requested register before request. 1388c2ecf20Sopenharmony_ci */ 1398c2ecf20Sopenharmony_ci u8 buffer[USB_MAX_EP_INT_BUFFER]; 1408c2ecf20Sopenharmony_ci int length; 1418c2ecf20Sopenharmony_ci __le16 cr_int_addr; 1428c2ecf20Sopenharmony_ci}; 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_cistruct zd_ioreq16 { 1458c2ecf20Sopenharmony_ci zd_addr_t addr; 1468c2ecf20Sopenharmony_ci u16 value; 1478c2ecf20Sopenharmony_ci}; 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_cistruct zd_ioreq32 { 1508c2ecf20Sopenharmony_ci zd_addr_t addr; 1518c2ecf20Sopenharmony_ci u32 value; 1528c2ecf20Sopenharmony_ci}; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_cistruct zd_usb_interrupt { 1558c2ecf20Sopenharmony_ci struct read_regs_int read_regs; 1568c2ecf20Sopenharmony_ci spinlock_t lock; 1578c2ecf20Sopenharmony_ci struct urb *urb; 1588c2ecf20Sopenharmony_ci void *buffer; 1598c2ecf20Sopenharmony_ci dma_addr_t buffer_dma; 1608c2ecf20Sopenharmony_ci int interval; 1618c2ecf20Sopenharmony_ci atomic_t read_regs_enabled; 1628c2ecf20Sopenharmony_ci u8 read_regs_int_overridden:1; 1638c2ecf20Sopenharmony_ci}; 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_cistatic inline struct usb_int_regs *get_read_regs(struct zd_usb_interrupt *intr) 1668c2ecf20Sopenharmony_ci{ 1678c2ecf20Sopenharmony_ci return (struct usb_int_regs *)intr->read_regs.buffer; 1688c2ecf20Sopenharmony_ci} 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci#define RX_URBS_COUNT 5 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_cistruct zd_usb_rx { 1738c2ecf20Sopenharmony_ci spinlock_t lock; 1748c2ecf20Sopenharmony_ci struct mutex setup_mutex; 1758c2ecf20Sopenharmony_ci struct delayed_work idle_work; 1768c2ecf20Sopenharmony_ci struct tasklet_struct reset_timer_tasklet; 1778c2ecf20Sopenharmony_ci u8 fragment[2 * USB_MAX_RX_SIZE]; 1788c2ecf20Sopenharmony_ci unsigned int fragment_length; 1798c2ecf20Sopenharmony_ci unsigned int usb_packet_size; 1808c2ecf20Sopenharmony_ci struct urb **urbs; 1818c2ecf20Sopenharmony_ci int urbs_count; 1828c2ecf20Sopenharmony_ci}; 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci/** 1858c2ecf20Sopenharmony_ci * struct zd_usb_tx - structure used for transmitting frames 1868c2ecf20Sopenharmony_ci * @enabled: atomic enabled flag, indicates whether tx is enabled 1878c2ecf20Sopenharmony_ci * @lock: lock for transmission 1888c2ecf20Sopenharmony_ci * @submitted: anchor for URBs sent to device 1898c2ecf20Sopenharmony_ci * @submitted_urbs: atomic integer that counts the URBs having sent to the 1908c2ecf20Sopenharmony_ci * device, which haven't been completed 1918c2ecf20Sopenharmony_ci * @stopped: indicates whether higher level tx queues are stopped 1928c2ecf20Sopenharmony_ci */ 1938c2ecf20Sopenharmony_cistruct zd_usb_tx { 1948c2ecf20Sopenharmony_ci atomic_t enabled; 1958c2ecf20Sopenharmony_ci spinlock_t lock; 1968c2ecf20Sopenharmony_ci struct delayed_work watchdog_work; 1978c2ecf20Sopenharmony_ci struct sk_buff_head submitted_skbs; 1988c2ecf20Sopenharmony_ci struct usb_anchor submitted; 1998c2ecf20Sopenharmony_ci int submitted_urbs; 2008c2ecf20Sopenharmony_ci u8 stopped:1, watchdog_enabled:1; 2018c2ecf20Sopenharmony_ci}; 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci/* Contains the usb parts. The structure doesn't require a lock because intf 2048c2ecf20Sopenharmony_ci * will not be changed after initialization. 2058c2ecf20Sopenharmony_ci */ 2068c2ecf20Sopenharmony_cistruct zd_usb { 2078c2ecf20Sopenharmony_ci struct zd_usb_interrupt intr; 2088c2ecf20Sopenharmony_ci struct zd_usb_rx rx; 2098c2ecf20Sopenharmony_ci struct zd_usb_tx tx; 2108c2ecf20Sopenharmony_ci struct usb_interface *intf; 2118c2ecf20Sopenharmony_ci struct usb_anchor submitted_cmds; 2128c2ecf20Sopenharmony_ci struct urb *urb_async_waiting; 2138c2ecf20Sopenharmony_ci int cmd_error; 2148c2ecf20Sopenharmony_ci u8 req_buf[64]; /* zd_usb_iowrite16v needs 62 bytes */ 2158c2ecf20Sopenharmony_ci u8 is_zd1211b:1, initialized:1, was_running:1, in_async:1; 2168c2ecf20Sopenharmony_ci}; 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci#define zd_usb_dev(usb) (&usb->intf->dev) 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_cistatic inline struct usb_device *zd_usb_to_usbdev(struct zd_usb *usb) 2218c2ecf20Sopenharmony_ci{ 2228c2ecf20Sopenharmony_ci return interface_to_usbdev(usb->intf); 2238c2ecf20Sopenharmony_ci} 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_cistatic inline struct ieee80211_hw *zd_intf_to_hw(struct usb_interface *intf) 2268c2ecf20Sopenharmony_ci{ 2278c2ecf20Sopenharmony_ci return usb_get_intfdata(intf); 2288c2ecf20Sopenharmony_ci} 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_cistatic inline struct ieee80211_hw *zd_usb_to_hw(struct zd_usb *usb) 2318c2ecf20Sopenharmony_ci{ 2328c2ecf20Sopenharmony_ci return zd_intf_to_hw(usb->intf); 2338c2ecf20Sopenharmony_ci} 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_civoid zd_usb_init(struct zd_usb *usb, struct ieee80211_hw *hw, 2368c2ecf20Sopenharmony_ci struct usb_interface *intf); 2378c2ecf20Sopenharmony_ciint zd_usb_init_hw(struct zd_usb *usb); 2388c2ecf20Sopenharmony_civoid zd_usb_clear(struct zd_usb *usb); 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ciint zd_usb_scnprint_id(struct zd_usb *usb, char *buffer, size_t size); 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_civoid zd_tx_watchdog_enable(struct zd_usb *usb); 2438c2ecf20Sopenharmony_civoid zd_tx_watchdog_disable(struct zd_usb *usb); 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ciint zd_usb_enable_int(struct zd_usb *usb); 2468c2ecf20Sopenharmony_civoid zd_usb_disable_int(struct zd_usb *usb); 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ciint zd_usb_enable_rx(struct zd_usb *usb); 2498c2ecf20Sopenharmony_civoid zd_usb_disable_rx(struct zd_usb *usb); 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_civoid zd_usb_reset_rx_idle_timer(struct zd_usb *usb); 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_civoid zd_usb_enable_tx(struct zd_usb *usb); 2548c2ecf20Sopenharmony_civoid zd_usb_disable_tx(struct zd_usb *usb); 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ciint zd_usb_tx(struct zd_usb *usb, struct sk_buff *skb); 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ciint zd_usb_ioread16v(struct zd_usb *usb, u16 *values, 2598c2ecf20Sopenharmony_ci const zd_addr_t *addresses, unsigned int count); 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_cistatic inline int zd_usb_ioread16(struct zd_usb *usb, u16 *value, 2628c2ecf20Sopenharmony_ci const zd_addr_t addr) 2638c2ecf20Sopenharmony_ci{ 2648c2ecf20Sopenharmony_ci return zd_usb_ioread16v(usb, value, &addr, 1); 2658c2ecf20Sopenharmony_ci} 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_civoid zd_usb_iowrite16v_async_start(struct zd_usb *usb); 2688c2ecf20Sopenharmony_ciint zd_usb_iowrite16v_async_end(struct zd_usb *usb, unsigned int timeout); 2698c2ecf20Sopenharmony_ciint zd_usb_iowrite16v_async(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs, 2708c2ecf20Sopenharmony_ci unsigned int count); 2718c2ecf20Sopenharmony_ciint zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs, 2728c2ecf20Sopenharmony_ci unsigned int count); 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ciint zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits); 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ciint zd_usb_read_fw(struct zd_usb *usb, zd_addr_t addr, u8 *data, u16 len); 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ciextern struct workqueue_struct *zd_workqueue; 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci#endif /* _ZD_USB_H */ 281