GNU Linux-libre 4.14.266-gnu1
[releases.git] / drivers / staging / rtlwifi / halmac / halmac_88xx / halmac_api_88xx_usb.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2016  Realtek Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  *
14  * The full GNU General Public License is included in this distribution in the
15  * file called LICENSE.
16  *
17  * Contact Information:
18  * wlanfae <wlanfae@realtek.com>
19  * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
20  * Hsinchu 300, Taiwan.
21  *
22  * Larry Finger <Larry.Finger@lwfinger.net>
23  *
24  *****************************************************************************/
25 #include "halmac_88xx_cfg.h"
26
27 /**
28  * halmac_init_usb_cfg_88xx() - init USB
29  * @halmac_adapter : the adapter of halmac
30  * Author : KaiYuan Chang/Ivan Lin
31  * Return : enum halmac_ret_status
32  * More details of status code can be found in prototype document
33  */
34 enum halmac_ret_status
35 halmac_init_usb_cfg_88xx(struct halmac_adapter *halmac_adapter)
36 {
37         void *driver_adapter = NULL;
38         u8 value8 = 0;
39
40         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
41                 return HALMAC_RET_ADAPTER_INVALID;
42
43         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
44                 return HALMAC_RET_API_INVALID;
45
46         halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_INIT_USB_CFG);
47
48         driver_adapter = halmac_adapter->driver_adapter;
49
50         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
51                         "%s ==========>\n", __func__);
52
53         value8 |= (BIT_DMA_MODE |
54                    (0x3 << BIT_SHIFT_BURST_CNT)); /* burst number = 4 */
55
56         if (PLATFORM_REG_READ_8(driver_adapter, REG_SYS_CFG2 + 3) ==
57             0x20) { /* usb3.0 */
58                 value8 |= (HALMAC_USB_BURST_SIZE_3_0 << BIT_SHIFT_BURST_SIZE);
59         } else {
60                 if ((PLATFORM_REG_READ_8(driver_adapter, REG_USB_USBSTAT) &
61                      0x3) == 0x1) /* usb2.0 */
62                         value8 |= HALMAC_USB_BURST_SIZE_2_0_HSPEED
63                                   << BIT_SHIFT_BURST_SIZE;
64                 else /* usb1.1 */
65                         value8 |= HALMAC_USB_BURST_SIZE_2_0_FSPEED
66                                   << BIT_SHIFT_BURST_SIZE;
67         }
68
69         PLATFORM_REG_WRITE_8(driver_adapter, REG_RXDMA_MODE, value8);
70         PLATFORM_REG_WRITE_16(
71                 driver_adapter, REG_TXDMA_OFFSET_CHK,
72                 PLATFORM_REG_READ_16(driver_adapter, REG_TXDMA_OFFSET_CHK) |
73                         BIT_DROP_DATA_EN);
74
75         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
76                         "%s <==========\n", __func__);
77
78         return HALMAC_RET_SUCCESS;
79 }
80
81 /**
82  * halmac_deinit_usb_cfg_88xx() - deinit USB
83  * @halmac_adapter : the adapter of halmac
84  * Author : KaiYuan Chang/Ivan Lin
85  * Return : enum halmac_ret_status
86  * More details of status code can be found in prototype document
87  */
88 enum halmac_ret_status
89 halmac_deinit_usb_cfg_88xx(struct halmac_adapter *halmac_adapter)
90 {
91         void *driver_adapter = NULL;
92
93         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
94                 return HALMAC_RET_ADAPTER_INVALID;
95
96         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
97                 return HALMAC_RET_API_INVALID;
98
99         halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_DEINIT_USB_CFG);
100
101         driver_adapter = halmac_adapter->driver_adapter;
102
103         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
104                         "%s ==========>\n", __func__);
105
106         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
107                         "%s <==========\n", __func__);
108
109         return HALMAC_RET_SUCCESS;
110 }
111
112 /**
113  * halmac_cfg_rx_aggregation_88xx_usb() - config rx aggregation
114  * @halmac_adapter : the adapter of halmac
115  * @halmac_rx_agg_mode
116  * Author : KaiYuan Chang/Ivan Lin
117  * Return : enum halmac_ret_status
118  * More details of status code can be found in prototype document
119  */
120 enum halmac_ret_status
121 halmac_cfg_rx_aggregation_88xx_usb(struct halmac_adapter *halmac_adapter,
122                                    struct halmac_rxagg_cfg *phalmac_rxagg_cfg)
123 {
124         u8 dma_usb_agg;
125         u8 size = 0, timeout = 0, agg_enable = 0;
126         void *driver_adapter = NULL;
127         struct halmac_api *halmac_api;
128
129         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
130                 return HALMAC_RET_ADAPTER_INVALID;
131
132         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
133                 return HALMAC_RET_API_INVALID;
134
135         halmac_api_record_id_88xx(halmac_adapter,
136                                   HALMAC_API_CFG_RX_AGGREGATION);
137
138         driver_adapter = halmac_adapter->driver_adapter;
139         halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
140
141         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
142                         "%s ==========>\n", __func__);
143
144         dma_usb_agg =
145                 HALMAC_REG_READ_8(halmac_adapter, REG_RXDMA_AGG_PG_TH + 3);
146         agg_enable = HALMAC_REG_READ_8(halmac_adapter, REG_TXDMA_PQ_MAP);
147
148         switch (phalmac_rxagg_cfg->mode) {
149         case HALMAC_RX_AGG_MODE_NONE:
150                 agg_enable &= ~BIT_RXDMA_AGG_EN;
151                 break;
152         case HALMAC_RX_AGG_MODE_DMA:
153                 agg_enable |= BIT_RXDMA_AGG_EN;
154                 dma_usb_agg |= BIT(7);
155                 break;
156
157         case HALMAC_RX_AGG_MODE_USB:
158                 agg_enable |= BIT_RXDMA_AGG_EN;
159                 dma_usb_agg &= ~BIT(7);
160                 break;
161         default:
162                 pr_err("%s switch case not support\n", __func__);
163                 agg_enable &= ~BIT_RXDMA_AGG_EN;
164                 break;
165         }
166
167         if (!phalmac_rxagg_cfg->threshold.drv_define) {
168                 if (PLATFORM_REG_READ_8(driver_adapter, REG_SYS_CFG2 + 3) ==
169                     0x20) {
170                         /* usb3.0 */
171                         size = 0x5;
172                         timeout = 0xA;
173                 } else {
174                         /* usb2.0 */
175                         size = 0x5;
176                         timeout = 0x20;
177                 }
178         } else {
179                 size = phalmac_rxagg_cfg->threshold.size;
180                 timeout = phalmac_rxagg_cfg->threshold.timeout;
181         }
182
183         HALMAC_REG_WRITE_8(halmac_adapter, REG_TXDMA_PQ_MAP, agg_enable);
184         HALMAC_REG_WRITE_8(halmac_adapter, REG_RXDMA_AGG_PG_TH + 3,
185                            dma_usb_agg);
186         HALMAC_REG_WRITE_16(halmac_adapter, REG_RXDMA_AGG_PG_TH,
187                             (u16)(size | (timeout << BIT_SHIFT_DMA_AGG_TO)));
188
189         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
190                         "%s <==========\n", __func__);
191
192         return HALMAC_RET_SUCCESS;
193 }
194
195 /**
196  * halmac_reg_read_8_usb_88xx() - read 1byte register
197  * @halmac_adapter : the adapter of halmac
198  * @halmac_offset : register offset
199  * Author : KaiYuan Chang/Ivan Lin
200  * Return : enum halmac_ret_status
201  * More details of status code can be found in prototype document
202  */
203 u8 halmac_reg_read_8_usb_88xx(struct halmac_adapter *halmac_adapter,
204                               u32 halmac_offset)
205 {
206         u8 value8;
207         void *driver_adapter = NULL;
208         struct halmac_api *halmac_api;
209
210         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
211                 return HALMAC_RET_ADAPTER_INVALID;
212
213         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
214                 return HALMAC_RET_API_INVALID;
215
216         driver_adapter = halmac_adapter->driver_adapter;
217         halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
218
219         value8 = PLATFORM_REG_READ_8(driver_adapter, halmac_offset);
220
221         return value8;
222 }
223
224 /**
225  * halmac_reg_write_8_usb_88xx() - write 1byte register
226  * @halmac_adapter : the adapter of halmac
227  * @halmac_offset : register offset
228  * @halmac_data : register value
229  * Author : KaiYuan Chang/Ivan Lin
230  * Return : enum halmac_ret_status
231  * More details of status code can be found in prototype document
232  */
233 enum halmac_ret_status
234 halmac_reg_write_8_usb_88xx(struct halmac_adapter *halmac_adapter,
235                             u32 halmac_offset, u8 halmac_data)
236 {
237         void *driver_adapter = NULL;
238         struct halmac_api *halmac_api;
239
240         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
241                 return HALMAC_RET_ADAPTER_INVALID;
242
243         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
244                 return HALMAC_RET_API_INVALID;
245
246         driver_adapter = halmac_adapter->driver_adapter;
247         halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
248
249         PLATFORM_REG_WRITE_8(driver_adapter, halmac_offset, halmac_data);
250
251         return HALMAC_RET_SUCCESS;
252 }
253
254 /**
255  * halmac_reg_read_16_usb_88xx() - read 2byte register
256  * @halmac_adapter : the adapter of halmac
257  * @halmac_offset : register offset
258  * Author : KaiYuan Chang/Ivan Lin
259  * Return : enum halmac_ret_status
260  * More details of status code can be found in prototype document
261  */
262 u16 halmac_reg_read_16_usb_88xx(struct halmac_adapter *halmac_adapter,
263                                 u32 halmac_offset)
264 {
265         void *driver_adapter = NULL;
266         struct halmac_api *halmac_api;
267
268         union {
269                 u16 word;
270                 u8 byte[2];
271         } value16 = {0x0000};
272
273         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
274                 return HALMAC_RET_ADAPTER_INVALID;
275
276         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
277                 return HALMAC_RET_API_INVALID;
278
279         driver_adapter = halmac_adapter->driver_adapter;
280         halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
281
282         value16.word = PLATFORM_REG_READ_16(driver_adapter, halmac_offset);
283
284         return value16.word;
285 }
286
287 /**
288  * halmac_reg_write_16_usb_88xx() - write 2byte register
289  * @halmac_adapter : the adapter of halmac
290  * @halmac_offset : register offset
291  * @halmac_data : register value
292  * Author : KaiYuan Chang/Ivan Lin
293  * Return : enum halmac_ret_status
294  * More details of status code can be found in prototype document
295  */
296 enum halmac_ret_status
297 halmac_reg_write_16_usb_88xx(struct halmac_adapter *halmac_adapter,
298                              u32 halmac_offset, u16 halmac_data)
299 {
300         void *driver_adapter = NULL;
301         struct halmac_api *halmac_api;
302
303         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
304                 return HALMAC_RET_ADAPTER_INVALID;
305
306         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
307                 return HALMAC_RET_API_INVALID;
308
309         driver_adapter = halmac_adapter->driver_adapter;
310         halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
311
312         PLATFORM_REG_WRITE_16(driver_adapter, halmac_offset, halmac_data);
313
314         return HALMAC_RET_SUCCESS;
315 }
316
317 /**
318  * halmac_reg_read_32_usb_88xx() - read 4byte register
319  * @halmac_adapter : the adapter of halmac
320  * @halmac_offset : register offset
321  * Author : KaiYuan Chang/Ivan Lin
322  * Return : enum halmac_ret_status
323  * More details of status code can be found in prototype document
324  */
325 u32 halmac_reg_read_32_usb_88xx(struct halmac_adapter *halmac_adapter,
326                                 u32 halmac_offset)
327 {
328         void *driver_adapter = NULL;
329         struct halmac_api *halmac_api;
330
331         union {
332                 u32 dword;
333                 u8 byte[4];
334         } value32 = {0x00000000};
335
336         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
337                 return HALMAC_RET_ADAPTER_INVALID;
338
339         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
340                 return HALMAC_RET_API_INVALID;
341
342         driver_adapter = halmac_adapter->driver_adapter;
343         halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
344
345         value32.dword = PLATFORM_REG_READ_32(driver_adapter, halmac_offset);
346
347         return value32.dword;
348 }
349
350 /**
351  * halmac_reg_write_32_usb_88xx() - write 4byte register
352  * @halmac_adapter : the adapter of halmac
353  * @halmac_offset : register offset
354  * @halmac_data : register value
355  * Author : KaiYuan Chang/Ivan Lin
356  * Return : enum halmac_ret_status
357  * More details of status code can be found in prototype document
358  */
359 enum halmac_ret_status
360 halmac_reg_write_32_usb_88xx(struct halmac_adapter *halmac_adapter,
361                              u32 halmac_offset, u32 halmac_data)
362 {
363         void *driver_adapter = NULL;
364         struct halmac_api *halmac_api;
365
366         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
367                 return HALMAC_RET_ADAPTER_INVALID;
368
369         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
370                 return HALMAC_RET_API_INVALID;
371
372         driver_adapter = halmac_adapter->driver_adapter;
373         halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
374
375         PLATFORM_REG_WRITE_32(driver_adapter, halmac_offset, halmac_data);
376
377         return HALMAC_RET_SUCCESS;
378 }
379
380 /**
381  * halmac_set_bulkout_num_usb_88xx() - inform bulk-out num
382  * @halmac_adapter : the adapter of halmac
383  * @bulkout_num : usb bulk-out number
384  * Author : KaiYuan Chang
385  * Return : enum halmac_ret_status
386  * More details of status code can be found in prototype document
387  */
388 enum halmac_ret_status
389 halmac_set_bulkout_num_88xx(struct halmac_adapter *halmac_adapter,
390                             u8 bulkout_num)
391 {
392         void *driver_adapter = NULL;
393         struct halmac_api *halmac_api;
394
395         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
396                 return HALMAC_RET_ADAPTER_INVALID;
397
398         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
399                 return HALMAC_RET_API_INVALID;
400
401         halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_SET_BULKOUT_NUM);
402
403         driver_adapter = halmac_adapter->driver_adapter;
404         halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
405
406         halmac_adapter->halmac_bulkout_num = bulkout_num;
407
408         return HALMAC_RET_SUCCESS;
409 }
410
411 /**
412  * halmac_get_usb_bulkout_id_usb_88xx() - get bulk out id for the TX packet
413  * @halmac_adapter : the adapter of halmac
414  * @halmac_buf : tx packet, include txdesc
415  * @halmac_size : tx packet size
416  * @bulkout_id : usb bulk-out id
417  * Author : KaiYuan Chang
418  * Return : enum halmac_ret_status
419  * More details of status code can be found in prototype document
420  */
421 enum halmac_ret_status
422 halmac_get_usb_bulkout_id_88xx(struct halmac_adapter *halmac_adapter,
423                                u8 *halmac_buf, u32 halmac_size, u8 *bulkout_id)
424 {
425         void *driver_adapter = NULL;
426         struct halmac_api *halmac_api;
427         enum halmac_queue_select queue_sel;
428         enum halmac_dma_mapping dma_mapping;
429
430         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
431                 return HALMAC_RET_ADAPTER_INVALID;
432
433         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
434                 return HALMAC_RET_API_INVALID;
435
436         halmac_api_record_id_88xx(halmac_adapter,
437                                   HALMAC_API_GET_USB_BULKOUT_ID);
438
439         driver_adapter = halmac_adapter->driver_adapter;
440         halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
441
442         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
443                         "%s ==========>\n", __func__);
444
445         if (!halmac_buf) {
446                 pr_err("halmac_buf is NULL!!\n");
447                 return HALMAC_RET_DATA_BUF_NULL;
448         }
449
450         if (halmac_size == 0) {
451                 pr_err("halmac_size is 0!!\n");
452                 return HALMAC_RET_DATA_SIZE_INCORRECT;
453         }
454
455         queue_sel = (enum halmac_queue_select)GET_TX_DESC_QSEL(halmac_buf);
456
457         switch (queue_sel) {
458         case HALMAC_QUEUE_SELECT_VO:
459         case HALMAC_QUEUE_SELECT_VO_V2:
460                 dma_mapping =
461                         halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_VO];
462                 break;
463         case HALMAC_QUEUE_SELECT_VI:
464         case HALMAC_QUEUE_SELECT_VI_V2:
465                 dma_mapping =
466                         halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_VI];
467                 break;
468         case HALMAC_QUEUE_SELECT_BE:
469         case HALMAC_QUEUE_SELECT_BE_V2:
470                 dma_mapping =
471                         halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_BE];
472                 break;
473         case HALMAC_QUEUE_SELECT_BK:
474         case HALMAC_QUEUE_SELECT_BK_V2:
475                 dma_mapping =
476                         halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_BK];
477                 break;
478         case HALMAC_QUEUE_SELECT_MGNT:
479                 dma_mapping =
480                         halmac_adapter->halmac_ptcl_queue[HALMAC_PTCL_QUEUE_MG];
481                 break;
482         case HALMAC_QUEUE_SELECT_HIGH:
483         case HALMAC_QUEUE_SELECT_BCN:
484         case HALMAC_QUEUE_SELECT_CMD:
485                 dma_mapping = HALMAC_DMA_MAPPING_HIGH;
486                 break;
487         default:
488                 pr_err("Qsel is out of range\n");
489                 return HALMAC_RET_QSEL_INCORRECT;
490         }
491
492         switch (dma_mapping) {
493         case HALMAC_DMA_MAPPING_HIGH:
494                 *bulkout_id = 0;
495                 break;
496         case HALMAC_DMA_MAPPING_NORMAL:
497                 *bulkout_id = 1;
498                 break;
499         case HALMAC_DMA_MAPPING_LOW:
500                 *bulkout_id = 2;
501                 break;
502         case HALMAC_DMA_MAPPING_EXTRA:
503                 *bulkout_id = 3;
504                 break;
505         default:
506                 pr_err("DmaMapping is out of range\n");
507                 return HALMAC_RET_DMA_MAP_INCORRECT;
508         }
509
510         HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
511                         "%s <==========\n", __func__);
512
513         return HALMAC_RET_SUCCESS;
514 }
515
516 /**
517  * halmac_cfg_tx_agg_align_usb_88xx() -config sdio bus tx agg alignment
518  * @halmac_adapter : the adapter of halmac
519  * @enable : function enable(1)/disable(0)
520  * @align_size : sdio bus tx agg alignment size (2^n, n = 3~11)
521  * Author : Soar Tu
522  * Return : enum halmac_ret_status
523  * More details of status code can be found in prototype document
524  */
525 enum halmac_ret_status halmac_cfg_tx_agg_align_usb_not_support_88xx(
526         struct halmac_adapter *halmac_adapter, u8 enable, u16 align_size)
527 {
528         struct halmac_api *halmac_api;
529         void *driver_adapter = NULL;
530
531         if (halmac_adapter_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
532                 return HALMAC_RET_ADAPTER_INVALID;
533
534         if (halmac_api_validate(halmac_adapter) != HALMAC_RET_SUCCESS)
535                 return HALMAC_RET_API_INVALID;
536
537         halmac_api_record_id_88xx(halmac_adapter, HALMAC_API_CFG_TX_AGG_ALIGN);
538
539         driver_adapter = halmac_adapter->driver_adapter;
540         halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
541
542         HALMAC_RT_TRACE(
543                 driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
544                 "%s ==========>\n", __func__);
545
546         HALMAC_RT_TRACE(
547                 driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
548                 "%s not support\n", __func__);
549         HALMAC_RT_TRACE(
550                 driver_adapter, HALMAC_MSG_INIT, DBG_DMESG,
551                 "%s <==========\n", __func__);
552
553         return HALMAC_RET_SUCCESS;
554 }