• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 HiSilicon (Shanghai) Technologies CO., LIMITED.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17  */
18 
19 #include "hdf_wlan_sdio.h"
20 #include "hdf_wlan_config.h"
21 #ifdef __KERNEL__
22 #include <linux/module.h>
23 #include <linux/kernel.h>
24 #include <linux/device.h>
25 #include <linux/slab.h>
26 #include <linux/types.h>
27 #include <linux/err.h>
28 #include <linux/workqueue.h>
29 #include <linux/sched.h>
30 #include <linux/delay.h>
31 #include <linux/kthread.h>
32 #include <linux/mmc/sdio.h>
33 #include <linux/mmc/card.h>
34 #include <linux/mmc/sdio_func.h>
35 #include <linux/mmc/sdio_ids.h>
36 #include <linux/mmc/host.h>
37 #include <linux/pm_runtime.h>
38 #include <linux/random.h>
39 #include <linux/completion.h>
40 #else
41 #include <linux/device.h>
42 #include <linux/module.h>
43 #include <linux/kernel.h>
44 #include <linux/slab.h>
45 #include <linux/types.h>
46 #include <linux/workqueue.h>
47 #include <linux/sched.h>
48 #include <linux/delay.h>
49 #endif
50 #include "hdf_base.h"
51 #include "hdf_log.h"
52 #include "hdf_wlan_chipdriver_manager.h"
53 
54 
55 #ifdef __KERNEL__
56 #define REG_WRITE(ADDR, VALUE)                                                                     \
57     do {                                                                                           \
58         void __iomem *reg = ioremap(ADDR, sizeof(uint32_t));                                       \
59         if (reg == NULL) {                                                                         \
60             HDF_LOGE("%s:ioremap failed!addr=0x%08x", __func__, ADDR);                             \
61             break;                                                                                 \
62         }                                                                                          \
63         HDF_LOGW("%s: Change register[0x%08x] %04x to %04x", __func__, ADDR, readl(reg), (VALUE)); \
64         writel(VALUE, reg);                                                                        \
65         iounmap(reg);                                                                              \
66     } while (0)
67 
68 #define REG_SET_BITS(ADDR, VALUE)                                                                               \
69     do {                                                                                                        \
70         void __iomem *reg = ioremap(ADDR, sizeof(uint32_t));                                                    \
71         if (reg == NULL) {                                                                                      \
72             HDF_LOGE("%s: ioremap failed!addr=0x%08x", __func__, ADDR);                                         \
73             break;                                                                                              \
74         }                                                                                                       \
75         HDF_LOGW("%s: Change register[0x%08x] %04x to %04x", __func__, ADDR, readl(reg), readl(reg) | (VALUE)); \
76         writel(readl(reg) | (VALUE), reg);                                                                      \
77         iounmap(reg);                                                                                           \
78     } while (0)
79 #else
80 #define REG_WRITE(ADDR, VALUE)                                                                     \
81     do {                                                                                           \
82         int reg = IO_DEVICE_ADDR(ADDR);                                                            \
83         HDF_LOGW("%s: Change register[0x%08x] %04x to %04x", __func__, ADDR, readl(reg), (VALUE)); \
84         writel(VALUE, reg);                                                                        \
85     } while (0)
86 
87 #define REG_SET_BITS(ADDR, VALUE)                                                                               \
88     do {                                                                                                        \
89         int reg = IO_DEVICE_ADDR(ADDR);                                                                         \
90         HDF_LOGW("%s: Change register[0x%08x] %04x to %04x", __func__, ADDR, readl(reg), readl(reg) | (VALUE)); \
91         writel(readl(reg) | (VALUE), reg);                                                                      \
92     } while (0)
93 #endif
94 
95 
ConfigHi3516DV300SDIO(uint8_t busId)96 static int32_t ConfigHi3516DV300SDIO(uint8_t busId)
97 {
98     if (busId == 2) {
99         HDF_LOGE("%s: Config Hi3516DV300 SDIO bus %d", __func__, busId);
100         const uint32_t PMC_REG_ADDR_REG0 = 0x12090000;
101         const uint32_t PIN_REG_ADDR_CLK = 0x112F0008;
102         const uint32_t PIN_REG_ADDR_CMD = 0x112F000C;
103         const uint32_t PIN_REG_ADDR_DATA0 = 0x112F0010;
104         const uint32_t PIN_REG_ADDR_DATA1 = 0x112F0014;
105         const uint32_t PIN_REG_ADDR_DATA2 = 0x112F0018;
106         const uint32_t PIN_REG_ADDR_DATA3 = 0x112F001C;
107 
108         REG_SET_BITS(PMC_REG_ADDR_REG0, 0x0080);
109         REG_WRITE(PIN_REG_ADDR_CLK, 0x601);
110         REG_WRITE(PIN_REG_ADDR_CMD, 0x501);
111         REG_WRITE(PIN_REG_ADDR_DATA0, 0x501);
112         REG_WRITE(PIN_REG_ADDR_DATA1, 0x501);
113         REG_WRITE(PIN_REG_ADDR_DATA2, 0x501);
114         REG_WRITE(PIN_REG_ADDR_DATA3, 0x501);
115         return HDF_SUCCESS;
116     }
117 
118     HDF_LOGE("%s: SDIO bus ID %d not supportted!", __func__, busId);
119     return HDF_FAILURE;
120 }
121 
ConfigHi3518EV300SDIO(uint8_t busId)122 static int32_t ConfigHi3518EV300SDIO(uint8_t busId)
123 {
124     if (busId == 1) {
125         HDF_LOGE("%s: Config Hi3518EV300 SDIO bus %d", __func__, busId);
126         const uint32_t PIN_REG_ADDR_CLK = 0x112c0048;
127         const uint32_t PIN_REG_ADDR_CMD = 0x112C004C;
128         const uint32_t PIN_REG_ADDR_DATA0 = 0x112C0064;
129         const uint32_t PIN_REG_ADDR_DATA1 = 0x112c0060;
130         const uint32_t PIN_REG_ADDR_DATA2 = 0x112c005c;
131         const uint32_t PIN_REG_ADDR_DATA3 = 0x112c0058;
132 
133         REG_WRITE(PIN_REG_ADDR_CLK, 0x1a04);
134         REG_WRITE(PIN_REG_ADDR_CMD, 0x1004);
135         REG_WRITE(PIN_REG_ADDR_DATA0, 0x1004);
136         REG_WRITE(PIN_REG_ADDR_DATA1, 0x1004);
137         REG_WRITE(PIN_REG_ADDR_DATA2, 0x1004);
138         REG_WRITE(PIN_REG_ADDR_DATA3, 0x1004);
139         return HDF_SUCCESS;
140     }
141     HDF_LOGE("%s: SDIO bus ID %d not supportted!", __func__, busId);
142     return HDF_FAILURE;
143 }
144 
HdfWlanConfigSDIO(uint8_t busId)145 int32_t HdfWlanConfigSDIO(uint8_t busId)
146 {
147     struct HdfConfigWlanRoot *config = HdfWlanGetModuleConfigRoot();
148     if (config == NULL || config->wlanConfig.hostChipName == NULL) {
149         HDF_LOGE("%s: No config or chip name is NULL!", __func__);
150         return HDF_FAILURE;
151     }
152     if (strcmp("hi3516dv300", config->wlanConfig.hostChipName) == 0) {
153         return ConfigHi3516DV300SDIO(busId);
154     }
155     if (strcmp("hi3518ev300", config->wlanConfig.hostChipName) == 0) {
156         return ConfigHi3518EV300SDIO(busId);
157     }
158     HDF_LOGE("%s: platform chip not supported!", __func__);
159     return HDF_FAILURE;
160 }
161