├── LICENSE
├── Makefile
├── adapter.h
├── esp.h
├── esp_api.h
├── esp_bt.c
├── esp_bt_api.h
├── esp_if.h
├── esp_rb.c
├── esp_rb.h
├── esp_serial.c
├── esp_serial.h
├── main.c
├── sdio
├── esp_sdio.c
├── esp_sdio_api.c
├── esp_sdio_api.h
└── esp_sdio_decl.h
└── spi
├── esp_spi.c
└── esp_spi.h
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 2, June 1991
3 |
4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | Preamble
10 |
11 | The licenses for most software are designed to take away your
12 | freedom to share and change it. By contrast, the GNU General Public
13 | License is intended to guarantee your freedom to share and change free
14 | software--to make sure the software is free for all its users. This
15 | General Public License applies to most of the Free Software
16 | Foundation's software and to any other program whose authors commit to
17 | using it. (Some other Free Software Foundation software is covered by
18 | the GNU Lesser General Public License instead.) You can apply it to
19 | your programs, too.
20 |
21 | When we speak of free software, we are referring to freedom, not
22 | price. Our General Public Licenses are designed to make sure that you
23 | have the freedom to distribute copies of free software (and charge for
24 | this service if you wish), that you receive source code or can get it
25 | if you want it, that you can change the software or use pieces of it
26 | in new free programs; and that you know you can do these things.
27 |
28 | To protect your rights, we need to make restrictions that forbid
29 | anyone to deny you these rights or to ask you to surrender the rights.
30 | These restrictions translate to certain responsibilities for you if you
31 | distribute copies of the software, or if you modify it.
32 |
33 | For example, if you distribute copies of such a program, whether
34 | gratis or for a fee, you must give the recipients all the rights that
35 | you have. You must make sure that they, too, receive or can get the
36 | source code. And you must show them these terms so they know their
37 | rights.
38 |
39 | We protect your rights with two steps: (1) copyright the software, and
40 | (2) offer you this license which gives you legal permission to copy,
41 | distribute and/or modify the software.
42 |
43 | Also, for each author's protection and ours, we want to make certain
44 | that everyone understands that there is no warranty for this free
45 | software. If the software is modified by someone else and passed on, we
46 | want its recipients to know that what they have is not the original, so
47 | that any problems introduced by others will not reflect on the original
48 | authors' reputations.
49 |
50 | Finally, any free program is threatened constantly by software
51 | patents. We wish to avoid the danger that redistributors of a free
52 | program will individually obtain patent licenses, in effect making the
53 | program proprietary. To prevent this, we have made it clear that any
54 | patent must be licensed for everyone's free use or not licensed at all.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | GNU GENERAL PUBLIC LICENSE
60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61 |
62 | 0. This License applies to any program or other work which contains
63 | a notice placed by the copyright holder saying it may be distributed
64 | under the terms of this General Public License. The "Program", below,
65 | refers to any such program or work, and a "work based on the Program"
66 | means either the Program or any derivative work under copyright law:
67 | that is to say, a work containing the Program or a portion of it,
68 | either verbatim or with modifications and/or translated into another
69 | language. (Hereinafter, translation is included without limitation in
70 | the term "modification".) Each licensee is addressed as "you".
71 |
72 | Activities other than copying, distribution and modification are not
73 | covered by this License; they are outside its scope. The act of
74 | running the Program is not restricted, and the output from the Program
75 | is covered only if its contents constitute a work based on the
76 | Program (independent of having been made by running the Program).
77 | Whether that is true depends on what the Program does.
78 |
79 | 1. You may copy and distribute verbatim copies of the Program's
80 | source code as you receive it, in any medium, provided that you
81 | conspicuously and appropriately publish on each copy an appropriate
82 | copyright notice and disclaimer of warranty; keep intact all the
83 | notices that refer to this License and to the absence of any warranty;
84 | and give any other recipients of the Program a copy of this License
85 | along with the Program.
86 |
87 | You may charge a fee for the physical act of transferring a copy, and
88 | you may at your option offer warranty protection in exchange for a fee.
89 |
90 | 2. You may modify your copy or copies of the Program or any portion
91 | of it, thus forming a work based on the Program, and copy and
92 | distribute such modifications or work under the terms of Section 1
93 | above, provided that you also meet all of these conditions:
94 |
95 | a) You must cause the modified files to carry prominent notices
96 | stating that you changed the files and the date of any change.
97 |
98 | b) You must cause any work that you distribute or publish, that in
99 | whole or in part contains or is derived from the Program or any
100 | part thereof, to be licensed as a whole at no charge to all third
101 | parties under the terms of this License.
102 |
103 | c) If the modified program normally reads commands interactively
104 | when run, you must cause it, when started running for such
105 | interactive use in the most ordinary way, to print or display an
106 | announcement including an appropriate copyright notice and a
107 | notice that there is no warranty (or else, saying that you provide
108 | a warranty) and that users may redistribute the program under
109 | these conditions, and telling the user how to view a copy of this
110 | License. (Exception: if the Program itself is interactive but
111 | does not normally print such an announcement, your work based on
112 | the Program is not required to print an announcement.)
113 |
114 | These requirements apply to the modified work as a whole. If
115 | identifiable sections of that work are not derived from the Program,
116 | and can be reasonably considered independent and separate works in
117 | themselves, then this License, and its terms, do not apply to those
118 | sections when you distribute them as separate works. But when you
119 | distribute the same sections as part of a whole which is a work based
120 | on the Program, the distribution of the whole must be on the terms of
121 | this License, whose permissions for other licensees extend to the
122 | entire whole, and thus to each and every part regardless of who wrote it.
123 |
124 | Thus, it is not the intent of this section to claim rights or contest
125 | your rights to work written entirely by you; rather, the intent is to
126 | exercise the right to control the distribution of derivative or
127 | collective works based on the Program.
128 |
129 | In addition, mere aggregation of another work not based on the Program
130 | with the Program (or with a work based on the Program) on a volume of
131 | a storage or distribution medium does not bring the other work under
132 | the scope of this License.
133 |
134 | 3. You may copy and distribute the Program (or a work based on it,
135 | under Section 2) in object code or executable form under the terms of
136 | Sections 1 and 2 above provided that you also do one of the following:
137 |
138 | a) Accompany it with the complete corresponding machine-readable
139 | source code, which must be distributed under the terms of Sections
140 | 1 and 2 above on a medium customarily used for software interchange; or,
141 |
142 | b) Accompany it with a written offer, valid for at least three
143 | years, to give any third party, for a charge no more than your
144 | cost of physically performing source distribution, a complete
145 | machine-readable copy of the corresponding source code, to be
146 | distributed under the terms of Sections 1 and 2 above on a medium
147 | customarily used for software interchange; or,
148 |
149 | c) Accompany it with the information you received as to the offer
150 | to distribute corresponding source code. (This alternative is
151 | allowed only for noncommercial distribution and only if you
152 | received the program in object code or executable form with such
153 | an offer, in accord with Subsection b above.)
154 |
155 | The source code for a work means the preferred form of the work for
156 | making modifications to it. For an executable work, complete source
157 | code means all the source code for all modules it contains, plus any
158 | associated interface definition files, plus the scripts used to
159 | control compilation and installation of the executable. However, as a
160 | special exception, the source code distributed need not include
161 | anything that is normally distributed (in either source or binary
162 | form) with the major components (compiler, kernel, and so on) of the
163 | operating system on which the executable runs, unless that component
164 | itself accompanies the executable.
165 |
166 | If distribution of executable or object code is made by offering
167 | access to copy from a designated place, then offering equivalent
168 | access to copy the source code from the same place counts as
169 | distribution of the source code, even though third parties are not
170 | compelled to copy the source along with the object code.
171 |
172 | 4. You may not copy, modify, sublicense, or distribute the Program
173 | except as expressly provided under this License. Any attempt
174 | otherwise to copy, modify, sublicense or distribute the Program is
175 | void, and will automatically terminate your rights under this License.
176 | However, parties who have received copies, or rights, from you under
177 | this License will not have their licenses terminated so long as such
178 | parties remain in full compliance.
179 |
180 | 5. You are not required to accept this License, since you have not
181 | signed it. However, nothing else grants you permission to modify or
182 | distribute the Program or its derivative works. These actions are
183 | prohibited by law if you do not accept this License. Therefore, by
184 | modifying or distributing the Program (or any work based on the
185 | Program), you indicate your acceptance of this License to do so, and
186 | all its terms and conditions for copying, distributing or modifying
187 | the Program or works based on it.
188 |
189 | 6. Each time you redistribute the Program (or any work based on the
190 | Program), the recipient automatically receives a license from the
191 | original licensor to copy, distribute or modify the Program subject to
192 | these terms and conditions. You may not impose any further
193 | restrictions on the recipients' exercise of the rights granted herein.
194 | You are not responsible for enforcing compliance by third parties to
195 | this License.
196 |
197 | 7. If, as a consequence of a court judgment or allegation of patent
198 | infringement or for any other reason (not limited to patent issues),
199 | conditions are imposed on you (whether by court order, agreement or
200 | otherwise) that contradict the conditions of this License, they do not
201 | excuse you from the conditions of this License. If you cannot
202 | distribute so as to satisfy simultaneously your obligations under this
203 | License and any other pertinent obligations, then as a consequence you
204 | may not distribute the Program at all. For example, if a patent
205 | license would not permit royalty-free redistribution of the Program by
206 | all those who receive copies directly or indirectly through you, then
207 | the only way you could satisfy both it and this License would be to
208 | refrain entirely from distribution of the Program.
209 |
210 | If any portion of this section is held invalid or unenforceable under
211 | any particular circumstance, the balance of the section is intended to
212 | apply and the section as a whole is intended to apply in other
213 | circumstances.
214 |
215 | It is not the purpose of this section to induce you to infringe any
216 | patents or other property right claims or to contest validity of any
217 | such claims; this section has the sole purpose of protecting the
218 | integrity of the free software distribution system, which is
219 | implemented by public license practices. Many people have made
220 | generous contributions to the wide range of software distributed
221 | through that system in reliance on consistent application of that
222 | system; it is up to the author/donor to decide if he or she is willing
223 | to distribute software through any other system and a licensee cannot
224 | impose that choice.
225 |
226 | This section is intended to make thoroughly clear what is believed to
227 | be a consequence of the rest of this License.
228 |
229 | 8. If the distribution and/or use of the Program is restricted in
230 | certain countries either by patents or by copyrighted interfaces, the
231 | original copyright holder who places the Program under this License
232 | may add an explicit geographical distribution limitation excluding
233 | those countries, so that distribution is permitted only in or among
234 | countries not thus excluded. In such case, this License incorporates
235 | the limitation as if written in the body of this License.
236 |
237 | 9. The Free Software Foundation may publish revised and/or new versions
238 | of the General Public License from time to time. Such new versions will
239 | be similar in spirit to the present version, but may differ in detail to
240 | address new problems or concerns.
241 |
242 | Each version is given a distinguishing version number. If the Program
243 | specifies a version number of this License which applies to it and "any
244 | later version", you have the option of following the terms and conditions
245 | either of that version or of any later version published by the Free
246 | Software Foundation. If the Program does not specify a version number of
247 | this License, you may choose any version ever published by the Free Software
248 | Foundation.
249 |
250 | 10. If you wish to incorporate parts of the Program into other free
251 | programs whose distribution conditions are different, write to the author
252 | to ask for permission. For software which is copyrighted by the Free
253 | Software Foundation, write to the Free Software Foundation; we sometimes
254 | make exceptions for this. Our decision will be guided by the two goals
255 | of preserving the free status of all derivatives of our free software and
256 | of promoting the sharing and reuse of software generally.
257 |
258 | NO WARRANTY
259 |
260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268 | REPAIR OR CORRECTION.
269 |
270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278 | POSSIBILITY OF SUCH DAMAGES.
279 |
280 | END OF TERMS AND CONDITIONS
281 |
282 | How to Apply These Terms to Your New Programs
283 |
284 | If you develop a new program, and you want it to be of the greatest
285 | possible use to the public, the best way to achieve this is to make it
286 | free software which everyone can redistribute and change under these terms.
287 |
288 | To do so, attach the following notices to the program. It is safest
289 | to attach them to the start of each source file to most effectively
290 | convey the exclusion of warranty; and each file should have at least
291 | the "copyright" line and a pointer to where the full notice is found.
292 |
293 | {description}
294 | Copyright (C) {year} {fullname}
295 |
296 | This program is free software; you can redistribute it and/or modify
297 | it under the terms of the GNU General Public License as published by
298 | the Free Software Foundation; either version 2 of the License, or
299 | (at your option) any later version.
300 |
301 | This program is distributed in the hope that it will be useful,
302 | but WITHOUT ANY WARRANTY; without even the implied warranty of
303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304 | GNU General Public License for more details.
305 |
306 | You should have received a copy of the GNU General Public License along
307 | with this program; if not, write to the Free Software Foundation, Inc.,
308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309 |
310 | Also add information on how to contact you by electronic and paper mail.
311 |
312 | If the program is interactive, make it output a short notice like this
313 | when it starts in an interactive mode:
314 |
315 | Gnomovision version 69, Copyright (C) year name of author
316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317 | This is free software, and you are welcome to redistribute it
318 | under certain conditions; type `show c' for details.
319 |
320 | The hypothetical commands `show w' and `show c' should show the appropriate
321 | parts of the General Public License. Of course, the commands you use may
322 | be called something other than `show w' and `show c'; they could even be
323 | mouse-clicks or menu items--whatever suits your program.
324 |
325 | You should also get your employer (if you work as a programmer) or your
326 | school, if any, to sign a "copyright disclaimer" for the program, if
327 | necessary. Here is a sample; alter the names:
328 |
329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330 | `Gnomovision' (which makes passes at compilers) written by James Hacker.
331 |
332 | {signature of Ty Coon}, 1 April 1989
333 | Ty Coon, President of Vice
334 |
335 | This General Public License does not permit incorporating your program into
336 | proprietary programs. If your program is a subroutine library, you may
337 | consider it more useful to permit linking proprietary applications with the
338 | library. If this is what you want to do, use the GNU Lesser General
339 | Public License instead of this License.
340 |
341 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | KERNEL_SRC ?= /lib/modules/$(shell uname -r)/build
2 |
3 | CONFIG_SUPPORT_ESP_SERIAL ?= y
4 | CONFIG_ENABLE_MONITOR_PROCESS ?= n
5 |
6 | # Default interface is SPI
7 | target ?= spi
8 |
9 | # Targets passed overrrides default value
10 | ifeq ($(target), sdio)
11 | MODULE_NAME=esp32_sdio
12 | endif
13 | ifeq ($(target), spi)
14 | MODULE_NAME=esp32_spi
15 | endif
16 |
17 | ifeq ($(CONFIG_SUPPORT_ESP_SERIAL), y)
18 | EXTRA_CFLAGS += -DCONFIG_SUPPORT_ESP_SERIAL
19 | endif
20 |
21 | ifeq ($(CONFIG_ENABLE_MONITOR_PROCESS), y)
22 | EXTRA_CFLAGS += -DCONFIG_ENABLE_MONITOR_PROCESS
23 | endif
24 |
25 | EXTRA_CFLAGS += -I$(PWD)
26 |
27 | ifeq ($(MODULE_NAME), esp32_sdio)
28 | module_objects += sdio/esp_sdio.o sdio/esp_sdio_api.o
29 | endif
30 |
31 | ifeq ($(MODULE_NAME), esp32_spi)
32 | module_objects += spi/esp_spi.o
33 | endif
34 |
35 | obj-m := $(MODULE_NAME).o
36 | $(MODULE_NAME)-y := esp_bt.o main.o $(module_objects)
37 |
38 | ifeq ($(CONFIG_SUPPORT_ESP_SERIAL), y)
39 | $(MODULE_NAME)-y += esp_serial.o esp_rb.o
40 | endif
41 |
42 | all:
43 | $(MAKE) -C $(KERNEL_SRC) M=$(CURDIR) modules $(KBUILD_OPTIONS)
44 |
45 | modules_install:
46 | $(MAKE) INSTALL_MOD_STRIP=1 -C $(KERNEL_SRC) M=$(CURDIR) modules_install
47 |
48 | clean:
49 | $(MAKE) -C $(KERNEL_SRC) M=$(CURDIR) clean
50 |
--------------------------------------------------------------------------------
/adapter.h:
--------------------------------------------------------------------------------
1 | // Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
2 | /* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
3 |
4 | #ifndef __ESP_NETWORK_ADAPTER__H
5 | #define __ESP_NETWORK_ADAPTER__H
6 |
7 | struct esp_payload_header {
8 | uint8_t if_type:4;
9 | uint8_t if_num:4;
10 | uint8_t reserved1;
11 | uint16_t len;
12 | uint16_t offset;
13 | uint8_t reserved2;
14 | union {
15 | uint8_t reserved3;
16 | uint8_t hci_pkt_type; /* Packet type for HCI interface */
17 | uint8_t priv_pkt_type; /* Packet type for priv interface */
18 | };
19 | } __attribute__((packed));
20 |
21 | typedef enum {
22 | ESP_STA_IF,
23 | ESP_AP_IF,
24 | ESP_SERIAL_IF,
25 | ESP_HCI_IF,
26 | ESP_PRIV_IF,
27 | } ESP_INTERFACE_TYPE;
28 |
29 | typedef enum {
30 | ESP_OPEN_DATA_PATH,
31 | ESP_CLOSE_DATA_PATH,
32 | ESP_RESET,
33 | } ESP_HOST_INTERRUPT;
34 |
35 |
36 | typedef enum {
37 | ESP_WLAN_SDIO_SUPPORT = (1 << 0),
38 | ESP_BT_UART_SUPPORT = (1 << 1),
39 | ESP_BT_SDIO_SUPPORT = (1 << 2),
40 | ESP_BLE_ONLY_SUPPORT = (1 << 3),
41 | ESP_BR_EDR_ONLY_SUPPORT = (1 << 4),
42 | ESP_WLAN_SPI_SUPPORT = (1 << 5),
43 | ESP_BT_SPI_SUPPORT = (1 << 6),
44 | } ESP_CAPABILITIES;
45 |
46 | typedef enum {
47 | ESP_PACKET_TYPE_EVENT,
48 | } ESP_PRIV_PACKET_TYPE;
49 |
50 | typedef enum {
51 | ESP_PRIV_EVENT_INIT,
52 | } ESP_PRIV_EVENT_TYPE;
53 |
54 | typedef enum {
55 | ESP_PRIV_CAPABILITY,
56 | } ESP_PRIV_TAG_TYPE;
57 |
58 | struct esp_priv_event {
59 | uint8_t event_type;
60 | uint8_t event_len;
61 | uint8_t event_data[0];
62 | }__attribute__((packed));
63 | #endif
64 |
--------------------------------------------------------------------------------
/esp.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Espressif Systems Wireless LAN device driver
3 | *
4 | * Copyright (C) 2015-2020 Espressif Systems (Shanghai) PTE LTD
5 | *
6 | * This software file (the "File") is distributed by Espressif Systems (Shanghai)
7 | * PTE LTD under the terms of the GNU General Public License Version 2, June 1991
8 | * (the "License"). You may use, redistribute and/or modify this File in
9 | * accordance with the terms and conditions of the License, a copy of which
10 | * is available by writing to the Free Software Foundation, Inc.,
11 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
12 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
13 | *
14 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
15 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
16 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
17 | * this warranty disclaimer.
18 | */
19 |
20 | #ifndef __esp__h_
21 | #define __esp__h_
22 |
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include "adapter.h"
29 |
30 | #define ESP_IF_TYPE_SDIO 1
31 | #define ESP_IF_TYPE_SPI 2
32 |
33 | /* Network link status */
34 | #define ESP_LINK_DOWN 0
35 | #define ESP_LINK_UP 1
36 |
37 | #define ESP_MAX_INTERFACE 2
38 |
39 | #define ESP_PAYLOAD_HEADER 8
40 | struct esp_private;
41 | struct esp_adapter;
42 |
43 | #define ACQUIRE_LOCK 1
44 | #define LOCK_ALREADY_ACQUIRED 0
45 |
46 | struct esp_adapter {
47 | u8 if_type;
48 | u32 capabilities;
49 |
50 | /* Possible types:
51 | * struct esp_sdio_context */
52 | void *if_context;
53 |
54 | struct esp_if_ops *if_ops;
55 |
56 | /* Private for each interface */
57 | struct esp_private *priv[ESP_MAX_INTERFACE];
58 | struct hci_dev *hcidev;
59 |
60 | struct workqueue_struct *if_rx_workqueue;
61 | struct work_struct if_rx_work;
62 |
63 | /* Process TX work */
64 | struct workqueue_struct *tx_workqueue;
65 | struct work_struct tx_work;
66 |
67 | /* TX queue */
68 | struct sk_buff_head tx_q;
69 |
70 | /* RX Queue */
71 | struct sk_buff_head rx_q;
72 |
73 | /* Counters */
74 | atomic_t tx_pending;
75 | atomic_t rx_pending;
76 | };
77 |
78 |
79 | struct esp_private {
80 | struct esp_adapter *adapter;
81 | struct net_device *ndev;
82 | struct net_device_stats stats;
83 | u8 link_state;
84 | u8 mac_address[6];
85 | u8 if_type;
86 | u8 if_num;
87 | };
88 |
89 | struct esp_skb_cb {
90 | struct esp_private *priv;
91 | };
92 |
93 | void deinit_adapter(void);
94 | void esp_reset(void);
95 | struct esp_adapter * init_adapter(void);
96 | #endif
97 |
--------------------------------------------------------------------------------
/esp_api.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Espressif Systems Wireless LAN device driver
3 | *
4 | * Copyright (C) 2015-2020 Espressif Systems (Shanghai) PTE LTD
5 | *
6 | * This software file (the "File") is distributed by Espressif Systems (Shanghai)
7 | * PTE LTD under the terms of the GNU General Public License Version 2, June 1991
8 | * (the "License"). You may use, redistribute and/or modify this File in
9 | * accordance with the terms and conditions of the License, a copy of which
10 | * is available by writing to the Free Software Foundation, Inc.,
11 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
12 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
13 | *
14 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
15 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
16 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
17 | * this warranty disclaimer.
18 | */
19 |
20 | #ifndef _esp_api__h_
21 | #define _esp_api__h_
22 |
23 | #include "esp.h"
24 |
25 | int esp_add_card(struct esp_adapter *adapter);
26 | int esp_remove_card(struct esp_adapter *adapter);
27 | void esp_process_new_packet_intr(struct esp_adapter *adapter);
28 | struct esp_adapter * esp_get_adapter(void);
29 | struct sk_buff * esp_alloc_skb(u32 len);
30 | int esp_send_packet(struct esp_adapter *adapter, u8 *buf, u32 size);
31 | u8 esp_is_bt_supported_over_sdio(u32 cap);
32 |
33 | #endif
34 |
--------------------------------------------------------------------------------
/esp_bt.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Espressif Systems Wireless LAN device driver
3 | *
4 | * Copyright (C) 2015-2020 Espressif Systems (Shanghai) PTE LTD
5 | *
6 | * This software file (the "File") is distributed by Espressif Systems (Shanghai)
7 | * PTE LTD under the terms of the GNU General Public License Version 2, June 1991
8 | * (the "License"). You may use, redistribute and/or modify this File in
9 | * accordance with the terms and conditions of the License, a copy of which
10 | * is available by writing to the Free Software Foundation, Inc.,
11 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
12 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
13 | *
14 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
15 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
16 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
17 | * this warranty disclaimer.
18 | */
19 | #include "esp_bt_api.h"
20 | #include "esp_api.h"
21 |
22 | void esp_hci_update_tx_counter(struct hci_dev *hdev, u8 pkt_type, size_t len)
23 | {
24 | if (hdev) {
25 | if (pkt_type == HCI_COMMAND_PKT) {
26 | hdev->stat.cmd_tx++;
27 | } else if (pkt_type == HCI_ACLDATA_PKT) {
28 | hdev->stat.acl_tx++;
29 | } else if (pkt_type == HCI_SCODATA_PKT) {
30 | hdev->stat.sco_tx++;
31 | }
32 |
33 | hdev->stat.byte_tx += len;
34 | }
35 | }
36 |
37 | void esp_hci_update_rx_counter(struct hci_dev *hdev, u8 pkt_type, size_t len)
38 | {
39 | if (hdev) {
40 | if (pkt_type == HCI_EVENT_PKT) {
41 | hdev->stat.evt_rx++;
42 | } else if (pkt_type == HCI_ACLDATA_PKT) {
43 | hdev->stat.acl_rx++;
44 | } else if (pkt_type == HCI_SCODATA_PKT) {
45 | hdev->stat.sco_rx++;
46 | }
47 |
48 | hdev->stat.byte_rx += len;
49 | }
50 | }
51 |
52 | static int esp_bt_open(struct hci_dev *hdev)
53 | {
54 | return 0;
55 | }
56 |
57 | static int esp_bt_close(struct hci_dev *hdev)
58 | {
59 | return 0;
60 | }
61 |
62 | static int esp_bt_flush(struct hci_dev *hdev)
63 | {
64 | return 0;
65 | }
66 |
67 | static int esp_bt_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
68 | {
69 | struct esp_payload_header *hdr;
70 | size_t total_len, len = skb->len;
71 | int ret = 0;
72 | struct esp_adapter *adapter = hci_get_drvdata(hdev);
73 | struct sk_buff *new_skb;
74 |
75 | if (!adapter) {
76 | printk(KERN_ERR "%s: invalid args", __func__);
77 | return -EINVAL;
78 | }
79 |
80 | total_len = len + sizeof(struct esp_payload_header);
81 |
82 | if (skb_headroom(skb) < sizeof(struct esp_payload_header)) {
83 | /* insufficent headroom to add payload header */
84 | new_skb = skb_realloc_headroom(skb, sizeof(struct esp_payload_header));
85 |
86 | if(!new_skb) {
87 | printk(KERN_ERR "%s: Failed to allocate SKB", __func__);
88 | dev_kfree_skb(skb);
89 | hdev->stat.err_tx++;
90 | return -ENOMEM;
91 | }
92 |
93 | dev_kfree_skb(skb);
94 |
95 | skb = new_skb;
96 | }
97 |
98 | skb_push(skb, sizeof(struct esp_payload_header));
99 |
100 | hdr = (struct esp_payload_header *) skb->data;
101 |
102 | memset (hdr, 0, sizeof(struct esp_payload_header));
103 |
104 | hdr->if_type = ESP_HCI_IF;
105 | hdr->if_num = 0;
106 | hdr->len = cpu_to_le16(len);
107 | hdr->offset = cpu_to_le16(sizeof(struct esp_payload_header));
108 | hdr->hci_pkt_type = hci_skb_pkt_type(skb);
109 |
110 | /* print_hex_dump_bytes("Tx:", DUMP_PREFIX_NONE, skb->data, skb->len);*/
111 | ret = esp_send_packet(adapter, skb->data, skb->len);
112 |
113 | if (ret) {
114 | hdev->stat.err_tx++;
115 | } else {
116 | esp_hci_update_tx_counter(hdev, hdr->hci_pkt_type, skb->len);
117 | }
118 |
119 | dev_kfree_skb(skb);
120 |
121 | return 0;
122 | }
123 |
124 | static int esp_bt_setup(struct hci_dev *hdev)
125 | {
126 | return 0;
127 | }
128 |
129 | static int esp_bt_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
130 | {
131 | return 0;
132 | }
133 |
134 | int esp_deinit_bt(struct esp_adapter *adapter)
135 | {
136 | struct hci_dev *hdev = NULL;
137 |
138 | if (!adapter || !adapter->hcidev)
139 | return 0;
140 |
141 | hdev = adapter->hcidev;
142 |
143 | hci_unregister_dev(hdev);
144 | hci_free_dev(hdev);
145 |
146 | adapter->hcidev = NULL;
147 |
148 | return 0;
149 | }
150 |
151 | int esp_init_bt(struct esp_adapter *adapter)
152 | {
153 | int ret = 0;
154 | struct hci_dev *hdev = NULL;
155 |
156 | if (!adapter) {
157 | return -EINVAL;
158 | }
159 |
160 | if (adapter->hcidev) {
161 | return -EEXIST;
162 | }
163 |
164 | hdev = hci_alloc_dev();
165 |
166 | if (!hdev) {
167 | BT_ERR("Can not allocate HCI device");
168 | return -ENOMEM;
169 | }
170 |
171 | adapter->hcidev = hdev;
172 | hci_set_drvdata(hdev, adapter);
173 |
174 | if (adapter->if_type == ESP_IF_TYPE_SDIO)
175 | hdev->bus = HCI_SDIO;
176 | else if (adapter->if_type == ESP_IF_TYPE_SPI)
177 | hdev->bus = HCI_SPI;
178 |
179 | hdev->open = esp_bt_open;
180 | hdev->close = esp_bt_close;
181 | hdev->flush = esp_bt_flush;
182 | hdev->send = esp_bt_send_frame;
183 | hdev->setup = esp_bt_setup;
184 | hdev->set_bdaddr = esp_bt_set_bdaddr;
185 |
186 | hdev->dev_type = HCI_PRIMARY;
187 |
188 | ret = hci_register_dev(hdev);
189 | if (ret < 0) {
190 | BT_ERR("Can not register HCI device");
191 | hci_free_dev(hdev);
192 | return -ENOMEM;
193 | }
194 |
195 | return 0;
196 | }
197 |
--------------------------------------------------------------------------------
/esp_bt_api.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Espressif Systems Wireless LAN device driver
3 | *
4 | * Copyright (C) 2015-2020 Espressif Systems (Shanghai) PTE LTD
5 | *
6 | * This software file (the "File") is distributed by Espressif Systems (Shanghai)
7 | * PTE LTD under the terms of the GNU General Public License Version 2, June 1991
8 | * (the "License"). You may use, redistribute and/or modify this File in
9 | * accordance with the terms and conditions of the License, a copy of which
10 | * is available by writing to the Free Software Foundation, Inc.,
11 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
12 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
13 | *
14 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
15 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
16 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
17 | * this warranty disclaimer.
18 | */
19 |
20 | #ifndef __esp_bt_api_h_
21 | #define __esp_bt_api_h_
22 |
23 | #include
24 | #include "esp.h"
25 |
26 |
27 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0))
28 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14))
29 | #define hci_skb_pkt_type(skb) bt_cb((skb))->pkt_type
30 | #else
31 | #error "No symbol bt_cb((skb))->pkt_type in kernel < 2.6.14"
32 | #endif
33 | #endif
34 |
35 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0))
36 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34))
37 | #define HCI_PRIMARY HCI_BREDR
38 | #else
39 | #error "No symbol HCI_BREDR found in kernel < 2.6.34"
40 | #endif
41 | #endif
42 |
43 | int esp_init_bt(struct esp_adapter *adapter);
44 | int esp_deinit_bt(struct esp_adapter *adapter);
45 | void esp_hci_update_tx_counter(struct hci_dev *hdev, u8 pkt_type, size_t len);
46 | void esp_hci_update_rx_counter(struct hci_dev *hdev, u8 pkt_type, size_t len);
47 |
48 | #endif
49 |
--------------------------------------------------------------------------------
/esp_if.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Espressif Systems Wireless LAN device driver
3 | *
4 | * Copyright (C) 2015-2020 Espressif Systems (Shanghai) PTE LTD
5 | *
6 | * This software file (the "File") is distributed by Espressif Systems (Shanghai)
7 | * PTE LTD under the terms of the GNU General Public License Version 2, June 1991
8 | * (the "License"). You may use, redistribute and/or modify this File in
9 | * accordance with the terms and conditions of the License, a copy of which
10 | * is available by writing to the Free Software Foundation, Inc.,
11 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
12 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
13 | *
14 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
15 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
16 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
17 | * this warranty disclaimer.
18 | */
19 |
20 | #ifndef __ESP_IF__H_
21 | #define __ESP_IF__H_
22 |
23 | #include "esp.h"
24 |
25 | struct esp_if_ops {
26 | int (*init)(struct esp_adapter *adapter);
27 | struct sk_buff* (*read)(struct esp_adapter *adapter);
28 | int (*write)(struct esp_adapter *adapter, u8 *buf, u32 size);
29 | int (*deinit)(struct esp_adapter *adapter);
30 | };
31 |
32 | #endif
33 |
--------------------------------------------------------------------------------
/esp_rb.c:
--------------------------------------------------------------------------------
1 | /*
2 | * The citation should list that the code comes from the book "Linux Device
3 | * Drivers" by Alessandro Rubini and Jonathan Corbet, published
4 | * by O'Reilly & Associates.No warranty is attached;
5 | *
6 | * */
7 |
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 |
16 | #include "esp_rb.h"
17 |
18 | int esp_rb_init(esp_rb_t *rb, size_t sz)
19 | {
20 | init_waitqueue_head(&(rb->wq));
21 |
22 | rb->buf = kmalloc(sz, GFP_KERNEL);
23 | if (!rb->buf) {
24 | printk(KERN_ERR "Failed to allocate memory for rb\n");
25 | return -ENOMEM;
26 | }
27 |
28 | rb->end = rb->buf + sz;
29 | rb->rp = rb->wp = rb->buf;
30 | rb->size = sz;
31 |
32 | sema_init(&(rb->sem), 1);
33 | return 0;
34 | }
35 |
36 | ssize_t esp_rb_read_by_user(esp_rb_t *rb, const char __user *buf, size_t sz, int block)
37 | {
38 | if (down_interruptible(&rb->sem)) {
39 | return -ERESTARTSYS; /* Signal interruption */
40 | }
41 |
42 | while(rb->rp == rb->wp) {
43 | up(&rb->sem);
44 | if (block == 0) {
45 | return -EAGAIN;
46 | }
47 | if (wait_event_interruptible(rb->wq, (rb->rp != rb->wp))) {
48 | return -ERESTARTSYS; /* Signal interruption */
49 | }
50 | if (down_interruptible(&rb->sem)) {
51 | return -ERESTARTSYS;
52 | }
53 | }
54 |
55 | if (rb->wp > rb->rp) {
56 | sz = min(sz, (size_t)(rb->wp - rb->rp));
57 | } else {
58 | sz = min(sz, (size_t)(rb->end - rb->rp));
59 | }
60 | if (copy_to_user((void *)buf, rb->rp, sz)) {
61 | up(&rb->sem);
62 | return -EFAULT;
63 | }
64 | rb->rp += sz;
65 | if (rb->rp == rb->end) {
66 | rb->rp = rb->buf;
67 | }
68 | up(&rb->sem);
69 |
70 | return sz;
71 | }
72 |
73 | static size_t get_free_space(esp_rb_t *rb)
74 | {
75 | if (rb->rp == rb->wp) {
76 | return rb->size - 1;
77 | } else {
78 | return ((rb->rp + rb->size - rb->wp) % rb->size) - 1;
79 | }
80 | }
81 |
82 | ssize_t esp_rb_write_by_kernel(esp_rb_t *rb, const char *buf, size_t sz)
83 | {
84 | if (down_interruptible(&rb->sem)) {
85 | return -ERESTARTSYS;
86 | }
87 |
88 | if (get_free_space(rb) == 0) {
89 | up(&rb->sem);
90 | printk(KERN_ERR "Ringbuffer full, no space to write\n");
91 | return 0;
92 | }
93 |
94 | sz = min(sz, get_free_space(rb));
95 | if (rb->wp >= rb->rp) {
96 | sz = min(sz, (size_t)(rb->end - rb->wp));
97 | } else {
98 | sz = min(sz, (size_t)(rb->rp - rb->wp - 1));
99 | }
100 |
101 | memcpy(rb->wp, buf, sz);
102 | rb->wp += sz;
103 | if (rb->wp == rb->end) {
104 | rb->wp = rb->buf;
105 | }
106 | up(&rb->sem);
107 |
108 | wake_up_interruptible(&rb->wq);
109 |
110 | return sz;
111 | }
112 |
113 | void esp_rb_cleanup(esp_rb_t *rb)
114 | {
115 | kfree(rb->buf);
116 | rb->buf = rb->end = rb->rp = rb->wp = NULL;
117 | rb->size = 0;
118 | return;
119 | }
120 |
--------------------------------------------------------------------------------
/esp_rb.h:
--------------------------------------------------------------------------------
1 | /*
2 | * The citation should list that the code comes from the book "Linux Device
3 | * Drivers" by Alessandro Rubini and Jonathan Corbet, published
4 | * by O'Reilly & Associates.No warranty is attached;
5 | *
6 | * */
7 |
8 | #ifndef _ESP_RB_H_
9 | #define _ESP_RB_H_
10 |
11 | typedef struct esp_rb {
12 | wait_queue_head_t wq; /* waitqueue to wait for data */
13 | unsigned char *buf, *end; /* actual queue start and end */
14 | size_t size;
15 | unsigned char *rp, *wp; /* current read/write pointers */
16 | struct semaphore sem; /* Mutex to protect rb */
17 | } esp_rb_t;
18 |
19 | int esp_rb_init(esp_rb_t *rb, size_t sz);
20 | void esp_rb_cleanup(esp_rb_t *rb);
21 | ssize_t esp_rb_read_by_user(esp_rb_t *rb, const char __user *buf, size_t sz, int block);
22 | ssize_t esp_rb_write_by_kernel(esp_rb_t *rb, const char *buf, size_t sz);
23 |
24 | #endif
25 |
--------------------------------------------------------------------------------
/esp_serial.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Espressif Systems Wireless LAN device driver
3 | *
4 | * Copyright (C) 2015-2020 Espressif Systems (Shanghai) PTE LTD
5 | *
6 | * This software file (the "File") is distributed by Espressif Systems (Shanghai)
7 | * PTE LTD under the terms of the GNU General Public License Version 2, June 1991
8 | * (the "License"). You may use, redistribute and/or modify this File in
9 | * accordance with the terms and conditions of the License, a copy of which
10 | * is available by writing to the Free Software Foundation, Inc.,
11 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
12 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
13 | *
14 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
15 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
16 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
17 | * this warranty disclaimer.
18 | */
19 |
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 |
30 | #include "esp.h"
31 | #include "esp_rb.h"
32 | #include "esp_api.h"
33 |
34 | #define ESP_SERIAL_MAJOR 221
35 | #define ESP_SERIAL_MINOR_MAX 2
36 | #define ESP_RX_RB_SIZE 4096
37 |
38 | //#define ESP_SERIAL_TEST
39 |
40 | bool initialized = false;
41 | static struct esp_serial_devs {
42 | struct cdev cdev;
43 | int dev_index;
44 | esp_rb_t rb;
45 | void *priv;
46 | } devs[ESP_SERIAL_MINOR_MAX];
47 |
48 | static ssize_t esp_serial_read(struct file *file, char __user *user_buffer, size_t size, loff_t *offset)
49 | {
50 | struct esp_serial_devs *dev;
51 | dev = (struct esp_serial_devs *) file->private_data;
52 | size = esp_rb_read_by_user(&dev->rb, user_buffer, size, file->f_flags & O_NONBLOCK);
53 | /* print_hex_dump_bytes("Rx:", DUMP_PREFIX_NONE, user_buffer, size);*/
54 | if (size == 0) {
55 | return -EAGAIN;
56 | }
57 |
58 | return size;
59 | }
60 |
61 | static ssize_t esp_serial_write(struct file *file, const char __user *user_buffer, size_t size, loff_t * offset)
62 | {
63 | struct esp_payload_header *hdr;
64 | char *buf;
65 | struct esp_serial_devs *dev;
66 | int ret;
67 | size_t total_len;
68 |
69 | dev = (struct esp_serial_devs *) file->private_data;
70 | total_len = size + sizeof(struct esp_payload_header);
71 |
72 | buf = kmalloc(total_len, GFP_KERNEL);
73 | if (!buf) {
74 | printk(KERN_ERR "Error allocating buffer to send serial data\n");
75 | return -ENOMEM;
76 | }
77 |
78 | hdr = (struct esp_payload_header *) buf;
79 |
80 | memset (hdr, 0, sizeof(struct esp_payload_header));
81 |
82 | hdr->if_type = ESP_SERIAL_IF;
83 | hdr->if_num = dev->dev_index;
84 | hdr->len = cpu_to_le16(size);
85 | hdr->offset = cpu_to_le16(sizeof(struct esp_payload_header));
86 |
87 | ret = copy_from_user(buf + hdr->offset, user_buffer, size);
88 | if (ret != 0) {
89 | kfree(buf);
90 | printk(KERN_ERR "Error copying buffer to send serial data\n");
91 | return -EFAULT;
92 | }
93 |
94 | ret = esp_send_packet(dev->priv, buf, total_len);
95 | if (ret) {
96 | printk (KERN_ERR "%s: Failed to transmit data\n", __func__);
97 | }
98 |
99 | kfree(buf);
100 | return size;
101 | }
102 |
103 | static long esp_serial_ioctl (struct file *file, unsigned int cmd, unsigned long arg)
104 | {
105 | printk(KERN_INFO "%s IOCTL %d\n", __func__, cmd);
106 | return 0;
107 | }
108 |
109 | static int esp_serial_open(struct inode *inode, struct file *file)
110 | {
111 | struct esp_serial_devs *devs;
112 |
113 | devs = container_of(inode->i_cdev, struct esp_serial_devs, cdev);
114 | file->private_data = devs;
115 |
116 | return 0;
117 | }
118 |
119 | const struct file_operations esp_serial_fops = {
120 | .owner = THIS_MODULE,
121 | .open = esp_serial_open,
122 | .read = esp_serial_read,
123 | .write = esp_serial_write,
124 | .unlocked_ioctl = esp_serial_ioctl
125 | };
126 |
127 | int esp_serial_data_received(int dev_index, const char *data, size_t len)
128 | {
129 | int ret;
130 | size_t ret_len = 0;
131 |
132 | while (ret_len != len) {
133 | ret = esp_rb_write_by_kernel(&devs[dev_index].rb, data, len);
134 | ret_len += ret;
135 | if (ret == 0) {
136 | break;
137 | }
138 | }
139 | if (ret_len != len) {
140 | printk(KERN_ERR "RB full, no space to receive. Dropping packet");
141 | }
142 |
143 | return ret_len;
144 | }
145 |
146 | #ifdef ESP_SERIAL_TEST
147 | static int thread_fn(void *unused)
148 | {
149 | int i = 100;
150 |
151 | while(i--) {
152 | esp_rb_write_by_kernel(&devs[0].rb, "alphabetagamma", 14);
153 | ssleep(1);
154 | }
155 | printk(KERN_INFO "Thread stopping\n");
156 | do_exit(0);
157 | return 0;
158 | }
159 | #endif
160 |
161 | int esp_serial_init(void *priv)
162 | {
163 | int err;
164 | int i;
165 |
166 | err = register_chrdev_region(MKDEV(ESP_SERIAL_MAJOR, 0), ESP_SERIAL_MINOR_MAX, "esp_serial_driver");
167 | if (err) {
168 | printk(KERN_ERR "Error registering chrdev region %d\n", err);
169 | return -1;
170 | }
171 |
172 | for (i = 0; i < ESP_SERIAL_MINOR_MAX; i++) {
173 | cdev_init(&devs[i].cdev, &esp_serial_fops);
174 | devs[i].dev_index = i;
175 | cdev_add(&devs[i].cdev, MKDEV(ESP_SERIAL_MAJOR, i), 1);
176 | esp_rb_init(&devs[i].rb, ESP_RX_RB_SIZE);
177 | devs[i].priv = priv;
178 | }
179 |
180 | #ifdef ESP_SERIAL_TEST
181 | kthread_run(thread_fn, NULL, "esptest-thread");
182 | #endif
183 | initialized = true;
184 |
185 | return 0;
186 | }
187 |
188 | void esp_serial_cleanup(void)
189 | {
190 | int i;
191 | if (!initialized)
192 | return;
193 | for (i = 0; i < ESP_SERIAL_MINOR_MAX; i++) {
194 | cdev_del(&devs[i].cdev);
195 | esp_rb_cleanup(&devs[i].rb);
196 | }
197 | unregister_chrdev_region(MKDEV(ESP_SERIAL_MAJOR, 0), ESP_SERIAL_MINOR_MAX);
198 | }
199 |
--------------------------------------------------------------------------------
/esp_serial.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Espressif Systems Wireless LAN device driver
3 | *
4 | * Copyright (C) 2015-2020 Espressif Systems (Shanghai) PTE LTD
5 | *
6 | * This software file (the "File") is distributed by Espressif Systems (Shanghai)
7 | * PTE LTD under the terms of the GNU General Public License Version 2, June 1991
8 | * (the "License"). You may use, redistribute and/or modify this File in
9 | * accordance with the terms and conditions of the License, a copy of which
10 | * is available by writing to the Free Software Foundation, Inc.,
11 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
12 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
13 | *
14 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
15 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
16 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
17 | * this warranty disclaimer.
18 | */
19 |
20 | #ifndef _ESP_SERIAL_H_
21 | #define _ESP_SERIAL_H_
22 |
23 | int esp_serial_init(void * priv);
24 | void esp_serial_cleanup(void);
25 |
26 | int esp_serial_data_received(int dev_index, const char *data, size_t len);
27 | #endif
28 |
--------------------------------------------------------------------------------
/main.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Espressif Systems Wireless LAN device driver
3 | *
4 | * Copyright (C) 2015-2020 Espressif Systems (Shanghai) PTE LTD
5 | *
6 | * This software file (the "File") is distributed by Espressif Systems (Shanghai)
7 | * PTE LTD under the terms of the GNU General Public License Version 2, June 1991
8 | * (the "License"). You may use, redistribute and/or modify this File in
9 | * accordance with the terms and conditions of the License, a copy of which
10 | * is available by writing to the Free Software Foundation, Inc.,
11 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
12 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
13 | *
14 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
15 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
16 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
17 | * this warranty disclaimer.
18 | */
19 |
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 |
30 | #include "esp.h"
31 | #include "esp_if.h"
32 | #ifdef CONFIG_SUPPORT_ESP_SERIAL
33 | #include "esp_serial.h"
34 | #endif
35 | #include "esp_bt_api.h"
36 |
37 | struct esp_adapter adapter;
38 | volatile u8 stop_data = 0;
39 |
40 | #define ACTION_DROP 1
41 | static int esp_open(struct net_device *ndev);
42 | static int esp_stop(struct net_device *ndev);
43 | static int esp_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev);
44 | static int esp_set_mac_address(struct net_device *ndev, void *addr);
45 | static void esp_tx_timeout(struct net_device *ndev);
46 | static struct net_device_stats* esp_get_stats(struct net_device *ndev);
47 | static void esp_set_rx_mode(struct net_device *ndev);
48 | int esp_send_packet(struct esp_adapter *adapter, u8 *buf, u32 size);
49 |
50 | static const struct net_device_ops esp_netdev_ops = {
51 | .ndo_open = esp_open,
52 | .ndo_stop = esp_stop,
53 | .ndo_start_xmit = esp_hard_start_xmit,
54 | .ndo_set_mac_address = esp_set_mac_address,
55 | .ndo_validate_addr = eth_validate_addr,
56 | .ndo_tx_timeout = esp_tx_timeout,
57 | .ndo_get_stats = esp_get_stats,
58 | .ndo_set_rx_mode = esp_set_rx_mode,
59 | };
60 |
61 | #if 0
62 | u64 start_time, end_time;
63 | #endif
64 |
65 | struct esp_adapter * esp_get_adapter(void)
66 | {
67 | return &adapter;
68 | }
69 |
70 | static int esp_open(struct net_device *ndev)
71 | {
72 | netif_start_queue(ndev);
73 | return 0;
74 | }
75 |
76 | static int esp_stop(struct net_device *ndev)
77 | {
78 | netif_stop_queue(ndev);
79 | return 0;
80 | }
81 |
82 | static struct net_device_stats* esp_get_stats(struct net_device *ndev)
83 | {
84 | struct esp_private *priv = netdev_priv(ndev);
85 | return &priv->stats;
86 | }
87 |
88 | static int esp_set_mac_address(struct net_device *ndev, void *data)
89 | {
90 | struct esp_private *priv = netdev_priv(ndev);
91 | struct sockaddr *mac_addr = data;
92 |
93 | if (!priv)
94 | return -EINVAL;
95 |
96 | ether_addr_copy(priv->mac_address, mac_addr->sa_data);
97 | ether_addr_copy(ndev->dev_addr, mac_addr->sa_data);
98 | return 0;
99 | }
100 |
101 | static void esp_tx_timeout(struct net_device *ndev)
102 | {
103 | }
104 |
105 | static void esp_set_rx_mode(struct net_device *ndev)
106 | {
107 | }
108 |
109 | static int esp_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev)
110 | {
111 | struct sk_buff *new_skb;
112 | struct esp_private *priv = netdev_priv(ndev);
113 | struct esp_skb_cb *cb;
114 |
115 | if (!priv) {
116 | dev_kfree_skb(skb);
117 | return -EINVAL;
118 | }
119 |
120 | if (!skb->len || (skb->len > ETH_FRAME_LEN)) {
121 | printk (KERN_ERR "%s: Bad len %d\n", __func__, skb->len);
122 | priv->stats.tx_dropped++;
123 | dev_kfree_skb(skb);
124 | return -EINVAL;
125 | }
126 |
127 | if (skb_headroom(skb) < ESP_PAYLOAD_HEADER) {
128 | /* Insufficient space. Realloc skb. */
129 | new_skb = skb_realloc_headroom(skb, ESP_PAYLOAD_HEADER);
130 |
131 | if (unlikely(!new_skb)) {
132 | printk (KERN_ERR "%s: Failed to allocate SKB\n", __func__);
133 | priv->stats.tx_dropped++;
134 | dev_kfree_skb(skb);
135 | return -ENOMEM;
136 | }
137 |
138 | /* Free old SKB */
139 | dev_kfree_skb(skb);
140 |
141 | skb = new_skb;
142 | }
143 |
144 | cb = (struct esp_skb_cb *) skb->cb;
145 | cb->priv = priv;
146 |
147 | /* print_hex_dump_bytes("Tx:", DUMP_PREFIX_NONE, skb->data, 8);*/
148 |
149 | skb_queue_tail(&adapter.tx_q, skb);
150 | atomic_inc(&adapter.tx_pending);
151 | queue_work(adapter.tx_workqueue, &adapter.tx_work);
152 |
153 | return 0;
154 | }
155 |
156 | u8 esp_is_bt_supported_over_sdio(u32 cap)
157 | {
158 | return (cap & ESP_BT_SDIO_SUPPORT);
159 | }
160 |
161 | static struct esp_private * get_priv_from_payload_header(struct esp_payload_header *header)
162 | {
163 | struct esp_private *priv;
164 | u8 i;
165 |
166 | if (!header)
167 | return NULL;
168 |
169 | for (i = 0; i < ESP_MAX_INTERFACE; i++) {
170 | priv = adapter.priv[i];
171 |
172 | if (!priv)
173 | continue;
174 |
175 | if (priv->if_type == header->if_type &&
176 | priv->if_num == header->if_num) {
177 | return priv;
178 | }
179 | }
180 |
181 | return NULL;
182 | }
183 |
184 | void esp_process_new_packet_intr(struct esp_adapter *adapter)
185 | {
186 | if(adapter)
187 | queue_work(adapter->if_rx_workqueue, &adapter->if_rx_work);
188 | }
189 |
190 | static void process_tx_packet (void)
191 | {
192 | struct sk_buff *skb;
193 | struct esp_private *priv;
194 | struct esp_skb_cb *cb;
195 | struct esp_payload_header *payload_header;
196 | struct sk_buff *new_skb;
197 | int ret = 0;
198 | u8 pad_len = 0;
199 | u16 len = 0;
200 | static u32 c = 0;
201 |
202 | while ((skb = skb_dequeue(&adapter.tx_q))) {
203 | c++;
204 | /* Get the priv */
205 | cb = (struct esp_skb_cb *) skb->cb;
206 | priv = cb->priv;
207 |
208 | if (!priv) {
209 | dev_kfree_skb_any(skb);
210 | atomic_dec(&adapter.tx_pending);
211 | continue;
212 | }
213 |
214 | len = skb->len;
215 |
216 | /* Create space for payload header */
217 | pad_len = sizeof(struct esp_payload_header);
218 |
219 | if (skb_headroom(skb) < pad_len) {
220 | /* insufficent headroom to add payload header */
221 | new_skb = skb_realloc_headroom(skb, pad_len);
222 |
223 | if(!new_skb) {
224 | printk(KERN_ERR "%s: Failed to allocate SKB", __func__);
225 | dev_kfree_skb(skb);
226 | atomic_dec(&adapter.tx_pending);
227 | continue;
228 | }
229 |
230 | dev_kfree_skb(skb);
231 |
232 | skb = new_skb;
233 | }
234 |
235 | skb_push(skb, pad_len);
236 |
237 | /* Set payload header */
238 | payload_header = (struct esp_payload_header *) skb->data;
239 | memset(payload_header, 0, pad_len);
240 |
241 | payload_header->if_type = priv->if_type;
242 | payload_header->if_num = priv->if_num;
243 | payload_header->len = cpu_to_le16(skb->len - pad_len);
244 | payload_header->offset = cpu_to_le16(pad_len);
245 | payload_header->reserved1 = c % 255;
246 |
247 | /* printk (KERN_ERR "H -> S: %d %d %d %d", len, payload_header->offset,*/
248 | /* payload_header->len, payload_header->reserved1);*/
249 |
250 | if (!stop_data) {
251 | ret = esp_send_packet(priv->adapter, skb->data, skb->len);
252 |
253 | if (ret) {
254 | priv->stats.tx_errors++;
255 | } else {
256 | priv->stats.tx_packets++;
257 | priv->stats.tx_bytes += skb->len;
258 | }
259 | } else {
260 | priv->stats.tx_dropped++;
261 | }
262 |
263 | dev_kfree_skb_any(skb);
264 | atomic_dec(&adapter.tx_pending);
265 | }
266 | }
267 |
268 | static void process_rx_packet(struct sk_buff *skb)
269 | {
270 | struct esp_private *priv;
271 | struct esp_payload_header *payload_header;
272 | u16 len, offset;
273 | struct hci_dev *hdev = adapter.hcidev;
274 | u8 *type;
275 |
276 | if (!skb)
277 | return;
278 |
279 | /* get the paload header */
280 | payload_header = (struct esp_payload_header *) skb->data;
281 |
282 | len = le16_to_cpu(payload_header->len);
283 | offset = le16_to_cpu(payload_header->offset);
284 |
285 | if (payload_header->if_type == ESP_SERIAL_IF) {
286 | #ifdef CONFIG_SUPPORT_ESP_SERIAL
287 | esp_serial_data_received(payload_header->if_num, skb->data + offset, len);
288 | #else
289 | printk(KERN_ERR "Dropping unsupported serial frame\n");
290 | #endif
291 | dev_kfree_skb_any(skb);
292 | } else if (payload_header->if_type == ESP_STA_IF || payload_header->if_type == ESP_AP_IF) {
293 | /* chop off the header from skb */
294 | skb_pull(skb, offset);
295 |
296 | /* retrieve priv based on payload header contents */
297 | priv = get_priv_from_payload_header(payload_header);
298 |
299 | if (!priv) {
300 | printk (KERN_ERR "%s: empty priv\n", __func__);
301 | dev_kfree_skb_any(skb);
302 | /* atomic_dec(&adapter.rx_pending);*/
303 | return;
304 | }
305 |
306 | skb->dev = priv->ndev;
307 | skb->protocol = eth_type_trans(skb, priv->ndev);
308 | skb->ip_summed = CHECKSUM_NONE;
309 | /* print_hex_dump_bytes("Rx:", DUMP_PREFIX_NONE, skb->data, 8);*/
310 |
311 | /* Forward skb to kernel */
312 | netif_rx(skb);
313 |
314 | priv->stats.rx_bytes += skb->len;
315 | priv->stats.rx_packets++;
316 | } else if (payload_header->if_type == ESP_HCI_IF) {
317 | if (hdev) {
318 | /* chop off the header from skb */
319 | skb_pull(skb, offset);
320 |
321 | /* print_hex_dump_bytes("Rx:", DUMP_PREFIX_NONE, skb->data, skb->len);*/
322 | type = skb->data;
323 | hci_skb_pkt_type(skb) = *type;
324 | skb_pull(skb, 1);
325 |
326 | if (hci_recv_frame(hdev, skb)) {
327 | hdev->stat.err_rx++;
328 | } else {
329 | esp_hci_update_rx_counter(hdev, *type, skb->len);
330 | }
331 | }
332 | }
333 | }
334 |
335 | struct sk_buff * esp_alloc_skb(u32 len)
336 | {
337 | struct sk_buff *skb;
338 |
339 | skb = netdev_alloc_skb(NULL, len);
340 | return skb;
341 | }
342 |
343 |
344 | static int esp_get_packets(struct esp_adapter *adapter)
345 | {
346 | struct sk_buff *skb;
347 |
348 | if (!adapter || !adapter->if_ops || !adapter->if_ops->read)
349 | return -EINVAL;
350 |
351 | skb = adapter->if_ops->read(adapter);
352 |
353 | if (!skb)
354 | return -EFAULT;
355 |
356 | process_rx_packet(skb);
357 |
358 | return 0;
359 | }
360 |
361 | int esp_send_packet(struct esp_adapter *adapter, u8 *buf, u32 size)
362 | {
363 | if (!adapter || !adapter->if_ops || !adapter->if_ops->write)
364 | return -EINVAL;
365 |
366 | return adapter->if_ops->write(adapter, buf, size);
367 | }
368 |
369 | static int insert_priv_to_adapter(struct esp_private *priv)
370 | {
371 | int i = 0;
372 |
373 | for (i = 0; i < ESP_MAX_INTERFACE; i++) {
374 | /* Check if priv can be added */
375 | if (adapter.priv[i] == NULL) {
376 | adapter.priv[i] = priv;
377 | return 0;
378 | }
379 | }
380 |
381 | return -1;
382 | }
383 |
384 | static int esp_init_priv(struct esp_private *priv, struct net_device *dev,
385 | u8 if_type, u8 if_num)
386 | {
387 | int ret = 0;
388 |
389 | if (!priv || !dev)
390 | return -EINVAL;
391 |
392 | ret = insert_priv_to_adapter(priv);
393 | if (ret)
394 | return ret;
395 |
396 | priv->ndev = dev;
397 | priv->if_type = if_type;
398 | priv->if_num = if_num;
399 | priv->link_state = ESP_LINK_DOWN;
400 | priv->adapter = &adapter;
401 | memset(&priv->stats, 0, sizeof(priv->stats));
402 |
403 | return 0;
404 | }
405 |
406 | static int esp_init_net_dev(struct net_device *ndev, struct esp_private *priv)
407 | {
408 | int ret = 0;
409 | /* Set netdev */
410 | /* SET_NETDEV_DEV(ndev, &adapter->context.func->dev);*/
411 |
412 | /* set net dev ops */
413 | ndev->netdev_ops = &esp_netdev_ops;
414 |
415 | ether_addr_copy(ndev->dev_addr, priv->mac_address);
416 | /* set ethtool ops */
417 |
418 | /* update features supported */
419 |
420 | /* min mtu */
421 |
422 | /* register netdev */
423 | ret = register_netdev(ndev);
424 |
425 | /* netif_start_queue(ndev);*/
426 | /* ndev->needs_free_netdev = true; */
427 |
428 | /* set watchdog timeout */
429 |
430 | return ret;
431 | }
432 |
433 | static int esp_add_interface(struct esp_adapter *adapter, u8 if_type, u8 if_num, char *name)
434 | {
435 | struct net_device *ndev = NULL;
436 | struct esp_private *priv = NULL;
437 | int ret = 0;
438 |
439 | ndev = alloc_netdev_mqs(sizeof(struct esp_private), name,
440 | NET_NAME_ENUM, ether_setup, 1, 1);
441 |
442 | if (!ndev) {
443 | printk(KERN_ERR "%s: alloc failed\n", __func__);
444 | return -ENOMEM;
445 | }
446 |
447 | priv = netdev_priv(ndev);
448 |
449 | /* Init priv */
450 | ret = esp_init_priv(priv, ndev, if_type, if_num);
451 | if (ret) {
452 | printk(KERN_ERR "%s: Init priv failed\n", __func__);
453 | goto error_exit;
454 | }
455 |
456 | ret = esp_init_net_dev(ndev, priv);
457 | if (ret) {
458 | printk(KERN_ERR "%s: Init netdev failed\n", __func__);
459 | goto error_exit;
460 | }
461 |
462 | return ret;
463 |
464 | error_exit:
465 | free_netdev(ndev);
466 | return ret;
467 | }
468 |
469 | static void flush_ring_buffers(struct esp_adapter *adapter)
470 | {
471 | struct sk_buff *skb;
472 |
473 | printk (KERN_INFO "%s: Flush Pending SKBs: %d %d\n", __func__,
474 | atomic_read(&adapter->tx_pending),
475 | atomic_read(&adapter->rx_pending));
476 |
477 | while ((skb = skb_dequeue(&adapter->tx_q))) {
478 | dev_kfree_skb_any(skb);
479 | atomic_dec(&adapter->tx_pending);
480 | }
481 |
482 | while ((skb = skb_dequeue(&adapter->rx_q))) {
483 | dev_kfree_skb_any(skb);
484 | atomic_dec(&adapter->rx_pending);
485 | }
486 | }
487 |
488 | static void esp_remove_network_interfaces(struct esp_adapter *adapter)
489 | {
490 | if (adapter->priv[0] && adapter->priv[0]->ndev) {
491 | netif_stop_queue(adapter->priv[0]->ndev);
492 | unregister_netdev(adapter->priv[0]->ndev);
493 | free_netdev(adapter->priv[0]->ndev);
494 | }
495 |
496 | if (adapter->priv[1] && adapter->priv[1]->ndev) {
497 | netif_stop_queue(adapter->priv[1]->ndev);
498 | unregister_netdev(adapter->priv[1]->ndev);
499 | free_netdev(adapter->priv[1]->ndev);
500 | }
501 | }
502 |
503 | int esp_add_card(struct esp_adapter *adapter)
504 | {
505 | int ret = 0;
506 |
507 | if (!adapter) {
508 | printk(KERN_ERR "%s: Invalid args\n", __func__);
509 | return -EINVAL;
510 | }
511 |
512 | stop_data = 0;
513 |
514 | /* Add interface STA and AP */
515 | ret = esp_add_interface(adapter, ESP_STA_IF, 0, "ethsta%d");
516 | if (ret) {
517 | printk(KERN_ERR "%s: Failed to add STA\n", __func__);
518 | return ret;
519 | }
520 |
521 | ret = esp_add_interface(adapter, ESP_AP_IF, 0, "ethap%d");
522 | if (ret) {
523 | printk(KERN_ERR "%s: Failed to add AP\n", __func__);
524 | esp_remove_network_interfaces(adapter);
525 | }
526 |
527 | return ret;
528 | }
529 |
530 | int esp_remove_card(struct esp_adapter *adapter)
531 | {
532 | stop_data = 1;
533 |
534 | if (!adapter)
535 | return 0;
536 |
537 | /* Flush workqueues */
538 | if (adapter->if_rx_workqueue)
539 | flush_workqueue(adapter->if_rx_workqueue);
540 |
541 | if (adapter->tx_workqueue)
542 | flush_workqueue(adapter->tx_workqueue);
543 |
544 | esp_remove_network_interfaces(adapter);
545 |
546 | flush_ring_buffers(adapter);
547 |
548 | adapter->priv[0] = NULL;
549 | adapter->priv[1] = NULL;
550 |
551 | atomic_set(&adapter->tx_pending, 0);
552 | atomic_set(&adapter->rx_pending, 0);
553 |
554 | return 0;
555 | }
556 |
557 |
558 | static void esp_tx_work (struct work_struct *work)
559 | {
560 | process_tx_packet();
561 | }
562 |
563 | static void esp_if_rx_work (struct work_struct *work)
564 | {
565 | /* read inbound packet and forward it to network/serial interface */
566 | esp_get_packets(&adapter);
567 | }
568 |
569 | void deinit_adapter(void)
570 | {
571 | if (adapter.if_rx_workqueue)
572 | destroy_workqueue(adapter.if_rx_workqueue);
573 |
574 | if (adapter.tx_workqueue)
575 | destroy_workqueue(adapter.tx_workqueue);
576 | }
577 |
578 | struct esp_adapter * init_adapter(void)
579 | {
580 | memset(&adapter, 0, sizeof(adapter));
581 |
582 | /* Prepare interface RX work */
583 | adapter.if_rx_workqueue = create_workqueue("ESP_IF_RX_WORK_QUEUE");
584 | if (!adapter.if_rx_workqueue) {
585 | deinit_adapter();
586 | return NULL;
587 | }
588 |
589 | INIT_WORK(&adapter.if_rx_work, esp_if_rx_work);
590 |
591 | /* Prepare TX work */
592 | adapter.tx_workqueue = create_workqueue("ESP_TX_WORK_QUEUE");
593 | if (!adapter.tx_workqueue) {
594 | deinit_adapter();
595 | return NULL;
596 | }
597 |
598 | INIT_WORK(&adapter.tx_work, esp_tx_work);
599 |
600 | /* Prepare TX work */
601 | skb_queue_head_init(&adapter.tx_q);
602 | skb_queue_head_init(&adapter.rx_q);
603 |
604 | atomic_set(&adapter.tx_pending, 0);
605 | atomic_set(&adapter.rx_pending, 0);
606 |
607 | return &adapter;
608 | }
609 |
--------------------------------------------------------------------------------
/sdio/esp_sdio.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Espressif Systems Wireless LAN device driver
3 | *
4 | * Copyright (C) 2015-2020 Espressif Systems (Shanghai) PTE LTD
5 | *
6 | * This software file (the "File") is distributed by Espressif Systems (Shanghai)
7 | * PTE LTD under the terms of the GNU General Public License Version 2, June 1991
8 | * (the "License"). You may use, redistribute and/or modify this File in
9 | * accordance with the terms and conditions of the License, a copy of which
10 | * is available by writing to the Free Software Foundation, Inc.,
11 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
12 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
13 | *
14 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
15 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
16 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
17 | * this warranty disclaimer.
18 | */
19 |
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include "esp_if.h"
27 | #include "esp_sdio_api.h"
28 | #include "esp_api.h"
29 | #include "esp_bt_api.h"
30 | #ifdef CONFIG_SUPPORT_ESP_SERIAL
31 | #include "esp_serial.h"
32 | #endif
33 | #include
34 |
35 | #define CHECK_SDIO_RW_ERROR(ret) do { \
36 | if (ret) \
37 | printk(KERN_ERR "%s: CMD53 read/write error at %d\n", __func__, __LINE__); \
38 | } while (0);
39 |
40 | struct esp_sdio_context sdio_context;
41 |
42 | #ifdef CONFIG_ENABLE_MONITOR_PROCESS
43 | struct task_struct *monitor_thread;
44 | #endif
45 |
46 | static int init_context(struct esp_sdio_context *context);
47 | static struct sk_buff * read_packet(struct esp_adapter *adapter);
48 | static int write_packet(struct esp_adapter *adapter, u8 *buf, u32 size);
49 | /*int deinit_context(struct esp_adapter *adapter);*/
50 |
51 | static const struct sdio_device_id esp_devices[] = {
52 | { SDIO_DEVICE(ESP_VENDOR_ID, ESP_DEVICE_ID_1) },
53 | { SDIO_DEVICE(ESP_VENDOR_ID, ESP_DEVICE_ID_2) },
54 | {}
55 | };
56 |
57 | static void print_capabilities(u32 cap)
58 | {
59 | printk(KERN_INFO "Features supported are:\n");
60 | if (cap & ESP_WLAN_SDIO_SUPPORT)
61 | printk(KERN_INFO "\t * WLAN\n");
62 | if ((cap & ESP_BT_UART_SUPPORT) || (cap & ESP_BT_SDIO_SUPPORT)) {
63 | printk(KERN_INFO "\t * BT/BLE\n");
64 | if (cap & ESP_BT_UART_SUPPORT)
65 | printk(KERN_INFO "\t - HCI over UART\n");
66 | if (cap & ESP_BT_SDIO_SUPPORT)
67 | printk(KERN_INFO "\t - HCI over SDIO\n");
68 |
69 | if ((cap & ESP_BLE_ONLY_SUPPORT) && (cap & ESP_BR_EDR_ONLY_SUPPORT))
70 | printk(KERN_INFO "\t - BT/BLE dual mode\n");
71 | else if (cap & ESP_BLE_ONLY_SUPPORT)
72 | printk(KERN_INFO "\t - BLE only\n");
73 | else if (cap & ESP_BR_EDR_ONLY_SUPPORT)
74 | printk(KERN_INFO "\t - BR EDR only\n");
75 | }
76 | }
77 |
78 | static void esp_process_interrupt(struct esp_sdio_context *context, u32 int_status)
79 | {
80 | if (!context) {
81 | return;
82 | }
83 |
84 | if (int_status & ESP_SLAVE_RX_NEW_PACKET_INT) {
85 | esp_process_new_packet_intr(context->adapter);
86 | }
87 | }
88 |
89 | static void esp_handle_isr(struct sdio_func *func)
90 | {
91 | struct esp_sdio_context *context = NULL;
92 | u32 int_status = 0;
93 | int ret;
94 |
95 | if (!func) {
96 | return;
97 | }
98 |
99 | context = sdio_get_drvdata(func);
100 |
101 | if (!context) {
102 | return;
103 | }
104 |
105 | /* Read interrupt status register */
106 | ret = esp_read_reg(context, ESP_SLAVE_INT_ST_REG,
107 | (u8 *) &int_status, sizeof(int_status), ACQUIRE_LOCK);
108 | CHECK_SDIO_RW_ERROR(ret);
109 |
110 | esp_process_interrupt(context, int_status);
111 |
112 | /* Clear interrupt status */
113 | ret = esp_write_reg(context, ESP_SLAVE_INT_CLR_REG,
114 | (u8 *) &int_status, sizeof(int_status), ACQUIRE_LOCK);
115 | CHECK_SDIO_RW_ERROR(ret);
116 | }
117 |
118 | int generate_slave_intr(struct esp_sdio_context *context, u8 data)
119 | {
120 | if (!context)
121 | return -EINVAL;
122 |
123 | return esp_write_reg(context, ESP_SLAVE_SCRATCH_REG_7, &data,
124 | sizeof(data), ACQUIRE_LOCK);
125 | }
126 |
127 | static void deinit_sdio_func(struct sdio_func *func)
128 | {
129 | sdio_claim_host(func);
130 | /* Release IRQ */
131 | sdio_release_irq(func);
132 | /* Disable sdio function */
133 | sdio_disable_func(func);
134 | sdio_release_host(func);
135 | sdio_set_drvdata(func, NULL);
136 | }
137 |
138 | static int esp_slave_get_tx_buffer_num(struct esp_sdio_context *context, u32 *tx_num, u8 is_lock_needed)
139 | {
140 | u32 len;
141 | int ret = 0;
142 |
143 | ret = esp_read_reg(context, ESP_SLAVE_TOKEN_RDATA, (uint8_t*)&len, 4, is_lock_needed);
144 |
145 | if (ret)
146 | return ret;
147 |
148 | len = (len >> 16) & ESP_TX_BUFFER_MASK;
149 | len = (len + ESP_TX_BUFFER_MAX - context->tx_buffer_count) % ESP_TX_BUFFER_MAX;
150 |
151 | *tx_num = len;
152 |
153 | return ret;
154 | }
155 |
156 | static int esp_get_len_from_slave(struct esp_sdio_context *context, u32 *rx_size, u8 is_lock_needed)
157 | {
158 | u32 len, temp;
159 | int ret = 0;
160 |
161 | ret = esp_read_reg(context, ESP_SLAVE_PACKET_LEN_REG,
162 | (u8 *) &len, sizeof(len), is_lock_needed);
163 |
164 | if (ret)
165 | return ret;
166 |
167 | len &= ESP_SLAVE_LEN_MASK;
168 |
169 | if (len >= context->rx_byte_count)
170 | len = (len + ESP_RX_BYTE_MAX - context->rx_byte_count) % ESP_RX_BYTE_MAX;
171 | else {
172 | /* Handle a case of roll over */
173 | temp = ESP_RX_BYTE_MAX - context->rx_byte_count;
174 | len = temp + len;
175 |
176 | if (len > ESP_RX_BUFFER_SIZE) {
177 | printk(KERN_INFO "%s: Len from slave[%d] exceeds max [%d]\n",
178 | __func__, len, ESP_RX_BUFFER_SIZE);
179 | }
180 | }
181 | *rx_size = len;
182 |
183 | return 0;
184 | }
185 |
186 |
187 | static void flush_sdio(struct esp_sdio_context *context)
188 | {
189 | struct sk_buff *skb;
190 |
191 | if (!context || !context->adapter)
192 | return;
193 |
194 | while (1) {
195 | skb = read_packet(context->adapter);
196 |
197 | if (!skb) {
198 | break;
199 | }
200 |
201 | if (skb->len)
202 | printk (KERN_INFO "%s: Flushed %d bytes\n", __func__, skb->len);
203 | dev_kfree_skb(skb);
204 | }
205 | }
206 |
207 | static void esp_remove(struct sdio_func *func)
208 | {
209 | struct esp_sdio_context *context;
210 | context = sdio_get_drvdata(func);
211 |
212 | printk(KERN_INFO "%s -> Remove card", __func__);
213 |
214 | #ifdef CONFIG_SUPPORT_ESP_SERIAL
215 | esp_serial_cleanup();
216 | #endif
217 |
218 | #ifdef CONFIG_ENABLE_MONITOR_PROCESS
219 | if (monitor_thread)
220 | kthread_stop(monitor_thread);
221 | #endif
222 |
223 | if (context) {
224 | generate_slave_intr(context, BIT(ESP_CLOSE_DATA_PATH));
225 | msleep(100);
226 |
227 | flush_sdio(context);
228 |
229 | if (context->adapter) {
230 | esp_remove_card(context->adapter);
231 |
232 | if (context->adapter->hcidev) {
233 | esp_deinit_bt(context->adapter);
234 | }
235 |
236 | }
237 |
238 | memset(context, 0, sizeof(struct esp_sdio_context));
239 | }
240 |
241 | deinit_sdio_func(func);
242 |
243 | printk (KERN_INFO "%s: Context deinit %d - %d\n", __func__, context->rx_byte_count,
244 | context->tx_buffer_count);
245 |
246 | }
247 |
248 | static struct esp_if_ops if_ops = {
249 | .read = read_packet,
250 | .write = write_packet,
251 | };
252 |
253 | static int init_context(struct esp_sdio_context *context)
254 | {
255 | int ret = 0;
256 | u32 val = 0;
257 |
258 | if (!context) {
259 | return -EINVAL;
260 | }
261 |
262 | /* Initialize rx_byte_count */
263 | ret = esp_read_reg(context, ESP_SLAVE_PACKET_LEN_REG,
264 | (u8 *) &val, sizeof(val), ACQUIRE_LOCK);
265 | if (ret)
266 | return ret;
267 |
268 | /* printk(KERN_DEBUG "%s: LEN %d\n", __func__, (val & ESP_SLAVE_LEN_MASK));*/
269 |
270 | context->rx_byte_count = val & ESP_SLAVE_LEN_MASK;
271 |
272 | /* Initialize tx_buffer_count */
273 | ret = esp_read_reg(context, ESP_SLAVE_TOKEN_RDATA, (u8 *) &val,
274 | sizeof(val), ACQUIRE_LOCK);
275 |
276 | if (ret)
277 | return ret;
278 |
279 | val = ((val >> 16) & ESP_TX_BUFFER_MASK);
280 |
281 | /* printk(KERN_DEBUG "%s: BUF_CNT %d\n", __func__, val);*/
282 |
283 | if (val >= ESP_MAX_BUF_CNT)
284 | context->tx_buffer_count = val - ESP_MAX_BUF_CNT;
285 | else
286 | context->tx_buffer_count = 0;
287 |
288 | /* printk(KERN_DEBUG "%s: Context init %d - %d\n", __func__, context->rx_byte_count,*/
289 | /* context->tx_buffer_count);*/
290 |
291 | context->adapter = esp_get_adapter();
292 |
293 | if (!context->adapter)
294 | printk (KERN_ERR "%s: Failed to get adapter\n", __func__);
295 |
296 | context->adapter->if_type = ESP_IF_TYPE_SDIO;
297 |
298 | return ret;
299 | }
300 |
301 | static struct sk_buff * read_packet(struct esp_adapter *adapter)
302 | {
303 | u32 len_from_slave, data_left, len_to_read, size, num_blocks;
304 | int ret = 0;
305 | struct sk_buff *skb;
306 | u8 *pos;
307 | struct esp_sdio_context *context;
308 |
309 | if (!adapter || !adapter->if_context) {
310 | printk (KERN_ERR "%s: INVALID args\n", __func__);
311 | return NULL;
312 | }
313 |
314 | context = adapter->if_context;
315 |
316 | sdio_claim_host(context->func);
317 |
318 | data_left = len_to_read = len_from_slave = num_blocks = 0;
319 |
320 | /* Read length */
321 | ret = esp_get_len_from_slave(context, &len_from_slave, LOCK_ALREADY_ACQUIRED);
322 |
323 | /* printk (KERN_DEBUG "LEN FROM SLAVE: %d\n", len_from_slave);*/
324 |
325 | if (ret || !len_from_slave) {
326 | sdio_release_host(context->func);
327 | return NULL;
328 | }
329 |
330 | size = ESP_BLOCK_SIZE * 4;
331 |
332 | if (len_from_slave > size) {
333 | printk(KERN_INFO "Rx large packet: %d\n", len_from_slave);
334 | }
335 |
336 | skb = esp_alloc_skb(len_from_slave);
337 |
338 | if (!skb) {
339 | printk (KERN_ERR "%s: SKB alloc failed\n", __func__);
340 | sdio_release_host(context->func);
341 | return NULL;
342 | }
343 |
344 | skb_put(skb, len_from_slave);
345 | pos = skb->data;
346 |
347 | data_left = len_from_slave;
348 |
349 | do {
350 | num_blocks = data_left/ESP_BLOCK_SIZE;
351 |
352 | #if 0
353 | if (!context->rx_byte_count) {
354 | start_time = ktime_get_ns();
355 | }
356 | #endif
357 |
358 | if (num_blocks) {
359 | len_to_read = num_blocks * ESP_BLOCK_SIZE;
360 | ret = esp_read_block(context,
361 | ESP_SLAVE_CMD53_END_ADDR - len_to_read,
362 | pos, len_to_read, LOCK_ALREADY_ACQUIRED);
363 | } else {
364 | len_to_read = data_left;
365 | /* 4 byte aligned length */
366 | ret = esp_read_block(context,
367 | ESP_SLAVE_CMD53_END_ADDR - len_to_read,
368 | pos, (len_to_read + 3) & (~3), LOCK_ALREADY_ACQUIRED);
369 | }
370 |
371 | if (ret) {
372 | printk (KERN_ERR "%s: Failed to read data\n", __func__);
373 | dev_kfree_skb(skb);
374 | sdio_release_host(context->func);
375 | return NULL;
376 | }
377 |
378 | data_left -= len_to_read;
379 | pos += len_to_read;
380 | context->rx_byte_count += len_to_read;
381 | context->rx_byte_count = context->rx_byte_count % ESP_RX_BYTE_MAX;
382 |
383 | } while (data_left > 0);
384 |
385 | sdio_release_host(context->func);
386 |
387 | return skb;
388 | }
389 |
390 | static int write_packet(struct esp_adapter *adapter, u8 *buf, u32 size)
391 | {
392 | u32 block_cnt = 0, buf_needed = 0;
393 | u32 buf_available = 0;
394 | int ret = 0;
395 | u8 *pos = NULL;
396 | u32 data_left, len_to_send, pad;
397 | struct esp_sdio_context *context;
398 |
399 | if (!adapter || !adapter->if_context || !buf || !size) {
400 | printk (KERN_ERR "%s: Invalid args\n", __func__);
401 | return -EINVAL;
402 | }
403 |
404 | context = adapter->if_context;
405 |
406 | sdio_claim_host(context->func);
407 |
408 | buf_needed = (size + ESP_RX_BUFFER_SIZE - 1) / ESP_RX_BUFFER_SIZE;
409 |
410 | ret = esp_slave_get_tx_buffer_num(context, &buf_available, LOCK_ALREADY_ACQUIRED);
411 |
412 | /* printk(KERN_ERR "%s: TX -> Available [%d], needed [%d]\n", __func__, buf_available, buf_needed);*/
413 |
414 | if (buf_available < buf_needed) {
415 | printk(KERN_DEBUG "%s: Not enough buffers available: availabale [%d], needed [%d]\n", __func__,
416 | buf_available, buf_needed);
417 | sdio_release_host(context->func);
418 | return -ENOMEM;
419 | }
420 |
421 | pos = buf;
422 | data_left = len_to_send = 0;
423 |
424 | data_left = size;
425 | pad = ESP_BLOCK_SIZE - (data_left % ESP_BLOCK_SIZE);
426 | data_left += pad;
427 |
428 |
429 | do {
430 | block_cnt = data_left / ESP_BLOCK_SIZE;
431 | len_to_send = data_left;
432 | ret = esp_write_block(context, ESP_SLAVE_CMD53_END_ADDR - len_to_send,
433 | pos, (len_to_send + 3) & (~3), LOCK_ALREADY_ACQUIRED);
434 |
435 | if (ret) {
436 | printk (KERN_ERR "%s: Failed to send data\n", __func__);
437 | sdio_release_host(context->func);
438 | return ret;
439 | }
440 | /* printk (KERN_ERR "--> %d %d %d\n", block_cnt, data_left, len_to_send);*/
441 |
442 | data_left -= len_to_send;
443 | pos += len_to_send;
444 | } while (data_left);
445 |
446 | context->tx_buffer_count += buf_needed;
447 | context->tx_buffer_count = context->tx_buffer_count % ESP_TX_BUFFER_MAX;
448 |
449 | sdio_release_host(context->func);
450 |
451 | return 0;
452 | }
453 |
454 | static struct esp_sdio_context * init_sdio_func(struct sdio_func *func)
455 | {
456 | struct esp_sdio_context *context = NULL;
457 | int ret = 0;
458 |
459 | if (!func)
460 | return NULL;
461 |
462 | context = &sdio_context;
463 |
464 | context->func = func;
465 |
466 | sdio_claim_host(func);
467 |
468 | /* Enable Function */
469 | ret = sdio_enable_func(func);
470 | if (ret) {
471 | return NULL;
472 | }
473 |
474 | /* Register IRQ */
475 | ret = sdio_claim_irq(func, esp_handle_isr);
476 | if (ret) {
477 | sdio_disable_func(func);
478 | return NULL;
479 | }
480 |
481 | /* Set private data */
482 | sdio_set_drvdata(func, context);
483 |
484 | context->state = ESP_CONTEXT_INIT;
485 |
486 | sdio_release_host(func);
487 |
488 | return context;
489 | }
490 |
491 | #ifdef CONFIG_ENABLE_MONITOR_PROCESS
492 | static int monitor_process(void *data)
493 | {
494 | u32 val, intr, len_reg, rdata, old_len = 0;
495 | struct esp_sdio_context *context = (struct esp_sdio_context *) data;
496 | struct sk_buff *skb;
497 |
498 | while (!kthread_should_stop()) {
499 | msleep(5000);
500 |
501 | val = intr = len_reg = rdata = 0;
502 |
503 | esp_read_reg(context, ESP_SLAVE_PACKET_LEN_REG,
504 | (u8 *) &val, sizeof(val), ACQUIRE_LOCK);
505 |
506 | len_reg = val & ESP_SLAVE_LEN_MASK;
507 |
508 | val = 0;
509 | esp_read_reg(context, ESP_SLAVE_TOKEN_RDATA, (u8 *) &val,
510 | sizeof(val), ACQUIRE_LOCK);
511 |
512 | rdata = ((val >> 16) & ESP_TX_BUFFER_MASK);
513 |
514 | esp_read_reg(context, ESP_SLAVE_INT_ST_REG,
515 | (u8 *) &intr, sizeof(intr), ACQUIRE_LOCK);
516 |
517 |
518 | if (len_reg > context->rx_byte_count) {
519 | if (old_len && (context->rx_byte_count == old_len)) {
520 | printk (KERN_DEBUG "Monitor thread ----> [%d - %d] [%d - %d] %d\n",
521 | len_reg, context->rx_byte_count,
522 | rdata, context->tx_buffer_count, intr);
523 |
524 | skb = read_packet(context->adapter);
525 |
526 | if (!skb)
527 | continue;
528 |
529 | if (skb->len)
530 | printk (KERN_DEBUG "%s: Flushed %d bytes\n", __func__, skb->len);
531 |
532 | /* drop the packet */
533 | dev_kfree_skb(skb);
534 | }
535 | }
536 |
537 | old_len = context->rx_byte_count;
538 | }
539 |
540 | do_exit(0);
541 | return 0;
542 | }
543 | #endif
544 |
545 | static int esp_probe(struct sdio_func *func,
546 | const struct sdio_device_id *id)
547 | {
548 | struct esp_sdio_context *context = NULL;
549 | int ret = 0;
550 | uint32_t cap = 0;
551 |
552 | if (func->num != 1) {
553 | return -EINVAL;
554 | }
555 |
556 | printk(KERN_INFO "%s: ESP network device detected\n", __func__);
557 |
558 | context = init_sdio_func(func);
559 |
560 | if (!context) {
561 | return -ENOMEM;
562 | }
563 |
564 | generate_slave_intr(context, BIT(ESP_RESET));
565 |
566 | msleep(200);
567 |
568 | ret = init_context(context);
569 | if (ret) {
570 | deinit_sdio_func(func);
571 | return ret;
572 | }
573 |
574 | #ifdef CONFIG_SUPPORT_ESP_SERIAL
575 | ret = esp_serial_init((void *) context->adapter);
576 | if (ret != 0) {
577 | esp_remove(func);
578 | printk(KERN_ERR "Error initialising serial interface\n");
579 | return ret;
580 | }
581 | #endif
582 |
583 | ret = esp_add_card(context->adapter);
584 | if (ret) {
585 | esp_remove(func);
586 | printk (KERN_ERR "Failed to add card\n");
587 | deinit_sdio_func(func);
588 | return ret;
589 | }
590 |
591 | /* Read slave capabilities */
592 | esp_read_reg(context, ESP_SLAVE_SCRATCH_REG_0,
593 | (u8 *) &cap, sizeof(cap), ACQUIRE_LOCK);
594 |
595 | context->adapter->capabilities = cap;
596 |
597 | print_capabilities(cap);
598 |
599 | if (esp_is_bt_supported_over_sdio(cap)) {
600 | ret = esp_init_bt(context->adapter);
601 | if (ret) {
602 | esp_remove(func);
603 | printk (KERN_ERR "Failed to init BT\n");
604 | deinit_sdio_func(func);
605 | return ret;
606 | }
607 | }
608 |
609 | context->state = ESP_CONTEXT_READY;
610 |
611 | #ifdef CONFIG_ENABLE_MONITOR_PROCESS
612 | monitor_thread = kthread_run(monitor_process, context, "Monitor process");
613 |
614 | if (!monitor_thread)
615 | printk (KERN_ERR "Failed to create monitor thread\n");
616 | #endif
617 |
618 |
619 | msleep(200);
620 | generate_slave_intr(context, BIT(ESP_OPEN_DATA_PATH));
621 | return ret;
622 | }
623 |
624 | /* SDIO driver structure to be registered with kernel */
625 | static struct sdio_driver esp_sdio_driver = {
626 | .name = "esp_sdio",
627 | .id_table = esp_devices,
628 | .probe = esp_probe,
629 | .remove = esp_remove,
630 | };
631 |
632 | int esp_init_interface_layer(struct esp_adapter *adapter)
633 | {
634 | if (!adapter)
635 | return -EINVAL;
636 |
637 | adapter->if_context = &sdio_context;
638 | adapter->if_ops = &if_ops;
639 | sdio_context.adapter = adapter;
640 |
641 | return sdio_register_driver(&esp_sdio_driver);
642 | }
643 |
644 | void esp_deinit_interface_layer(void)
645 | {
646 | sdio_unregister_driver(&esp_sdio_driver);
647 | }
648 |
--------------------------------------------------------------------------------
/sdio/esp_sdio_api.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Espressif Systems Wireless LAN device driver
3 | *
4 | * Copyright (C) 2015-2020 Espressif Systems (Shanghai) PTE LTD
5 | *
6 | * This software file (the "File") is distributed by Espressif Systems (Shanghai)
7 | * PTE LTD under the terms of the GNU General Public License Version 2, June 1991
8 | * (the "License"). You may use, redistribute and/or modify this File in
9 | * accordance with the terms and conditions of the License, a copy of which
10 | * is available by writing to the Free Software Foundation, Inc.,
11 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
12 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
13 | *
14 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
15 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
16 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
17 | * this warranty disclaimer.
18 | */
19 |
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include "esp_sdio_api.h"
26 |
27 | static int esp_read_byte(struct esp_sdio_context *context, u32 reg, u8 *data, u8 is_lock_needed)
28 | {
29 | struct sdio_func *func = NULL;
30 | int ret;
31 |
32 | if (!context || !context->func || !data) {
33 | printk (KERN_ERR "%s: Invalid or incomplete arguments!\n", __func__);
34 | return -1;
35 | }
36 |
37 | func = context->func;
38 |
39 | if (is_lock_needed)
40 | sdio_claim_host(func);
41 |
42 | *data = sdio_readb(func, reg, &ret);
43 |
44 | if (is_lock_needed)
45 | sdio_release_host(func);
46 |
47 | return ret;
48 | }
49 |
50 | static int esp_write_byte(struct esp_sdio_context *context, u32 reg, u8 data, u8 is_lock_needed)
51 | {
52 | struct sdio_func *func = NULL;
53 | int ret;
54 |
55 | if (!context || !context->func) {
56 | printk (KERN_ERR "%s: Invalid or incomplete arguments!\n", __func__);
57 | return -1;
58 | }
59 |
60 | func = context->func;
61 |
62 | if (is_lock_needed)
63 | sdio_claim_host(func);
64 |
65 | sdio_writeb(func, data, reg, &ret);
66 |
67 | if (is_lock_needed)
68 | sdio_release_host(func);
69 |
70 | return ret;
71 | }
72 |
73 | static int esp_read_multi_byte(struct esp_sdio_context *context, u32 reg, u8 *data, u16 size, u8 is_lock_needed)
74 | {
75 | struct sdio_func *func = NULL;
76 | int ret;
77 |
78 | if (!context || !context->func || !data) {
79 | printk (KERN_ERR "%s: Invalid or incomplete arguments!\n", __func__);
80 | return -1;
81 | }
82 |
83 | func = context->func;
84 |
85 | if (is_lock_needed)
86 | sdio_claim_host(func);
87 |
88 | ret = sdio_memcpy_fromio(func, data, reg, size);
89 |
90 | if (is_lock_needed)
91 | sdio_release_host(func);
92 |
93 | return ret;
94 | }
95 |
96 | static int esp_write_multi_byte(struct esp_sdio_context *context, u32 reg, u8 *data, u16 size, u8 is_lock_needed)
97 | {
98 | struct sdio_func *func = NULL;
99 | int ret;
100 |
101 | if (!context || !context->func || !data) {
102 | printk (KERN_ERR "%s: Invalid or incomplete arguments!\n", __func__);
103 | return -1;
104 | }
105 |
106 | func = context->func;
107 |
108 | if (is_lock_needed)
109 | sdio_claim_host(func);
110 |
111 | ret = sdio_memcpy_toio(func, reg, data, size);
112 |
113 | if (is_lock_needed)
114 | sdio_release_host(func);
115 |
116 | return ret;
117 | }
118 |
119 | int esp_read_reg(struct esp_sdio_context *context, u32 reg, u8 *data, u16 size, u8 is_lock_needed)
120 | {
121 | /* Need to apply address mask when reading/writing slave registers */
122 | reg &= ESP_ADDRESS_MASK;
123 |
124 | if (size <= 1) {
125 | return esp_read_byte(context, reg, data, is_lock_needed);
126 | } else {
127 | return esp_read_multi_byte(context, reg, data, size, is_lock_needed);
128 | }
129 | }
130 |
131 | int esp_read_block(struct esp_sdio_context *context, u32 reg, u8 *data, u16 size, u8 is_lock_needed)
132 | {
133 | if (size <= 1) {
134 | return esp_read_byte(context, reg, data, is_lock_needed);
135 | } else {
136 | return esp_read_multi_byte(context, reg, data, size, is_lock_needed);
137 | }
138 | }
139 |
140 | int esp_write_reg(struct esp_sdio_context *context, u32 reg, u8 *data, u16 size, u8 is_lock_needed)
141 | {
142 | /* Need to apply address mask when reading/writing slave registers */
143 | reg &= ESP_ADDRESS_MASK;
144 |
145 | if (size <= 1) {
146 | return esp_write_byte(context, reg, *data, is_lock_needed);
147 | } else {
148 | return esp_write_multi_byte(context, reg, data, size, is_lock_needed);
149 | }
150 | }
151 |
152 | int esp_write_block(struct esp_sdio_context *context, u32 reg, u8 *data, u16 size, u8 is_lock_needed)
153 | {
154 | if (size <= 1) {
155 | return esp_write_byte(context, reg, *data, is_lock_needed);
156 | } else {
157 | return esp_write_multi_byte(context, reg, data, size, is_lock_needed);
158 | }
159 | }
160 |
161 |
--------------------------------------------------------------------------------
/sdio/esp_sdio_api.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Espressif Systems Wireless LAN device driver
3 | *
4 | * Copyright (C) 2015-2020 Espressif Systems (Shanghai) PTE LTD
5 | *
6 | * This software file (the "File") is distributed by Espressif Systems (Shanghai)
7 | * PTE LTD under the terms of the GNU General Public License Version 2, June 1991
8 | * (the "License"). You may use, redistribute and/or modify this File in
9 | * accordance with the terms and conditions of the License, a copy of which
10 | * is available by writing to the Free Software Foundation, Inc.,
11 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
12 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
13 | *
14 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
15 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
16 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
17 | * this warranty disclaimer.
18 | */
19 |
20 | #ifndef _ESP_SDIO_API_H_
21 | #define _ESP_SDIO_API_H_
22 | #include "esp_sdio_decl.h"
23 |
24 | int esp_read_reg(struct esp_sdio_context *context, u32 reg, u8 *data, u16 size, u8 is_lock_needed);
25 | int esp_read_block(struct esp_sdio_context *context, u32 reg, u8 *data, u16 size, u8 is_lock_needed);
26 | int esp_write_reg(struct esp_sdio_context *context, u32 reg, u8 *data, u16 size, u8 is_lock_needed);
27 | int esp_write_block(struct esp_sdio_context *context, u32 reg, u8 *data, u16 size, u8 is_lock_needed);
28 |
29 | #endif
30 |
--------------------------------------------------------------------------------
/sdio/esp_sdio_decl.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Espressif Systems Wireless LAN device driver
3 | *
4 | * Copyright (C) 2015-2020 Espressif Systems (Shanghai) PTE LTD
5 | *
6 | * This software file (the "File") is distributed by Espressif Systems (Shanghai)
7 | * PTE LTD under the terms of the GNU General Public License Version 2, June 1991
8 | * (the "License"). You may use, redistribute and/or modify this File in
9 | * accordance with the terms and conditions of the License, a copy of which
10 | * is available by writing to the Free Software Foundation, Inc.,
11 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
12 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
13 | *
14 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
15 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
16 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
17 | * this warranty disclaimer.
18 | */
19 |
20 | #ifndef _ESP_DECL_H_
21 | #define _ESP_DECL_H_
22 |
23 | #include "esp.h"
24 |
25 | /* Interrupt Status */
26 | #define ESP_SLAVE_BIT0_INT BIT(0)
27 | #define ESP_SLAVE_BIT1_INT BIT(1)
28 | #define ESP_SLAVE_BIT2_INT BIT(2)
29 | #define ESP_SLAVE_BIT3_INT BIT(3)
30 | #define ESP_SLAVE_BIT4_INT BIT(4)
31 | #define ESP_SLAVE_BIT5_INT BIT(5)
32 | #define ESP_SLAVE_BIT6_INT BIT(6)
33 | #define ESP_SLAVE_BIT7_INT BIT(7)
34 | #define ESP_SLAVE_RX_UNDERFLOW_INT BIT(16)
35 | #define ESP_SLAVE_TX_OVERFLOW_INT BIT(17)
36 | #define ESP_SLAVE_RX_NEW_PACKET_INT BIT(23)
37 |
38 |
39 | #define ESP_SLAVE_CMD53_END_ADDR 0x1F800
40 | #define ESP_SLAVE_LEN_MASK 0xFFFFF
41 | #define ESP_BLOCK_SIZE 512
42 | #define ESP_RX_BYTE_MAX 0x100000
43 | #define ESP_RX_BUFFER_SIZE 2048
44 |
45 | #define ESP_TX_BUFFER_MASK 0xFFF
46 | #define ESP_TX_BUFFER_MAX 0x1000
47 | #define ESP_MAX_BUF_CNT 10
48 |
49 | #define ESP_SLAVE_SLCHOST_BASE 0x3FF55000
50 |
51 | #define ESP_SLAVE_SCRATCH_REG_7 (ESP_SLAVE_SLCHOST_BASE + 0x8C)
52 | /* SLAVE registers */
53 | /* Interrupt Registers */
54 | #define ESP_SLAVE_INT_RAW_REG (ESP_SLAVE_SLCHOST_BASE + 0x50)
55 | #define ESP_SLAVE_INT_ST_REG (ESP_SLAVE_SLCHOST_BASE + 0x58)
56 | #define ESP_SLAVE_INT_CLR_REG (ESP_SLAVE_SLCHOST_BASE + 0xD4)
57 |
58 | /* Data path registers*/
59 | #define ESP_SLAVE_PACKET_LEN_REG (ESP_SLAVE_SLCHOST_BASE + 0x60)
60 | #define ESP_SLAVE_TOKEN_RDATA (ESP_SLAVE_SLCHOST_BASE + 0x44)
61 |
62 | /* Scratch registers*/
63 | #define ESP_SLAVE_SCRATCH_REG_0 (ESP_SLAVE_SLCHOST_BASE + 0x6C)
64 | #define ESP_SLAVE_SCRATCH_REG_1 (ESP_SLAVE_SLCHOST_BASE + 0x70)
65 | #define ESP_SLAVE_SCRATCH_REG_2 (ESP_SLAVE_SLCHOST_BASE + 0x74)
66 | #define ESP_SLAVE_SCRATCH_REG_3 (ESP_SLAVE_SLCHOST_BASE + 0x78)
67 | #define ESP_SLAVE_SCRATCH_REG_4 (ESP_SLAVE_SLCHOST_BASE + 0x7C)
68 | #define ESP_SLAVE_SCRATCH_REG_6 (ESP_SLAVE_SLCHOST_BASE + 0x88)
69 | #define ESP_SLAVE_SCRATCH_REG_8 (ESP_SLAVE_SLCHOST_BASE + 0x9C)
70 | #define ESP_SLAVE_SCRATCH_REG_9 (ESP_SLAVE_SLCHOST_BASE + 0xA0)
71 | #define ESP_SLAVE_SCRATCH_REG_10 (ESP_SLAVE_SLCHOST_BASE + 0xA4)
72 | #define ESP_SLAVE_SCRATCH_REG_11 (ESP_SLAVE_SLCHOST_BASE + 0xA8)
73 | #define ESP_SLAVE_SCRATCH_REG_12 (ESP_SLAVE_SLCHOST_BASE + 0xAC)
74 | #define ESP_SLAVE_SCRATCH_REG_13 (ESP_SLAVE_SLCHOST_BASE + 0xB0)
75 | #define ESP_SLAVE_SCRATCH_REG_14 (ESP_SLAVE_SLCHOST_BASE + 0xB4)
76 | #define ESP_SLAVE_SCRATCH_REG_15 (ESP_SLAVE_SLCHOST_BASE + 0xB8)
77 |
78 | #define ESP_ADDRESS_MASK 0x3FF
79 |
80 | #define ESP_VENDOR_ID 0x6666
81 | #define ESP_DEVICE_ID_1 0x2222
82 | #define ESP_DEVICE_ID_2 0x3333
83 |
84 |
85 | enum context_state {
86 | ESP_CONTEXT_DISABLED = 0,
87 | ESP_CONTEXT_INIT,
88 | ESP_CONTEXT_READY
89 | };
90 |
91 | struct esp_sdio_context {
92 | struct esp_adapter *adapter;
93 | struct sdio_func *func;
94 | enum context_state state;
95 | u32 rx_byte_count;
96 | u32 tx_buffer_count;
97 | };
98 |
99 | #endif
100 |
--------------------------------------------------------------------------------
/spi/esp_spi.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015-2020 Espressif Systems (Shanghai) PTE LTD
3 | *
4 | * This software file (the "File") is distributed by Espressif Systems (Shanghai)
5 | * PTE LTD under the terms of the GNU General Public License Version 2, June 1991
6 | * (the "License"). You may use, redistribute and/or modify this File in
7 | * accordance with the terms and conditions of the License, a copy of which
8 | * is available by writing to the Free Software Foundation, Inc.,
9 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
10 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
11 | *
12 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
13 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
14 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
15 | * this warranty disclaimer.
16 | */
17 | #include
18 | #include
19 | #include
20 | #include "esp_spi.h"
21 | #include "esp_if.h"
22 | #include "esp_api.h"
23 | #include "esp_bt_api.h"
24 | #ifdef CONFIG_SUPPORT_ESP_SERIAL
25 | #include "esp_serial.h"
26 | #endif
27 |
28 | static struct sk_buff * read_packet(struct esp_adapter *adapter);
29 | static int write_packet(struct esp_adapter *adapter, u8 *buf, u32 size);
30 | static void spi_exit(struct esp_spi_context *esp);
31 |
32 | volatile u8 data_path = 0;
33 |
34 | static struct esp_if_ops if_ops = {
35 | .read = read_packet,
36 | .write = write_packet,
37 | };
38 |
39 |
40 | static void open_data_path(void)
41 | {
42 | msleep(200);
43 | data_path = OPEN_DATAPATH;
44 | }
45 |
46 | static void close_data_path(void)
47 | {
48 | data_path = CLOSE_DATAPATH;
49 | msleep(200);
50 | }
51 |
52 | static irqreturn_t spi_interrupt_handler(int irq, void * priv)
53 | {
54 | struct esp_spi_context *esp = (struct esp_spi_context *)priv;
55 |
56 | /* ESP32 is ready for next transaction */
57 | if (esp->spi_workqueue)
58 | queue_work(esp->spi_workqueue, &esp->spi_work);
59 |
60 | return IRQ_HANDLED;
61 | }
62 |
63 | static struct sk_buff * read_packet(struct esp_adapter *adapter)
64 | {
65 | struct esp_spi_context *esp;
66 | struct sk_buff *skb = NULL;
67 |
68 | if (!data_path) {
69 | return NULL;
70 | }
71 |
72 | if (!adapter || !adapter->if_context) {
73 | printk (KERN_ERR "%s: Invalid args\n", __func__);
74 | return NULL;
75 | }
76 |
77 | esp = adapter->if_context;
78 |
79 | if (esp->esp_spi_dev) {
80 | skb = skb_dequeue(&(esp->rx_q));
81 | } else {
82 | printk (KERN_ERR "%s: Invalid args\n", __func__);
83 | return NULL;
84 | }
85 |
86 | return skb;
87 | }
88 |
89 | static int write_packet(struct esp_adapter *adapter, u8 *buf, u32 size)
90 | {
91 | struct esp_spi_context *esp;
92 | struct sk_buff *skb;
93 | u8 *tx_buf = NULL;
94 |
95 | if (!adapter || !adapter->if_context || !buf || !size || (size > SPI_BUF_SIZE)) {
96 | printk (KERN_ERR "%s: Invalid args\n", __func__);
97 | return -EINVAL;
98 | }
99 |
100 | if (!data_path) {
101 | return -EPERM;
102 | }
103 |
104 | /* Adjust length to make it multiple of 4 bytes */
105 | size += 4 - (size & 3);
106 |
107 | esp = adapter->if_context;
108 |
109 | skb = esp_alloc_skb(size);
110 |
111 | if (!skb)
112 | return -ENOMEM;
113 |
114 | tx_buf = skb_put(skb, size);
115 |
116 | if (!tx_buf) {
117 | dev_kfree_skb(skb);
118 | return -ENOMEM;
119 | }
120 |
121 | /* TODO: This memecpy can be avoided if this function receives SKB as an argument */
122 | memcpy(tx_buf, buf, size);
123 |
124 | /* Enqueue SKB in tx_q */
125 | skb_queue_tail(&esp->tx_q, skb);
126 |
127 | return 0;
128 | }
129 |
130 | static void process_capabilities(struct esp_spi_context *esp, u8 cap)
131 | {
132 | printk (KERN_INFO "ESP32 capabilities: 0x%x", cap);
133 |
134 | /* Reset BT */
135 | esp_deinit_bt(esp->adapter);
136 |
137 | if ((cap & ESP_BT_SPI_SUPPORT) || (cap & ESP_BT_SDIO_SUPPORT)) {
138 | msleep(200);
139 | esp_init_bt(esp->adapter);
140 | }
141 | }
142 |
143 | static void process_init_event(struct esp_spi_context *esp, u8 *evt_buf, u8 len)
144 | {
145 | u8 len_left = len, tag_len;
146 | u8 *pos;
147 |
148 | if (!evt_buf)
149 | return;
150 |
151 | pos = evt_buf;
152 |
153 | while (len_left) {
154 | tag_len = *(pos + 1);
155 | if (*pos == ESP_PRIV_CAPABILITY) {
156 | process_capabilities(esp, *(pos + 2));
157 | } else {
158 | printk (KERN_WARNING "Unsupported tag in event");
159 | }
160 | len_left = len_left - (tag_len + 2);
161 | }
162 | }
163 |
164 | static void process_event(struct esp_spi_context *esp, u8 *evt_buf, u16 len)
165 | {
166 | struct esp_priv_event *event;
167 |
168 | if (!evt_buf || !len)
169 | return;
170 |
171 | event = (struct esp_priv_event *) evt_buf;
172 |
173 | if (event->event_type == ESP_PRIV_EVENT_INIT) {
174 | printk (KERN_INFO "Received INIT event from esp32");
175 | process_init_event(esp, event->event_data, event->event_len);
176 | } else {
177 | printk (KERN_WARNING "Drop unknown event");
178 | }
179 | }
180 |
181 | static void process_priv_communication(struct esp_spi_context *esp, struct sk_buff *skb)
182 | {
183 | struct esp_payload_header *header;
184 | u8 *payload;
185 | u16 len;
186 |
187 | if (!skb || !skb->data)
188 | return;
189 |
190 | header = (struct esp_payload_header *) skb->data;
191 |
192 | payload = skb->data + le16_to_cpu(header->offset);
193 | len = le16_to_cpu(header->len);
194 |
195 | if (header->priv_pkt_type == ESP_PACKET_TYPE_EVENT) {
196 | process_event(esp, payload, len);
197 | }
198 |
199 | dev_kfree_skb(skb);
200 | }
201 |
202 | static int process_rx_buf(struct esp_spi_context *esp, struct sk_buff *skb)
203 | {
204 | struct esp_payload_header *header;
205 | u16 len = 0;
206 | u16 offset = 0;
207 |
208 | if (!skb)
209 | return -EINVAL;
210 |
211 | header = (struct esp_payload_header *) skb->data;
212 |
213 | offset = le16_to_cpu(header->offset);
214 |
215 | /* Validate received SKB. Check len and offset fields */
216 | if (offset != sizeof(struct esp_payload_header))
217 | return -EINVAL;
218 |
219 | len = le16_to_cpu(header->len);
220 | if (!len)
221 | return -EINVAL;
222 |
223 | len += sizeof(struct esp_payload_header);
224 |
225 | if (len > SPI_BUF_SIZE)
226 | return -EINVAL;
227 |
228 | /* Trim SKB to actual size */
229 | skb_trim(skb, len);
230 |
231 | if (header->if_type == ESP_PRIV_IF) {
232 | process_priv_communication(esp, skb);
233 | return 0;
234 | }
235 |
236 | if (!data_path)
237 | return -EPERM;
238 |
239 | /* enqueue skb for read_packet to pick it */
240 | skb_queue_tail(&esp->rx_q, skb);
241 |
242 | /* indicate reception of new packet */
243 | esp_process_new_packet_intr(esp->adapter);
244 |
245 | return 0;
246 | }
247 |
248 | static void esp_spi_work(struct work_struct *work)
249 | {
250 | struct esp_spi_context *esp = container_of(work,
251 | struct esp_spi_context, spi_work);
252 | struct spi_transfer trans;
253 | struct sk_buff *tx_skb, *rx_skb;
254 | u8 *rx_buf;
255 | int ret = 0;
256 |
257 | memset(&trans, 0, sizeof(trans));
258 | tx_skb = NULL;
259 |
260 | /* Setup and execute SPI transaction
261 | * Tx_buf: Check if tx_q has valid buffer for transmission,
262 | * else keep it blank
263 | *
264 | * Rx_buf: Allocate memory for incoming data. This will be freed
265 | * immediately if received buffer is invalid.
266 | * If it is a valid buffer, upper layer will free it.
267 | * */
268 |
269 | /* Configure TX buffer if available */
270 | if (data_path)
271 | tx_skb = skb_dequeue(&esp->tx_q);
272 |
273 | if (tx_skb) {
274 | trans.tx_buf = tx_skb->data;
275 | }
276 |
277 | /* Configure RX buffer */
278 | rx_skb = esp_alloc_skb(SPI_BUF_SIZE);
279 | rx_buf = skb_put(rx_skb, SPI_BUF_SIZE);
280 |
281 | memset(rx_buf, 0, SPI_BUF_SIZE);
282 |
283 | trans.rx_buf = rx_buf;
284 | trans.len = SPI_BUF_SIZE;
285 |
286 | ret = spi_sync_transfer(esp->esp_spi_dev, &trans, 1);
287 |
288 | if (ret) {
289 | printk(KERN_ERR "SPI Transaction failed: %d", ret);
290 | }
291 |
292 | /* Free rx_skb if received data is not valid */
293 | if (process_rx_buf(esp, rx_skb)) {
294 | dev_kfree_skb(rx_skb);
295 | }
296 |
297 | if (tx_skb)
298 | dev_kfree_skb(tx_skb);
299 | }
300 |
301 | static int spi_init(struct esp_spi_context *esp, struct spi_device *spi)
302 | {
303 | struct device *dev = &spi->dev;
304 | int status = 0;
305 |
306 | esp->spi_workqueue = create_workqueue("ESP_SPI_WORK_QUEUE");
307 | if (!esp->spi_workqueue) {
308 | spi_exit(esp);
309 | return -EFAULT;
310 | }
311 |
312 | INIT_WORK(&esp->spi_work, esp_spi_work);
313 |
314 | skb_queue_head_init(&esp->tx_q);
315 | skb_queue_head_init(&esp->rx_q);
316 |
317 | esp->esp_spi_dev = spi;
318 | if (!esp->esp_spi_dev) {
319 | dev_err(dev, "Failed to add new SPI device\n");
320 | spi_exit(esp);
321 | return -ENODEV;
322 | }
323 |
324 | status = devm_request_irq(dev, spi->irq, spi_interrupt_handler,
325 | IRQF_SHARED | IRQF_TRIGGER_RISING,
326 | "esp_spi", esp);
327 | if (status) {
328 | dev_err(dev, "Failed to request IRQ %d\n", status);
329 | spi_exit(esp);
330 | return status;
331 | }
332 |
333 | open_data_path();
334 |
335 | #ifdef CONFIG_SUPPORT_ESP_SERIAL
336 | status = esp_serial_init((void *) esp->adapter);
337 | if (status != 0) {
338 | spi_exit(esp);
339 | dev_err(dev, "Error initialising serial interface\n");
340 | return status;
341 | }
342 | #endif
343 |
344 | status = esp_add_card(esp->adapter);
345 | if (status) {
346 | spi_exit(esp);
347 | dev_err(dev, "Failed to add card\n");
348 | return status;
349 | }
350 |
351 | msleep(200);
352 |
353 | return status;
354 | }
355 |
356 | static void spi_exit(struct esp_spi_context *esp)
357 | {
358 | close_data_path();
359 | msleep(200);
360 |
361 | skb_queue_purge(&esp->tx_q);
362 | skb_queue_purge(&esp->rx_q);
363 |
364 | if (esp->spi_workqueue) {
365 | destroy_workqueue(esp->spi_workqueue);
366 | esp->spi_workqueue = NULL;
367 | }
368 |
369 | esp_serial_cleanup();
370 | esp_remove_card(esp->adapter);
371 |
372 | if (esp->adapter->hcidev)
373 | esp_deinit_bt(esp->adapter);
374 |
375 | memset(esp, 0, sizeof(*esp));
376 | }
377 |
378 | static int esp_init_interface_layer(struct esp_spi_context *esp, struct esp_adapter *adapter,
379 | struct spi_device *spi)
380 | {
381 | if (!adapter)
382 | return -EINVAL;
383 |
384 | memset(esp, 0, sizeof(*esp));
385 |
386 | adapter->if_context = esp;
387 | adapter->if_ops = &if_ops;
388 | adapter->if_type = ESP_IF_TYPE_SPI;
389 | esp->adapter = adapter;
390 |
391 | return spi_init(esp, spi);
392 | }
393 |
394 | static void esp_deinit_interface_layer(struct esp_spi_context *esp)
395 | {
396 | spi_exit(esp);
397 | }
398 |
399 | static void esp32_spi_reset(struct esp_spi_context *esp)
400 | {
401 | gpiod_direction_output(esp->reset_gpio, GPIOD_OUT_LOW);
402 | udelay(100);
403 | gpiod_direction_output(esp->reset_gpio, GPIOD_OUT_HIGH);
404 | }
405 |
406 | static int esp32_spi_probe(struct spi_device *spi)
407 | {
408 | struct esp_spi_context *esp;
409 | int ret = 0;
410 | struct device *dev = &spi->dev;
411 | struct esp_adapter *adapter;
412 |
413 | esp = devm_kzalloc(dev, sizeof(*esp), GFP_KERNEL);
414 | if (!esp)
415 | return -ENOMEM;
416 | esp->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
417 | if (IS_ERR(esp->reset_gpio)) {
418 | dev_err(dev, "Can't get reset gpio\n");
419 | return -ENODEV;
420 | }
421 | spi_set_drvdata(spi, esp);
422 |
423 | esp32_spi_reset(esp);
424 |
425 | /* Init adapter */
426 | adapter = init_adapter();
427 | if (!adapter)
428 | return -EFAULT;
429 |
430 | /* Init transport layer */
431 | ret = esp_init_interface_layer(esp, adapter, spi);
432 | if (ret != 0) {
433 | deinit_adapter();
434 | } else
435 | dev_info(&spi->dev, "probed!\n");
436 |
437 | return ret;
438 | }
439 |
440 | static int esp32_spi_remove(struct spi_device *spi)
441 | {
442 | struct esp_spi_context *esp = spi_get_drvdata(spi);
443 |
444 | esp_deinit_interface_layer(esp);
445 | deinit_adapter();
446 |
447 | return 0;
448 | }
449 |
450 | #ifdef CONFIG_OF
451 | static const struct of_device_id esp32_spi_dt_ids[] = {
452 | { .compatible = "espressif,esp32" },
453 | {},
454 | };
455 | MODULE_DEVICE_TABLE(of, esp32_spi_dt_ids);
456 | #endif
457 |
458 | static struct spi_driver esp32_spi_driver = {
459 | .driver = {
460 | .name = "esp32",
461 | .of_match_table = of_match_ptr(esp32_spi_dt_ids),
462 | },
463 | .probe = esp32_spi_probe,
464 | .remove = esp32_spi_remove,
465 | };
466 | module_spi_driver(esp32_spi_driver);
467 |
468 | MODULE_AUTHOR("Amey Inamdar ");
469 | MODULE_AUTHOR("Mangesh Malusare ");
470 | MODULE_AUTHOR("Yogesh Mantri ");
471 | MODULE_AUTHOR("Boundary Devices ");
472 | MODULE_DESCRIPTION("Host SPI driver for ESP32 Hosted solution");
473 | MODULE_LICENSE("GPL");
474 | MODULE_ALIAS("spi:esp32");
475 |
--------------------------------------------------------------------------------
/spi/esp_spi.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015-2020 Espressif Systems (Shanghai) PTE LTD
3 | *
4 | * This software file (the "File") is distributed by Espressif Systems (Shanghai)
5 | * PTE LTD under the terms of the GNU General Public License Version 2, June 1991
6 | * (the "License"). You may use, redistribute and/or modify this File in
7 | * accordance with the terms and conditions of the License, a copy of which
8 | * is available by writing to the Free Software Foundation, Inc.,
9 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
10 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
11 | *
12 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
13 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
14 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
15 | * this warranty disclaimer.
16 | */
17 | #ifndef _ESP_SPI_H_
18 | #define _ESP_SPI_H_
19 |
20 | #include "esp.h"
21 |
22 | #define SPI_BUF_SIZE 2048
23 |
24 | struct esp_spi_context {
25 | struct esp_adapter *adapter;
26 | struct spi_device *esp_spi_dev;
27 | struct sk_buff_head tx_q;
28 | struct sk_buff_head rx_q;
29 | struct workqueue_struct *spi_workqueue;
30 | struct work_struct spi_work;
31 | struct gpio_desc *reset_gpio;
32 | };
33 |
34 | enum {
35 | CLOSE_DATAPATH,
36 | OPEN_DATAPATH,
37 | };
38 |
39 | #endif
40 |
--------------------------------------------------------------------------------