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