aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/stlc45xx/stlc45xx.h
blob: ac96bbbde79fdc698ba37234f1680ab48f1b7aff (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
/*
 * This file is part of stlc45xx
 *
 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
 *
 * Contact: Kalle Valo <kalle.valo@nokia.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 */

#include <linux/mutex.h>
#include <linux/list.h>
#include <net/mac80211.h>

#include "stlc45xx_lmac.h"

#define DRIVER_NAME "stlc45xx"
#define DRIVER_VERSION "0.1.3"

#define DRIVER_PREFIX DRIVER_NAME ": "

enum {
	DEBUG_NONE = 0,
	DEBUG_FUNC = 1 << 0,
	DEBUG_IRQ = 1 << 1,
	DEBUG_BH = 1 << 2,
	DEBUG_RX = 1 << 3,
	DEBUG_RX_CONTENT = 1 << 5,
	DEBUG_TX = 1 << 6,
	DEBUG_TX_CONTENT = 1 << 8,
	DEBUG_TXBUFFER = 1 << 9,
	DEBUG_QUEUE = 1 << 10,
	DEBUG_BOOT = 1 << 11,
	DEBUG_PSM = 1 << 12,
	DEBUG_ALL = ~0,
};

#define DEBUG_LEVEL DEBUG_NONE
/* #define DEBUG_LEVEL DEBUG_ALL */
/* #define DEBUG_LEVEL (DEBUG_TX | DEBUG_RX | DEBUG_IRQ) */
/* #define DEBUG_LEVEL (DEBUG_TX | DEBUG_MEMREGION | DEBUG_QUEUE) */
/* #define DEBUG_LEVEL (DEBUG_MEMREGION | DEBUG_QUEUE) */

#define stlc45xx_error(fmt, arg...) \
	printk(KERN_ERR DRIVER_PREFIX "ERROR " fmt "\n", ##arg)

#define stlc45xx_warning(fmt, arg...) \
	printk(KERN_WARNING DRIVER_PREFIX "WARNING " fmt "\n", ##arg)

#define stlc45xx_info(fmt, arg...) \
	printk(KERN_INFO DRIVER_PREFIX fmt "\n", ##arg)

#define stlc45xx_debug(level, fmt, arg...) \
	do { \
		if (level & DEBUG_LEVEL) \
			printk(KERN_DEBUG DRIVER_PREFIX fmt "\n", ##arg); \
	} while (0)

#define stlc45xx_dump(level, buf, len)		\
	do { \
		if (level & DEBUG_LEVEL) \
			print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, \
				       16, 1, buf, len, 1);		\
	} while (0)

#define MAC2STR(a) ((a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5])
#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"

/* Bit 15 is read/write bit; ON = READ, OFF = WRITE */
#define ADDR_READ_BIT_15  0x8000

#define SPI_ADRS_ARM_INTERRUPTS     0x00
#define SPI_ADRS_ARM_INT_EN	    0x04

#define SPI_ADRS_HOST_INTERRUPTS    0x08
#define SPI_ADRS_HOST_INT_EN	    0x0c
#define SPI_ADRS_HOST_INT_ACK	    0x10

#define SPI_ADRS_GEN_PURP_1   	    0x14
#define SPI_ADRS_GEN_PURP_2   	    0x18

/* high word */
#define SPI_ADRS_DEV_CTRL_STAT      0x26

#define SPI_ADRS_DMA_DATA      	    0x28

#define SPI_ADRS_DMA_WRITE_CTRL     0x2c
#define SPI_ADRS_DMA_WRITE_LEN      0x2e
#define SPI_ADRS_DMA_WRITE_BASE     0x30

#define SPI_ADRS_DMA_READ_CTRL      0x34
#define SPI_ADRS_DMA_READ_LEN       0x36
#define SPI_ADRS_DMA_READ_BASE      0x38

#define SPI_CTRL_STAT_HOST_OVERRIDE 0x8000
#define SPI_CTRL_STAT_START_HALTED  0x4000
#define SPI_CTRL_STAT_RAM_BOOT      0x2000
#define SPI_CTRL_STAT_HOST_RESET    0x1000
#define SPI_CTRL_STAT_HOST_CPU_EN   0x0800

#define SPI_DMA_WRITE_CTRL_ENABLE   0x0001
#define SPI_DMA_READ_CTRL_ENABLE    0x0001
#define HOST_ALLOWED                (1 << 7)

#define FIRMWARE_ADDRESS                        0x20000

#define SPI_TIMEOUT                             100         /* msec */

#define SPI_MAX_TX_PACKETS                      32

#define SPI_MAX_PACKET_SIZE                     32767

#define SPI_TARGET_INT_WAKEUP                   0x00000001
#define SPI_TARGET_INT_SLEEP                    0x00000002
#define SPI_TARGET_INT_RDDONE                   0x00000004

#define SPI_TARGET_INT_CTS                      0x00004000
#define SPI_TARGET_INT_DR                       0x00008000

#define SPI_HOST_INT_READY                      0x00000001
#define SPI_HOST_INT_WR_READY                   0x00000002
#define SPI_HOST_INT_SW_UPDATE                  0x00000004
#define SPI_HOST_INT_UPDATE                     0x10000000

/* clear to send */
#define SPI_HOST_INT_CTS	                0x00004000

/* data ready */
#define SPI_HOST_INT_DR	                        0x00008000

#define SPI_HOST_INTS_DEFAULT \
	(SPI_HOST_INT_READY | SPI_HOST_INT_UPDATE | SPI_HOST_INT_SW_UPDATE)

#define TARGET_BOOT_SLEEP 50

/* The firmware buffer is divided into three areas:
 *
 * o config area (for control commands)
 * o tx buffer
 * o rx buffer
 */
#define FIRMWARE_BUFFER_START 0x20200
#define FIRMWARE_BUFFER_END 0x27c60
#define FIRMWARE_BUFFER_LEN (FIRMWARE_BUFFER_END - FIRMWARE_BUFFER_START)
#define FIRMWARE_MTU 3240
#define FIRMWARE_CONFIG_PAYLOAD_LEN 1024
#define FIRMWARE_CONFIG_START FIRMWARE_BUFFER_START
#define FIRMWARE_CONFIG_LEN (sizeof(struct s_lm_control) + \
			     FIRMWARE_CONFIG_PAYLOAD_LEN)
#define FIRMWARE_CONFIG_END (FIRMWARE_CONFIG_START + FIRMWARE_CONFIG_LEN - 1)
#define FIRMWARE_RXBUFFER_LEN (5 * FIRMWARE_MTU + 1024)
#define FIRMWARE_RXBUFFER_START (FIRMWARE_BUFFER_END - FIRMWARE_RXBUFFER_LEN)
#define FIRMWARE_RXBUFFER_END (FIRMWARE_RXBUFFER_START + \
			       FIRMWARE_RXBUFFER_LEN - 1)
#define FIRMWARE_TXBUFFER_START (FIRMWARE_BUFFER_START + FIRMWARE_CONFIG_LEN)
#define FIRMWARE_TXBUFFER_LEN (FIRMWARE_BUFFER_LEN - FIRMWARE_CONFIG_LEN - \
			       FIRMWARE_RXBUFFER_LEN)
#define FIRMWARE_TXBUFFER_END (FIRMWARE_TXBUFFER_START + \
			       FIRMWARE_TXBUFFER_LEN - 1)

