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