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 /* ****************************************************************************
20 1 Header File Including
21 **************************************************************************** */
22 #include "oal_sdio.h"
23 #include "oal_sdio_host_if.h"
24 #include "oal_mm.h"
25
26 #include "plat_sdio.h"
27 #include "plat_pm.h"
28 #include "plat_firmware.h"
29 #include "oal_time.h"
30 #include "oam_ext_if.h"
31
32 #if (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION)
33 extern struct sdio_func *g_p_gst_sdio_func;
34 #endif
35
36 /* ****************************************************************************
37 2 Global Variable Definition
38 **************************************************************************** */
39 /* ****************************************************************************
40 3 Function Definition
41 **************************************************************************** */
42 /*
43 * Description : provide interface for pm driver
44 * Input : hi_u8* buf, hi_u32 len
45 * Output : None
46 * Return Value : hi_s32
47 *
48 */
sdio_patch_writesb(hi_u8 * buf,hi_u32 len)49 hi_s32 sdio_patch_writesb(hi_u8 *buf, hi_u32 len)
50 {
51 int ret;
52 struct BusDev *bus = oal_get_bus_default_handler();
53
54 if (bus == NULL || bus->priData.data == NULL) {
55 return -FAILURE;
56 }
57
58 if (buf == NULL || len == 0) {
59 return -FAILURE;
60 }
61
62 len = HISDIO_ALIGN_4_OR_BLK(len);
63
64 bus->ops.claimHost(bus);
65 ret = bus->ops.bulkWrite(bus, HISDIO_REG_FUNC1_FIFO, len, buf, 0);
66 bus->ops.releaseHost(bus);
67 return ret;
68 }
69
70 /*
71 * Description : provide interface for pm driver
72 * Input : hi_u8* buf, hi_u32 len hi_u32 timeout (ms)
73 * Output : None
74 * Return Value : hi_s32
75 */
sdio_patch_readsb(hi_u8 * buf,hi_u32 len,hi_u32 timeout)76 hi_s32 sdio_patch_readsb(hi_u8 *buf, hi_u32 len, hi_u32 timeout)
77 {
78 hi_u8 int_mask;
79 hi_u8 *ver_info = HI_NULL;
80 int ret = 0;
81 unsigned long timeout_jiffies;
82 hi_u32 xfer_count;
83 hi_u32 i;
84 struct BusDev *bus = oal_get_bus_default_handler();
85 hi_u8 *bus_buf = NULL;
86
87 if (bus == NULL || bus->priData.data == NULL) {
88 return -FAILURE;
89 }
90
91 if (buf == NULL || len == 0) {
92 return -FAILURE;
93 }
94 bus->ops.claimHost(bus);
95 timeout_jiffies = OAL_TIME_JIFFY + OAL_MSECS_TO_JIFFIES(timeout);
96 for (;;) {
97 ret = bus->ops.readData(bus, HISDIO_REG_FUNC1_INT_STATUS, ONE_BYTE, &int_mask);
98 if (ret) {
99 bus->ops.releaseHost(bus);
100 return -FAILURE;
101 }
102
103 if (int_mask & HISDIO_FUNC1_INT_MASK) {
104 /* sdio int came */
105 break;
106 }
107
108 if (oal_time_after(OAL_TIME_JIFFY, timeout_jiffies) > 0) {
109 bus->ops.releaseHost(bus);
110 return -FAILURE;
111 }
112 #if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION)
113 cpu_relax();
114 #endif
115 }
116
117 bus_buf = &int_mask;
118 ret = bus->ops.writeData(bus, HISDIO_REG_FUNC1_INT_STATUS, ONE_BYTE, bus_buf);
119 if (ret < 0) {
120 bus->ops.releaseHost(bus);
121 return -FAILURE;
122 }
123
124 timeout_jiffies = OAL_TIME_JIFFY + OAL_MSECS_TO_JIFFIES(timeout);
125 for (;;) {
126 ret = bus->ops.readData(bus, HISDIO_REG_FUNC1_INT_STATUS, ONE_BYTE, &int_mask);
127 if (ret) {
128 bus->ops.releaseHost(bus);
129 return -FAILURE;
130 }
131
132 if ((int_mask & HISDIO_FUNC1_INT_MASK) == 0) {
133 /* sdio int came */
134 break;
135 }
136
137 if (oal_time_after((hi_u32)OAL_TIME_JIFFY, timeout_jiffies) > 0) {
138 bus->ops.releaseHost(bus);
139 return -FAILURE;
140 }
141 #if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION)
142 cpu_relax();
143 #endif
144 }
145 bus_buf = (hi_u8 *)&xfer_count;
146 ret = bus->ops.readData(bus, HISDIO_REG_FUNC1_XFER_COUNT, FOUR_BYTE, bus_buf);
147 if (ret < 0) {
148 bus->ops.releaseHost(bus);
149 return -FAILURE;
150 }
151
152 if (xfer_count < len) {
153 len = xfer_count;
154 }
155 #if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION)
156 ver_info = oal_kzalloc((xfer_count + 1), OAL_GFP_KERNEL);
157 #elif (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION)
158 ver_info = (hi_u8 *)memalign(32, SKB_DATA_ALIGN(xfer_count + 1)); /* 32 */
159 #endif
160 if (ver_info == NULL) {
161 bus->ops.releaseHost(bus);
162 return -ENOMEM;
163 }
164
165 /* 安全编程规则6.6例外(3) 从堆中分配内存后,赋予初值 */
166 memset_s(ver_info, xfer_count + 1, 0, xfer_count);
167 ret = bus->ops.bulkRead(bus, HISDIO_REG_FUNC1_FIFO, xfer_count, ver_info, 0);
168 if (ret >= 0) {
169 for (i = 0; i < len; i++) {
170 buf[i] = ver_info[i];
171 }
172 }
173 oal_free(ver_info);
174
175 bus->ops.releaseHost(bus);
176
177 return xfer_count;
178 }
179