#define FIRMWARE_TXBUFFER_HEADER 100
#define FIRMWARE_TXBUFFER_TRAILER 4

/* FIXME: come up with a proper value */
#define MAX_FRAME_LEN 2500

/* unit is ms */
#define TX_FRAME_LIFETIME 2000
#define TX_TIMEOUT 4000

#define SUPPORTED_CHANNELS 13

/* FIXME */
/* #define CHANNEL_CAL_LEN offsetof(struct s_lmo_scan, bratemask) - \ */
/* 	offsetof(struct s_lmo_scan, channel) */
#define CHANNEL_CAL_LEN 292
#define CHANNEL_CAL_ARRAY_LEN (SUPPORTED_CHANNELS * CHANNEL_CAL_LEN)
/* FIXME */
/* #define RSSI_CAL_LEN sizeof(struct s_lmo_scan) - \ */
/* 	offsetof(struct s_lmo_scan, rssical) */
#define RSSI_CAL_LEN 8
#define RSSI_CAL_ARRAY_LEN (SUPPORTED_CHANNELS * RSSI_CAL_LEN)

struct s_dma_regs {
	unsigned short cmd;
	unsigned short len;
	unsigned long addr;
};

struct stlc45xx_ie_tim {
	u8 dtim_count;
	u8 dtim_period;
	u8 bmap_control;
	u8 pvbmap[251];
};

struct txbuffer {
	/* can be removed when switched to skb queue */
	struct list_head tx_list;

	struct list_head buffer_list;

	int start;
	int frame_start;
	int end;

	struct sk_buff *skb;
	u32 handle;

	bool status_needed;

	int header_len;

	/* unit jiffies */
	unsigned long lifetime;
};

enum fw_state {
	FW_STATE_OFF,
	FW_STATE_BOOTING,
	FW_STATE_READY,
	FW_STATE_RESET,
	FW_STATE_RESETTING,
};

struct stlc45xx {
	struct ieee80211_hw *hw;
	struct spi_device *spi;
	struct work_struct work;
	struct work_struct work_reset;
	struct delayed_work work_tx_timeout;
	struct mutex mutex;
	struct completion fw_comp;


	u8 bssid[ETH_ALEN];
	u8 mac_addr[ETH_ALEN];
	int channel;

	u8 *cal_rssi;
	u8 *cal_channels;

	enum fw_state fw_state;

	spinlock_t tx_lock;

	/* protected by tx_lock */
	struct list_head txbuffer;

	/* protected by tx_lock */
	struct list_head tx_pending;

	/* protected by tx_lock */
	int tx_queue_stopped;

	/* protected by mutex */
	struct list_head tx_sent;

	int tx_frames;

	u8 *fw;
	int fw_len;

	bool psm;
	bool associated;
	int aid;
	bool pspolling;
};