mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
ODROID-C4: wireless: esp8089: Support esp8089 driver.
- The esp8089 driver supports many esp's wifi modules. So it is imported. Change-Id: If039882e183e454baff2c222bf7a1282b6705459
This commit is contained in:
@@ -20,7 +20,8 @@ dtbo-$(CONFIG_ARCH_MESON64_ODROIDC4) += spi0.dtbo \
|
||||
pwm_b-backlight.dtbo \
|
||||
wifi_bt_combo.dtbo \
|
||||
sdio.dtbo \
|
||||
gpio_shortcut.dtbo
|
||||
gpio_shortcut.dtbo \
|
||||
esp8089.dtbo
|
||||
|
||||
targets += $(dtbo-y)
|
||||
always := $(dtbo-y)
|
||||
|
||||
24
arch/arm64/boot/dts/amlogic/overlays/odroidc4/esp8089.dts
Normal file
24
arch/arm64/boot/dts/amlogic/overlays/odroidc4/esp8089.dts
Normal file
@@ -0,0 +1,24 @@
|
||||
/dts-v1/;
|
||||
/plugin/;
|
||||
|
||||
/ {
|
||||
fragment@0 {
|
||||
target = <&sd_emmc_a>;
|
||||
|
||||
__overlay__ {
|
||||
status = "okay";
|
||||
|
||||
sdio {
|
||||
caps = "MMC_CAP_4_BIT_DATA",
|
||||
"MMC_CAP_MMC_HIGHSPEED",
|
||||
"MMC_CAP_SD_HIGHSPEED",
|
||||
"MMC_CAP_NONREMOVABLE",
|
||||
"MMC_CAP_UHS_SDR12",
|
||||
"MMC_CAP_UHS_SDR25",
|
||||
"MMC_CAP_UHS_SDR50",
|
||||
"MMC_CAP_UHS_SDR104",
|
||||
"MMC_PM_KEEP_POWER";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -2278,7 +2278,9 @@ CONFIG_WLAN_VENDOR_ZYDAS=y
|
||||
# CONFIG_USB_ZD1201 is not set
|
||||
# CONFIG_ZD1211RW is not set
|
||||
# CONFIG_MAC80211_HWSIM is not set
|
||||
# CONFIG_USB_NET_RNDIS_WLAN is not set
|
||||
CONFIG_USB_NET_RNDIS_WLAN=m
|
||||
CONFIG_ESP8089=m
|
||||
CONFIG_ESP8089_DEBUG_FS=y
|
||||
|
||||
#
|
||||
# Enable WiMAX (Networking options) to see the WiMAX drivers
|
||||
|
||||
@@ -2157,7 +2157,9 @@ CONFIG_WLAN_VENDOR_ZYDAS=y
|
||||
# CONFIG_USB_ZD1201 is not set
|
||||
# CONFIG_ZD1211RW is not set
|
||||
# CONFIG_MAC80211_HWSIM is not set
|
||||
# CONFIG_USB_NET_RNDIS_WLAN is not set
|
||||
CONFIG_USB_NET_RNDIS_WLAN=m
|
||||
CONFIG_ESP8089=m
|
||||
CONFIG_ESP8089_DEBUG_fs=y
|
||||
|
||||
#
|
||||
# Enable WiMAX (Networking options) to see the WiMAX drivers
|
||||
|
||||
@@ -32,6 +32,7 @@ source "drivers/net/wireless/rsi/Kconfig"
|
||||
source "drivers/net/wireless/st/Kconfig"
|
||||
source "drivers/net/wireless/ti/Kconfig"
|
||||
source "drivers/net/wireless/zydas/Kconfig"
|
||||
source "drivers/net/wireless/esp8089/Kconfig"
|
||||
|
||||
config PCMCIA_RAYCS
|
||||
tristate "Aviator/Raytheon 2.4GHz wireless support"
|
||||
|
||||
@@ -25,3 +25,5 @@ obj-$(CONFIG_PCMCIA_WL3501) += wl3501_cs.o
|
||||
obj-$(CONFIG_USB_NET_RNDIS_WLAN) += rndis_wlan.o
|
||||
|
||||
obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o
|
||||
|
||||
obj-$(CONFIG_ESP8089) += esp8089/
|
||||
|
||||
13
drivers/net/wireless/esp8089/Kconfig
Normal file
13
drivers/net/wireless/esp8089/Kconfig
Normal file
@@ -0,0 +1,13 @@
|
||||
config ESP8089
|
||||
tristate "Espressif ESP8089 SDIO WiFi"
|
||||
depends on MAC80211
|
||||
---help---
|
||||
ESP8089 is a low-budget 2.4GHz WiFi chip by Espressif, used in many
|
||||
cheap tablets with Allwinner or Rockchip SoC
|
||||
|
||||
config ESP8089_DEBUG_FS
|
||||
bool "Enable DebugFS support for ESP8089"
|
||||
depends on ESP8089
|
||||
default y
|
||||
---help---
|
||||
DebugFS support for ESP8089
|
||||
340
drivers/net/wireless/esp8089/LICENSE
Normal file
340
drivers/net/wireless/esp8089/LICENSE
Normal file
@@ -0,0 +1,340 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
{description}
|
||||
Copyright (C) {year} {fullname}
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
{signature of Ty Coon}, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
|
||||
148
drivers/net/wireless/esp8089/Makefile
Executable file
148
drivers/net/wireless/esp8089/Makefile
Executable file
@@ -0,0 +1,148 @@
|
||||
MODNAME = esp8089
|
||||
|
||||
# By default, we try to compile the modules for the currently running
|
||||
# kernel. But it's the first approximation, as we will re-read the
|
||||
# version from the kernel sources.
|
||||
KVERS_UNAME ?= $(shell uname -r)
|
||||
KVERS_ARCH ?= $(shell arch)
|
||||
|
||||
# KBUILD is the path to the Linux kernel build tree. It is usually the
|
||||
# same as the kernel source tree, except when the kernel was compiled in
|
||||
# a separate directory.
|
||||
KBUILD ?= $(PWD)/out/target/product/$(TARGET_PRODUCT)/obj/KERNEL_OBJ
|
||||
|
||||
ifeq (,$(KBUILD))
|
||||
$(error Kernel build tree not found - please set KBUILD to configured kernel)
|
||||
endif
|
||||
|
||||
KCONFIG := $(KBUILD)/.config
|
||||
ifeq (,$(wildcard $(KCONFIG)))
|
||||
$(error No .config found in $(KBUILD), please set KBUILD to configured kernel)
|
||||
endif
|
||||
|
||||
ifneq (,$(wildcard $(KBUILD)/include/linux/version.h))
|
||||
ifneq (,$(wildcard $(KBUILD)/include/generated/uapi/linux/version.h))
|
||||
$(error Multiple copies of version.h found, please clean your build tree)
|
||||
endif
|
||||
endif
|
||||
|
||||
# Kernel Makefile doesn't always know the exact kernel version, so we
|
||||
# get it from the kernel headers instead and pass it to make.
|
||||
VERSION_H := $(KBUILD)/include/generated/utsrelease.h
|
||||
ifeq (,$(wildcard $(VERSION_H)))
|
||||
VERSION_H := $(KBUILD)/include/linux/utsrelease.h
|
||||
endif
|
||||
ifeq (,$(wildcard $(VERSION_H)))
|
||||
VERSION_H := $(KBUILD)/include/linux/version.h
|
||||
endif
|
||||
ifeq (,$(wildcard $(VERSION_H)))
|
||||
$(error Please run 'make modules_prepare' in $(KBUILD))
|
||||
endif
|
||||
|
||||
KVERS := $(shell sed -ne 's/"//g;s/^\#define UTS_RELEASE //p' $(VERSION_H))
|
||||
|
||||
ifeq (,$(KVERS))
|
||||
$(error Cannot find UTS_RELEASE in $(VERSION_H), please report)
|
||||
endif
|
||||
|
||||
INST_DIR = /lib/modules/$(KVERS)/misc
|
||||
|
||||
SRC_DIR=$(shell pwd)
|
||||
|
||||
include $(KCONFIG)
|
||||
|
||||
#Shouldn't fail when not having dkms.conf in directory
|
||||
#(usually when installing a built package on other system)
|
||||
-include dkms.conf
|
||||
PACKAGE_NAME := $(patsubst "%",%,$(PACKAGE_NAME))
|
||||
PACKAGE_VERSION := $(patsubst "%",%,$(PACKAGE_VERSION))
|
||||
DKMS_PATH := /usr/src/$(PACKAGE_NAME)-$(PACKAGE_VERSION)/
|
||||
|
||||
EXTRA_CFLAGS += -DDEBUG -DSIP_DEBUG -DFAST_TX_STATUS \
|
||||
-DKERNEL_IV_WAR -DRX_SENDUP_SYNC -DDEBUG_FS \
|
||||
-DSIF_DSR_WAR -DHAS_INIT_DATA -DHAS_FW
|
||||
|
||||
EXTRA_CFLAGS += -DESP_USE_SDIO
|
||||
|
||||
ifdef ANDROID
|
||||
EXTRA_CFLAGS += -DANDROID
|
||||
endif
|
||||
|
||||
ifdef P2P_CONCURRENT
|
||||
EXTRA_CFLAGS += -DP2P_CONCURRENT
|
||||
endif
|
||||
|
||||
ifdef TEST_MODE
|
||||
EXTRA_CFLAGS += -DTEST_MODE
|
||||
endif
|
||||
|
||||
OBJS = esp_debug.o sdio_sif_esp.o spi_sif_esp.o esp_io.o \
|
||||
esp_file.o esp_main.o esp_sip.o esp_ext.o esp_ctrl.o \
|
||||
esp_mac80211.o esp_debug.o esp_utils.o esp_pm.o testmode.o
|
||||
|
||||
all: config_check modules
|
||||
|
||||
MODULE := $(MODNAME).ko
|
||||
obj-m := $(MODNAME).o
|
||||
|
||||
$(MODNAME)-objs := $(OBJS)
|
||||
|
||||
config_check:
|
||||
@if [ -z "$(CONFIG_WIRELESS_EXT)$(CONFIG_NET_RADIO)" ]; then \
|
||||
echo; echo; \
|
||||
echo "*** WARNING: This kernel lacks wireless extensions."; \
|
||||
echo "Wireless drivers will not work properly."; \
|
||||
echo; echo; \
|
||||
fi
|
||||
|
||||
# Taken from here:
|
||||
# http://www.xkyle.com/building-linux-packages-for-kernel-drivers/
|
||||
|
||||
dkms:
|
||||
$(MAKE) config_check
|
||||
echo $(DKMS_PATH)
|
||||
echo "$(KVERS_UNAME)"
|
||||
mkdir -p $(DKMS_PATH)
|
||||
cp -r . $(DKMS_PATH)
|
||||
-rm -rf $(DKMS_PATH)/.git
|
||||
-rm $(DKMS_PATH)/.gitignore
|
||||
-rm $(DKMS_PATH)/*deb
|
||||
dkms add -m $(PACKAGE_NAME) -v $(PACKAGE_VERSION)
|
||||
dkms build -m $(PACKAGE_NAME) -v $(PACKAGE_VERSION)
|
||||
|
||||
dkmsdeb: dkms
|
||||
dkms mkdsc -m $(PACKAGE_NAME) -v $(PACKAGE_VERSION) --source-only
|
||||
dkms mkdeb -m $(PACKAGE_NAME) -v $(PACKAGE_VERSION) --source-only
|
||||
cp /var/lib/dkms/$(PACKAGE_NAME)/$(PACKAGE_VERSION)/deb/*.deb .
|
||||
|
||||
cleandkms:
|
||||
-dkms uninstall $(PACKAGE_NAME)/$(PACKAGE_VERSION)
|
||||
-dkms remove $(PACKAGE_NAME)/$(PACKAGE_VERSION) --all
|
||||
-rm -rf /var/lib/dkms/$(PACKAGE_NAME)/$(PACKAGE_VERSION) $(DKMS_PATH)
|
||||
|
||||
modules:
|
||||
$(MAKE) -C $(KBUILD) M=$(SRC_DIR)
|
||||
|
||||
$(MODULE):
|
||||
$(MAKE) modules
|
||||
|
||||
clean:
|
||||
rm -f *.o *.ko .*.cmd *.mod.c *.symvers modules.order
|
||||
rm -rf .tmp_versions
|
||||
|
||||
install: config_check $(MODULE)
|
||||
@/sbin/modinfo $(MODULE) | grep -q "^vermagic: *$(KVERS) " || \
|
||||
{ echo "$(MODULE)" is not for Linux $(KVERS); exit 1; }
|
||||
mkdir -p -m 755 $(DESTDIR)$(INST_DIR)
|
||||
install -m 0644 $(MODULE) $(DESTDIR)$(INST_DIR)
|
||||
ifndef DESTDIR
|
||||
-/sbin/depmod -a $(KVERS)
|
||||
endif
|
||||
|
||||
uninstall:
|
||||
rm -f $(DESTDIR)$(INST_DIR)/$(MODULE)
|
||||
ifndef DESTDIR
|
||||
-/sbin/depmod -a $(KVERS)
|
||||
endif
|
||||
|
||||
.PHONY: all modules clean install config_check
|
||||
60
drivers/net/wireless/esp8089/README.md
Normal file
60
drivers/net/wireless/esp8089/README.md
Normal file
@@ -0,0 +1,60 @@
|
||||
esp8089
|
||||
======
|
||||
|
||||
ESP8089 Linux driver
|
||||
|
||||
v1.9 imported from the Rockchip Linux kernel github repo
|
||||
|
||||
Modified to build as a standalone module for SDIO devices.
|
||||
|
||||
|
||||
|
||||
|
||||
Building:
|
||||
|
||||
make
|
||||
|
||||
sudo make install
|
||||
|
||||
Using:
|
||||
|
||||
modprobe should autoload the module as the ESP8089 should be detected by
|
||||
the SDIO driver and loaded as a dependency.
|
||||
|
||||
The ESP8089 requires that the CH_PD signal be reset before the driver
|
||||
can load properly, so a GPIO is used by the driver to assert this signal
|
||||
for 200ms. The GPIO defaults to 0 (ID_SD on the Raspberry Pi) but this
|
||||
can be changed to any GPIO mapped by the kernel GPIO driver through the
|
||||
esp_reset_gpio module parameter. This can be accomplished by creating a
|
||||
new modprobe.d config file. For example, to use GPIO 5 instead, create
|
||||
as root /etc/modprobe.d/esp.conf and add the line:
|
||||
|
||||
options esp8089 esp_reset_gpio=5
|
||||
|
||||
which changes the GPIO from 0 to 5.
|
||||
|
||||
|
||||
Building a Debian source package:
|
||||
|
||||
To build a source package for release, first install the following:
|
||||
|
||||
apt-get install debhelper dkms raspberrypi-kernel-headers
|
||||
|
||||
Then build the package:
|
||||
|
||||
sudo make dkmsdeb
|
||||
|
||||
The module will be named esp8089-dkms_*.deb. Don't forget to update the version
|
||||
in dkms.conf and committing before making a release!
|
||||
|
||||
|
||||
If the build fails to create a source package, try installing dkms from github:
|
||||
|
||||
sudo apt-get remove dkms
|
||||
sudo apt-get install devscripts quilt
|
||||
git clone https://github.com/dell/dkms.git
|
||||
cd dkms
|
||||
sed -ie "s/module-init-tools/kmod/g" debian/control
|
||||
make debs
|
||||
|
||||
and install the resulting package in dist/
|
||||
7
drivers/net/wireless/esp8089/dkms.conf
Normal file
7
drivers/net/wireless/esp8089/dkms.conf
Normal file
@@ -0,0 +1,7 @@
|
||||
PACKAGE_NAME="esp8089"
|
||||
PACKAGE_VERSION="1.9.20190603"
|
||||
CLEAN="make clean"
|
||||
MAKE[0]="make KVERS_UNAME=$kernelver"
|
||||
BUILT_MODULE_NAME[0]="esp8089"
|
||||
DEST_MODULE_LOCATION="/updates"
|
||||
AUTOINSTALL="yes"
|
||||
3268
drivers/net/wireless/esp8089/eagle_fw1.h
Executable file
3268
drivers/net/wireless/esp8089/eagle_fw1.h
Executable file
File diff suppressed because it is too large
Load Diff
4197
drivers/net/wireless/esp8089/eagle_fw2.h
Executable file
4197
drivers/net/wireless/esp8089/eagle_fw2.h
Executable file
File diff suppressed because it is too large
Load Diff
3791
drivers/net/wireless/esp8089/eagle_fw3.h
Normal file
3791
drivers/net/wireless/esp8089/eagle_fw3.h
Normal file
File diff suppressed because it is too large
Load Diff
6
drivers/net/wireless/esp8089/esp_conf.h
Executable file
6
drivers/net/wireless/esp8089/esp_conf.h
Executable file
@@ -0,0 +1,6 @@
|
||||
#ifndef _ESP_CONF_H_
|
||||
#define _ESP_CONF_H_
|
||||
|
||||
#define INIT_DATA_CONF_BUF "crystal_26M_en=1;test_xtal=0;sdio_configure=2;bt_configure=0;bt_protocol=0;dual_ant_configure=0;test_uart_configure=0;share_xtal=0;gpio_wake=0;no_auto_sleep=1;ext_rst=0;wakeup_gpio=12;ate_test=0;speed_suspend=0;$"
|
||||
|
||||
#endif /*_ESP_CONF_H_ */
|
||||
1
drivers/net/wireless/esp8089/esp_config.mk
Executable file
1
drivers/net/wireless/esp8089/esp_config.mk
Executable file
@@ -0,0 +1 @@
|
||||
EXTRA_CFLAGS += -DP2P_CONCURRENT -DESP_ACK_INTERRUPT -DESP_USE_SDIO
|
||||
807
drivers/net/wireless/esp8089/esp_ctrl.c
Executable file
807
drivers/net/wireless/esp8089/esp_ctrl.c
Executable file
@@ -0,0 +1,807 @@
|
||||
/*
|
||||
* Copyright (c) 2009 - 2014 Espressif System.
|
||||
*
|
||||
* SIP ctrl packet parse and pack
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <net/mac80211.h>
|
||||
#include <net/cfg80211.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/firmware.h>
|
||||
|
||||
#include "esp_pub.h"
|
||||
#include "esp_sip.h"
|
||||
#include "esp_ctrl.h"
|
||||
#include "esp_sif.h"
|
||||
#include "esp_debug.h"
|
||||
#include "esp_wmac.h"
|
||||
#include "esp_utils.h"
|
||||
#include "esp_wl.h"
|
||||
#include "esp_file.h"
|
||||
#include "esp_path.h"
|
||||
#ifdef TEST_MODE
|
||||
#include "testmode.h"
|
||||
#endif /* TEST_MODE */
|
||||
#include "esp_version.h"
|
||||
|
||||
extern struct completion *gl_bootup_cplx;
|
||||
|
||||
static void esp_tx_ba_session_op(struct esp_sip *sip, struct esp_node *node, trc_ampdu_state_t state, u8 tid )
|
||||
{
|
||||
struct esp_tx_tid *txtid;
|
||||
|
||||
txtid = &node->tid[tid];
|
||||
if (state == TRC_TX_AMPDU_STOPPED) {
|
||||
if (txtid->state == ESP_TID_STATE_OPERATIONAL) {
|
||||
esp_dbg(ESP_DBG_TXAMPDU, "%s tid %d TXAMPDU GOT STOP EVT\n", __func__, tid);
|
||||
|
||||
spin_lock_bh(&sip->epub->tx_ampdu_lock);
|
||||
txtid->state = ESP_TID_STATE_WAIT_STOP;
|
||||
spin_unlock_bh(&sip->epub->tx_ampdu_lock);
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28))
|
||||
ieee80211_stop_tx_ba_session(sip->epub->hw, node->addr, (u16)tid, WLAN_BACK_INITIATOR);
|
||||
#elif (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32))
|
||||
ieee80211_stop_tx_ba_session(sip->epub->hw, node->sta->addr, (u16)tid, WLAN_BACK_INITIATOR);
|
||||
#elif (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35))
|
||||
ieee80211_stop_tx_ba_session(node->sta, (u16)tid, WLAN_BACK_INITIATOR);
|
||||
#else
|
||||
ieee80211_stop_tx_ba_session(node->sta, (u16)tid);
|
||||
#endif /* KERNEL_VERSION 2.6.39 */
|
||||
} else {
|
||||
esp_dbg(ESP_DBG_TXAMPDU, "%s tid %d TXAMPDU GOT STOP EVT IN WRONG STATE %d\n", __func__, tid, txtid->state);
|
||||
}
|
||||
} else if (state == TRC_TX_AMPDU_OPERATIONAL) {
|
||||
if (txtid->state == ESP_TID_STATE_STOP) {
|
||||
esp_dbg(ESP_DBG_TXAMPDU, "%s tid %d TXAMPDU GOT OPERATIONAL\n", __func__, tid);
|
||||
|
||||
spin_lock_bh(&sip->epub->tx_ampdu_lock);
|
||||
txtid->state = ESP_TID_STATE_TRIGGER;
|
||||
spin_unlock_bh(&sip->epub->tx_ampdu_lock);
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28))
|
||||
ieee80211_start_tx_ba_session(sip->epub->hw, node->addr, tid);
|
||||
#elif (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32))
|
||||
ieee80211_start_tx_ba_session(sip->epub->hw, node->sta->addr, tid);
|
||||
#elif (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 37))
|
||||
ieee80211_start_tx_ba_session(node->sta, (u16)tid);
|
||||
#else
|
||||
ieee80211_start_tx_ba_session(node->sta, (u16)tid, 0);
|
||||
#endif /* KERNEL_VERSION 2.6.39 */
|
||||
|
||||
} else if(txtid->state == ESP_TID_STATE_OPERATIONAL) {
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28))
|
||||
sip_send_ampdu_action(sip->epub, SIP_AMPDU_TX_OPERATIONAL, node->addr, tid, node->ifidx, 0);
|
||||
#else
|
||||
sip_send_ampdu_action(sip->epub, SIP_AMPDU_TX_OPERATIONAL, node->sta->addr, tid, node->ifidx, 0);
|
||||
#endif
|
||||
} else {
|
||||
esp_dbg(ESP_DBG_TXAMPDU, "%s tid %d TXAMPDU GOT OPERATIONAL EVT IN WRONG STATE %d\n", __func__, tid, txtid->state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TEST_MODE
|
||||
int sip_parse_event_debug(struct esp_pub *epub, const u8 *src, u8 *dst)
|
||||
{
|
||||
struct sip_evt_debug* debug_evt = (struct sip_evt_debug *)(src + SIP_CTRL_HDR_LEN);
|
||||
|
||||
switch (debug_evt->results[0]) {
|
||||
case RDRSSI: {
|
||||
u32 mask = debug_evt->results[1];
|
||||
u8 *p = (u8 *)&debug_evt->results[2];
|
||||
u8 index;
|
||||
struct esp_node *enode;
|
||||
|
||||
while (mask != 0) {
|
||||
index = ffs(mask) - 1;
|
||||
if (index >= ESP_PUB_MAX_STA)
|
||||
break;
|
||||
enode = esp_get_node_by_index(epub, index);
|
||||
if (enode == NULL) {
|
||||
esp_dbg(ESP_DBG_ERROR, "trc mask dismatch");
|
||||
} else {
|
||||
dst += sprintf(dst, "%02x:%02x:%02x:%02x:%02x:%02x 0x%x 0x%x\n",
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
|
||||
enode->sta->addr[0], enode->sta->addr[1], enode->sta->addr[2],
|
||||
enode->sta->addr[3], enode->sta->addr[4], enode->sta->addr[5],
|
||||
#else
|
||||
enode->addr[0], enode->addr[1], enode->addr[2],
|
||||
enode->addr[3], enode->addr[4], enode->addr[5],
|
||||
#endif
|
||||
*p, *(p+1));
|
||||
p += 2;
|
||||
}
|
||||
mask &= ~(1<<index);
|
||||
};
|
||||
dst += sprintf(dst, "%c", '\0');
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
int i;
|
||||
for(i = 1; i < debug_evt->len; i++)
|
||||
dst += sprintf(dst, "0x%x%s", debug_evt->results[i], i == debug_evt->len -1 ? "":" " );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /*TEST_MODE*/
|
||||
|
||||
|
||||
int sip_parse_events(struct esp_sip *sip, u8 *buf)
|
||||
{
|
||||
struct sip_hdr *hdr = (struct sip_hdr *)buf;
|
||||
|
||||
switch (hdr->c_evtid) {
|
||||
case SIP_EVT_TARGET_ON: {
|
||||
/* use rx work queue to send... */
|
||||
if (atomic_read(&sip->state) == SIP_PREPARE_BOOT || atomic_read(&sip->state) == SIP_BOOT) {
|
||||
atomic_set(&sip->state, SIP_SEND_INIT);
|
||||
queue_work(sip->epub->esp_wkq, &sip->rx_process_work);
|
||||
} else {
|
||||
esp_dbg(ESP_DBG_ERROR, "%s boot during wrong state %d\n", __func__, atomic_read(&sip->state));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SIP_EVT_BOOTUP: {
|
||||
struct sip_evt_bootup2 *bootup_evt = (struct sip_evt_bootup2 *)(buf + SIP_CTRL_HDR_LEN);
|
||||
if (sip->rawbuf)
|
||||
kfree(sip->rawbuf);
|
||||
|
||||
sip_post_init(sip, bootup_evt);
|
||||
|
||||
if (gl_bootup_cplx)
|
||||
complete(gl_bootup_cplx);
|
||||
|
||||
break;
|
||||
}
|
||||
case SIP_EVT_RESETTING:{
|
||||
sip->epub->wait_reset = 1;
|
||||
if (gl_bootup_cplx)
|
||||
complete(gl_bootup_cplx);
|
||||
break;
|
||||
}
|
||||
case SIP_EVT_SLEEP:{
|
||||
//atomic_set(&sip->epub->ps.state, ESP_PM_ON);
|
||||
break;
|
||||
}
|
||||
case SIP_EVT_TXIDLE:{
|
||||
//struct sip_evt_txidle *txidle = (struct sip_evt_txidle *)(buf + SIP_CTRL_HDR_LEN);
|
||||
//sip_txdone_clear(sip, txidle->last_seq);
|
||||
break;
|
||||
}
|
||||
#ifndef FAST_TX_STATUS
|
||||
case SIP_EVT_TX_STATUS: {
|
||||
struct sip_evt_tx_report *report = (struct sip_evt_tx_report *)(buf + SIP_CTRL_HDR_LEN);
|
||||
sip_txdoneq_process(sip, report);
|
||||
|
||||
break;
|
||||
}
|
||||
#endif /* FAST_TX_STATUS */
|
||||
|
||||
case SIP_EVT_SCAN_RESULT: {
|
||||
struct sip_evt_scan_report *report = (struct sip_evt_scan_report *)(buf + SIP_CTRL_HDR_LEN);
|
||||
if (atomic_read(&sip->epub->wl.off)) {
|
||||
esp_dbg(ESP_DBG_ERROR, "%s scan result while wlan off\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
sip_scandone_process(sip, report);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SIP_EVT_ROC: {
|
||||
struct sip_evt_roc* report = (struct sip_evt_roc *)(buf + SIP_CTRL_HDR_LEN);
|
||||
esp_rocdone_process(sip->epub->hw, report);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
#ifdef ESP_RX_COPYBACK_TEST
|
||||
|
||||
case SIP_EVT_COPYBACK: {
|
||||
u32 len = hdr->len - SIP_CTRL_HDR_LEN;
|
||||
|
||||
esp_dbg(ESP_DBG_TRACE, "%s copyback len %d seq %u\n", __func__, len, hdr->seq);
|
||||
|
||||
memcpy(copyback_buf + copyback_offset, pkt->buf + SIP_CTRL_HDR_LEN, len);
|
||||
copyback_offset += len;
|
||||
|
||||
//show_buf(pkt->buf, 256);
|
||||
|
||||
//how about totlen % 256 == 0??
|
||||
if (hdr->hdr.len < 256) {
|
||||
kfree(copyback_buf);
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif /* ESP_RX_COPYBACK_TEST */
|
||||
case SIP_EVT_CREDIT_RPT:
|
||||
break;
|
||||
|
||||
#ifdef TEST_MODE
|
||||
case SIP_EVT_WAKEUP: {
|
||||
u8 check_str[12];
|
||||
struct sip_evt_wakeup* wakeup_evt= (struct sip_evt_wakeup *)(buf + SIP_CTRL_HDR_LEN);
|
||||
sprintf((char *)&check_str, "%d", wakeup_evt->check_data);
|
||||
esp_test_cmd_event(TEST_CMD_WAKEUP, (char *)&check_str);
|
||||
break;
|
||||
}
|
||||
|
||||
case SIP_EVT_DEBUG: {
|
||||
u8 check_str[640];
|
||||
sip_parse_event_debug(sip->epub, buf, check_str);
|
||||
esp_dbg(ESP_DBG_TRACE, "%s", check_str);
|
||||
esp_test_cmd_event(TEST_CMD_DEBUG, (char *)&check_str);
|
||||
break;
|
||||
}
|
||||
|
||||
case SIP_EVT_LOOPBACK: {
|
||||
u8 check_str[12];
|
||||
struct sip_evt_loopback *loopback_evt = (struct sip_evt_loopback *)(buf + SIP_CTRL_HDR_LEN);
|
||||
esp_dbg(ESP_DBG_LOG, "%s loopback len %d seq %u\n", __func__,hdr->len, hdr->seq);
|
||||
|
||||
if(loopback_evt->pack_id!=get_loopback_id()) {
|
||||
sprintf((char *)&check_str, "seq id error %d, expect %d", loopback_evt->pack_id, get_loopback_id());
|
||||
esp_test_cmd_event(TEST_CMD_LOOPBACK, (char *)&check_str);
|
||||
}
|
||||
|
||||
if((loopback_evt->pack_id+1) <get_loopback_num()) {
|
||||
inc_loopback_id();
|
||||
sip_send_loopback_mblk(sip, loopback_evt->txlen, loopback_evt->rxlen, get_loopback_id());
|
||||
} else {
|
||||
sprintf((char *)&check_str, "test over!");
|
||||
sp_test_cmd_event(TEST_CMD_LOOPBACK, (char *)&check_str);
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif /*TEST_MODE*/
|
||||
|
||||
case SIP_EVT_SNPRINTF_TO_HOST: {
|
||||
u8 *p = (buf + sizeof(struct sip_hdr) + sizeof(u16));
|
||||
u16 *len = (u16 *)(buf + sizeof(struct sip_hdr));
|
||||
char test_res_str[560];
|
||||
sprintf(test_res_str, "esp_host:%llx\nesp_target: %.*s", DRIVER_VER, *len, p);
|
||||
|
||||
esp_dbg(ESP_SHOW, "%s\n", test_res_str);
|
||||
|
||||
if(*len && sip->epub->sdio_state == ESP_SDIO_STATE_FIRST_INIT){
|
||||
char filename[256];
|
||||
if (mod_eagle_path_get() == NULL)
|
||||
sprintf(filename, "%s/%s", FWPATH, "test_results");
|
||||
else
|
||||
sprintf(filename, "%s/%s", mod_eagle_path_get(), "test_results");
|
||||
esp_readwrite_file(filename, NULL, test_res_str, strlen(test_res_str));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SIP_EVT_TRC_AMPDU: {
|
||||
struct sip_evt_trc_ampdu *ep = (struct sip_evt_trc_ampdu*)(buf + SIP_CTRL_HDR_LEN);
|
||||
struct esp_node *node = NULL;
|
||||
int i = 0;
|
||||
|
||||
if (atomic_read(&sip->epub->wl.off)) {
|
||||
esp_dbg(ESP_DBG_ERROR, "%s scan result while wlan off\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
node = esp_get_node_by_addr(sip->epub, ep->addr);
|
||||
if(node == NULL)
|
||||
break;
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (ep->tid & (1<<i)) {
|
||||
esp_tx_ba_session_op(sip, node, ep->state, i);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef TEST_MODE
|
||||
case SIP_EVT_EP: {
|
||||
char *ep = (char *)(buf + SIP_CTRL_HDR_LEN);
|
||||
static int counter = 0;
|
||||
|
||||
esp_dbg(ESP_ATE, "%s EVT_EP \n\n", __func__);
|
||||
if (counter++ < 2) {
|
||||
esp_dbg(ESP_ATE, "ATE: %s \n", ep);
|
||||
}
|
||||
|
||||
esp_test_ate_done_cb(ep);
|
||||
|
||||
break;
|
||||
}
|
||||
#endif /*TEST_MODE*/
|
||||
|
||||
case SIP_EVT_INIT_EP: {
|
||||
char *ep = (char *)(buf + SIP_CTRL_HDR_LEN);
|
||||
esp_dbg(ESP_ATE, "Phy Init: %s \n", ep);
|
||||
break;
|
||||
}
|
||||
|
||||
case SIP_EVT_NOISEFLOOR:{
|
||||
struct sip_evt_noisefloor *ep = (struct sip_evt_noisefloor *)(buf + SIP_CTRL_HDR_LEN);
|
||||
atomic_set(&sip->noise_floor, ep->noise_floor);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAS_INIT_DATA
|
||||
#include "esp_init_data.h"
|
||||
#else
|
||||
#define ESP_INIT_NAME "esp_init_data.bin"
|
||||
#endif /* HAS_INIT_DATA */
|
||||
|
||||
void sip_send_chip_init(struct esp_sip *sip)
|
||||
{
|
||||
size_t size = 0;
|
||||
#ifndef HAS_INIT_DATA
|
||||
const struct firmware *fw_entry;
|
||||
u8 * esp_init_data = NULL;
|
||||
int ret = 0;
|
||||
|
||||
ret = esp_request_firmware(&fw_entry, ESP_INIT_NAME, sip->epub->dev);
|
||||
|
||||
if (ret) {
|
||||
esp_dbg(ESP_DBG_ERROR, "%s =============ERROR! NO INIT DATA!!=================\n", __func__);
|
||||
return;
|
||||
}
|
||||
esp_init_data = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);
|
||||
|
||||
size = fw_entry->size;
|
||||
|
||||
esp_release_firmware(fw_entry);
|
||||
|
||||
if (esp_init_data == NULL) {
|
||||
esp_dbg(ESP_DBG_ERROR, "%s =============ERROR! NO MEMORY!!=================\n", __func__);
|
||||
return;
|
||||
}
|
||||
#else
|
||||
size = sizeof(esp_init_data);
|
||||
|
||||
#endif /* !HAS_INIT_DATA */
|
||||
|
||||
fix_init_data(esp_init_data, size);
|
||||
|
||||
atomic_sub(1, &sip->tx_credits);
|
||||
|
||||
sip_send_cmd(sip, SIP_CMD_INIT, size, (void *)esp_init_data);
|
||||
|
||||
#ifndef HAS_INIT_DATA
|
||||
kfree(esp_init_data);
|
||||
#endif /* !HAS_INIT_DATA */
|
||||
}
|
||||
|
||||
int sip_send_config(struct esp_pub *epub, struct ieee80211_conf * conf)
|
||||
{
|
||||
struct sk_buff *skb = NULL;
|
||||
struct sip_cmd_config *configcmd;
|
||||
|
||||
skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_config) + sizeof(struct sip_hdr), SIP_CMD_CONFIG);
|
||||
if (!skb)
|
||||
return -EINVAL;
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
|
||||
esp_dbg(ESP_DBG_TRACE, "%s config center freq %d\n", __func__, conf->chandef.chan->center_freq);
|
||||
#else
|
||||
esp_dbg(ESP_DBG_TRACE, "%s config center freq %d\n", __func__, conf->channel->center_freq);
|
||||
#endif
|
||||
configcmd = (struct sip_cmd_config *)(skb->data + sizeof(struct sip_hdr));
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
|
||||
configcmd->center_freq= conf->chandef.chan->center_freq;
|
||||
#else
|
||||
configcmd->center_freq= conf->channel->center_freq;
|
||||
#endif
|
||||
configcmd->duration= 0;
|
||||
return sip_cmd_enqueue(epub->sip, skb, ENQUEUE_PRIOR_TAIL);
|
||||
}
|
||||
|
||||
int sip_send_bss_info_update(struct esp_pub *epub, struct esp_vif *evif, u8 *bssid, int assoc)
|
||||
{
|
||||
struct sk_buff *skb = NULL;
|
||||
struct sip_cmd_bss_info_update*bsscmd;
|
||||
|
||||
skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_bss_info_update) + sizeof(struct sip_hdr), SIP_CMD_BSS_INFO_UPDATE);
|
||||
if (!skb)
|
||||
return -EINVAL;
|
||||
|
||||
bsscmd = (struct sip_cmd_bss_info_update *)(skb->data + sizeof(struct sip_hdr));
|
||||
if (assoc == 2) { //hack for softAP mode
|
||||
bsscmd->beacon_int = evif->beacon_interval;
|
||||
} else if (assoc == 1) {
|
||||
set_bit(ESP_WL_FLAG_CONNECT, &epub->wl.flags);
|
||||
} else {
|
||||
clear_bit(ESP_WL_FLAG_CONNECT, &epub->wl.flags);
|
||||
}
|
||||
bsscmd->bssid_no = evif->index;
|
||||
bsscmd->isassoc= assoc;
|
||||
bsscmd->beacon_int = evif->beacon_interval;
|
||||
memcpy(bsscmd->bssid, bssid, ETH_ALEN);
|
||||
return sip_cmd_enqueue(epub->sip, skb, ENQUEUE_PRIOR_TAIL);
|
||||
}
|
||||
|
||||
int sip_send_wmm_params(struct esp_pub *epub, u8 aci, const struct ieee80211_tx_queue_params *params)
|
||||
{
|
||||
struct sk_buff *skb = NULL;
|
||||
struct sip_cmd_set_wmm_params* bsscmd;
|
||||
skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_set_wmm_params) + sizeof(struct sip_hdr), SIP_CMD_SET_WMM_PARAM);
|
||||
if (!skb)
|
||||
return -EINVAL;
|
||||
|
||||
bsscmd = (struct sip_cmd_set_wmm_params *)(skb->data + sizeof(struct sip_hdr));
|
||||
bsscmd->aci= aci;
|
||||
bsscmd->aifs=params->aifs;
|
||||
bsscmd->txop_us=params->txop*32;
|
||||
|
||||
bsscmd->ecw_min = 32 - __builtin_clz(params->cw_min);
|
||||
bsscmd->ecw_max= 32 -__builtin_clz(params->cw_max);
|
||||
|
||||
return sip_cmd_enqueue(epub->sip, skb, ENQUEUE_PRIOR_TAIL);
|
||||
}
|
||||
|
||||
int sip_send_ampdu_action(struct esp_pub *epub, u8 action_num, const u8 * addr, u16 tid, u16 ssn, u8 buf_size)
|
||||
{
|
||||
int index = 0;
|
||||
struct sk_buff *skb = NULL;
|
||||
struct sip_cmd_ampdu_action * action;
|
||||
if(action_num == SIP_AMPDU_RX_START){
|
||||
index = esp_get_empty_rxampdu(epub, addr, tid);
|
||||
} else if(action_num == SIP_AMPDU_RX_STOP){
|
||||
index = esp_get_exist_rxampdu(epub, addr, tid);
|
||||
}
|
||||
if(index < 0)
|
||||
return -EACCES;
|
||||
skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_ampdu_action) + sizeof(struct sip_hdr), SIP_CMD_AMPDU_ACTION);
|
||||
if(!skb)
|
||||
return -EINVAL;
|
||||
|
||||
action = (struct sip_cmd_ampdu_action *)(skb->data + sizeof(struct sip_hdr));
|
||||
action->action = action_num;
|
||||
//for TX, it means interface index
|
||||
action->index = ssn;
|
||||
|
||||
switch(action_num) {
|
||||
case SIP_AMPDU_RX_START:
|
||||
action->ssn = ssn;
|
||||
case SIP_AMPDU_RX_STOP:
|
||||
action->index = index;
|
||||
case SIP_AMPDU_TX_OPERATIONAL:
|
||||
case SIP_AMPDU_TX_STOP:
|
||||
action->win_size = buf_size;
|
||||
action->tid = tid;
|
||||
memcpy(action->addr, addr, ETH_ALEN);
|
||||
break;
|
||||
}
|
||||
|
||||
return sip_cmd_enqueue(epub->sip, skb, ENQUEUE_PRIOR_TAIL);
|
||||
}
|
||||
|
||||
#ifdef HW_SCAN
|
||||
/*send cmd to target, if aborted is true, inform target stop scan, report scan complete imediately
|
||||
return 1: complete over, 0: success, still have next scan, -1: hardware failure
|
||||
*/
|
||||
int sip_send_scan(struct esp_pub *epub)
|
||||
{
|
||||
struct cfg80211_scan_request *scan_req = epub->wl.scan_req;
|
||||
struct sk_buff *skb = NULL;
|
||||
struct sip_cmd_scan *scancmd;
|
||||
u8 *ptr = NULL;
|
||||
int i;
|
||||
u8 append_len, ssid_len;
|
||||
|
||||
ESSERT(scan_req != NULL);
|
||||
ssid_len = scan_req->n_ssids == 0 ? 0:
|
||||
(scan_req->n_ssids == 1 ? scan_req->ssids->ssid_len: scan_req->ssids->ssid_len + (scan_req->ssids + 1)->ssid_len);
|
||||
append_len = ssid_len + scan_req->n_channels + scan_req->ie_len;
|
||||
|
||||
skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_scan) + sizeof(struct sip_hdr) + append_len, SIP_CMD_SCAN);
|
||||
|
||||
if (!skb)
|
||||
return -EINVAL;
|
||||
|
||||
ptr = skb->data;
|
||||
scancmd = (struct sip_cmd_scan *)(ptr + sizeof(struct sip_hdr));
|
||||
ptr += sizeof(struct sip_hdr);
|
||||
|
||||
scancmd->aborted= false;
|
||||
|
||||
if (scancmd->aborted==false) {
|
||||
ptr += sizeof(struct sip_cmd_scan);
|
||||
if (scan_req->n_ssids <=0 || (scan_req->n_ssids == 1&& ssid_len == 0)) {
|
||||
scancmd->ssid_len = 0;
|
||||
} else {
|
||||
scancmd->ssid_len = ssid_len;
|
||||
if(scan_req->ssids->ssid_len == ssid_len)
|
||||
memcpy(ptr, scan_req->ssids->ssid, scancmd->ssid_len);
|
||||
else
|
||||
memcpy(ptr, (scan_req->ssids + 1)->ssid, scancmd->ssid_len);
|
||||
}
|
||||
|
||||
ptr += scancmd->ssid_len;
|
||||
scancmd->n_channels=scan_req->n_channels;
|
||||
for (i=0; i<scan_req->n_channels; i++)
|
||||
ptr[i] = scan_req->channels[i]->hw_value;
|
||||
|
||||
ptr += scancmd->n_channels;
|
||||
if (scan_req->ie_len && scan_req->ie != NULL) {
|
||||
scancmd->ie_len=scan_req->ie_len;
|
||||
memcpy(ptr, scan_req->ie, scan_req->ie_len);
|
||||
} else {
|
||||
scancmd->ie_len = 0;
|
||||
}
|
||||
//add a flag that support two ssids,
|
||||
if(scan_req->n_ssids > 1)
|
||||
scancmd->ssid_len |= 0x80;
|
||||
|
||||
}
|
||||
|
||||
return sip_cmd_enqueue(epub->sip, skb, ENQUEUE_PRIOR_TAIL);
|
||||
}
|
||||
#endif
|
||||
|
||||
int sip_send_suspend_config(struct esp_pub *epub, u8 suspend)
|
||||
{
|
||||
struct sip_cmd_suspend *cmd = NULL;
|
||||
struct sk_buff *skb = NULL;
|
||||
|
||||
skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_suspend) + sizeof(struct sip_hdr), SIP_CMD_SUSPEND);
|
||||
|
||||
if (!skb)
|
||||
return -EINVAL;
|
||||
|
||||
cmd = (struct sip_cmd_suspend *)(skb->data + sizeof(struct sip_hdr));
|
||||
cmd->suspend = suspend;
|
||||
return sip_cmd_enqueue(epub->sip, skb, ENQUEUE_PRIOR_TAIL);
|
||||
}
|
||||
|
||||
int sip_send_ps_config(struct esp_pub *epub, struct esp_ps *ps)
|
||||
{
|
||||
struct sip_cmd_ps *pscmd = NULL;
|
||||
struct sk_buff *skb = NULL;
|
||||
struct sip_hdr *shdr = NULL;
|
||||
|
||||
skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_ps) + sizeof(struct sip_hdr), SIP_CMD_PS);
|
||||
|
||||
if (!skb)
|
||||
return -EINVAL;
|
||||
|
||||
shdr = (struct sip_hdr *)skb->data;
|
||||
pscmd = (struct sip_cmd_ps *)(skb->data + sizeof(struct sip_hdr));
|
||||
|
||||
pscmd->dtim_period = ps->dtim_period;
|
||||
pscmd->max_sleep_period = ps->max_sleep_period;
|
||||
|
||||
return sip_cmd_enqueue(epub->sip, skb, ENQUEUE_PRIOR_TAIL);
|
||||
}
|
||||
|
||||
void sip_scandone_process(struct esp_sip *sip, struct sip_evt_scan_report *scan_report)
|
||||
{
|
||||
struct esp_pub *epub = sip->epub;
|
||||
|
||||
esp_dbg(ESP_DBG_TRACE, "eagle hw scan report\n");
|
||||
|
||||
if (epub->wl.scan_req) {
|
||||
hw_scan_done(epub, scan_report->aborted);
|
||||
epub->wl.scan_req = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int sip_send_setkey(struct esp_pub *epub, u8 bssid_no, u8 *peer_addr, struct ieee80211_key_conf *key, u8 isvalid)
|
||||
{
|
||||
struct sip_cmd_setkey *setkeycmd;
|
||||
struct sk_buff *skb = NULL;
|
||||
|
||||
skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_setkey) + sizeof(struct sip_hdr), SIP_CMD_SETKEY);
|
||||
|
||||
if (!skb)
|
||||
return -EINVAL;
|
||||
|
||||
setkeycmd = (struct sip_cmd_setkey *)(skb->data + sizeof(struct sip_hdr));
|
||||
|
||||
if (peer_addr) {
|
||||
memcpy(setkeycmd->addr, peer_addr, ETH_ALEN);
|
||||
} else {
|
||||
memset(setkeycmd->addr, 0, ETH_ALEN);
|
||||
}
|
||||
|
||||
setkeycmd->bssid_no = bssid_no;
|
||||
setkeycmd->hw_key_idx= key->hw_key_idx;
|
||||
|
||||
if (isvalid) {
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39))
|
||||
setkeycmd->alg= key->alg;
|
||||
#else
|
||||
setkeycmd->alg= esp_cipher2alg(key->cipher);
|
||||
#endif /* NEW_KERNEL */
|
||||
setkeycmd->keyidx = key->keyidx;
|
||||
setkeycmd->keylen = key->keylen;
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39))
|
||||
if (key->alg == ALG_TKIP) {
|
||||
#else
|
||||
if (key->cipher == WLAN_CIPHER_SUITE_TKIP) {
|
||||
#endif /* NEW_KERNEL */
|
||||
memcpy(setkeycmd->key, key->key, 16);
|
||||
memcpy(setkeycmd->key+16,key->key+24,8);
|
||||
memcpy(setkeycmd->key+24,key->key+16,8);
|
||||
} else {
|
||||
memcpy(setkeycmd->key, key->key, key->keylen);
|
||||
}
|
||||
|
||||
setkeycmd->flags=1;
|
||||
} else {
|
||||
setkeycmd->flags=0;
|
||||
}
|
||||
return sip_cmd_enqueue(epub->sip, skb, ENQUEUE_PRIOR_TAIL);
|
||||
}
|
||||
|
||||
#ifdef FPGA_LOOPBACK
|
||||
#define LOOPBACK_PKT_LEN 200
|
||||
int sip_send_loopback_cmd_mblk(struct esp_sip *sip)
|
||||
{
|
||||
int cnt, ret;
|
||||
|
||||
for (cnt = 0; cnt < 4; cnt++) {
|
||||
if (0!=(ret=sip_send_loopback_mblk(sip, LOOPBACK_PKT_LEN, LOOPBACK_PKT_LEN, 0)))
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* FPGA_LOOPBACK */
|
||||
|
||||
int sip_send_loopback_mblk(struct esp_sip *sip, int txpacket_len, int rxpacket_len, int packet_id)
|
||||
{
|
||||
struct sk_buff *skb = NULL;
|
||||
struct sip_cmd_loopback *cmd;
|
||||
u8 *ptr = NULL;
|
||||
int i, ret;
|
||||
|
||||
//send 100 loopback pkt
|
||||
if(txpacket_len)
|
||||
skb = sip_alloc_ctrl_skbuf(sip, sizeof(struct sip_cmd_loopback) + sizeof(struct sip_hdr) + txpacket_len, SIP_CMD_LOOPBACK);
|
||||
else
|
||||
skb = sip_alloc_ctrl_skbuf(sip, sizeof(struct sip_cmd_loopback) + sizeof(struct sip_hdr), SIP_CMD_LOOPBACK);
|
||||
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
ptr = skb->data;
|
||||
cmd = (struct sip_cmd_loopback *)(ptr + sizeof(struct sip_hdr));
|
||||
ptr += sizeof(struct sip_hdr);
|
||||
cmd->txlen = txpacket_len;
|
||||
cmd->rxlen = rxpacket_len;
|
||||
cmd->pack_id = packet_id;
|
||||
|
||||
if (txpacket_len) {
|
||||
ptr += sizeof(struct sip_cmd_loopback);
|
||||
/* fill up pkt payload */
|
||||
for (i = 0; i < txpacket_len; i++) {
|
||||
ptr[i] = i;
|
||||
}
|
||||
}
|
||||
|
||||
ret = sip_cmd_enqueue(sip, skb, ENQUEUE_PRIOR_TAIL);
|
||||
if (ret <0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//remain_on_channel
|
||||
int sip_send_roc(struct esp_pub *epub, u16 center_freq, u16 duration)
|
||||
{
|
||||
struct sk_buff *skb = NULL;
|
||||
struct sip_cmd_config *configcmd;
|
||||
|
||||
skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_config) + sizeof(struct sip_hdr), SIP_CMD_CONFIG);
|
||||
if (!skb)
|
||||
return -EINVAL;
|
||||
|
||||
configcmd = (struct sip_cmd_config *)(skb->data + sizeof(struct sip_hdr));
|
||||
configcmd->center_freq= center_freq;
|
||||
configcmd->duration= duration;
|
||||
return sip_cmd_enqueue(epub->sip, skb, ENQUEUE_PRIOR_TAIL);
|
||||
}
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
|
||||
int sip_send_set_sta(struct esp_pub *epub, u8 ifidx, u8 set, struct ieee80211_sta *sta, struct ieee80211_vif *vif, u8 index)
|
||||
#else
|
||||
int sip_send_set_sta(struct esp_pub *epub, u8 ifidx, u8 set, struct esp_node *node, struct ieee80211_vif *vif, u8 index)
|
||||
#endif
|
||||
{
|
||||
struct sk_buff *skb = NULL;
|
||||
struct sip_cmd_setsta *setstacmd;
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28))
|
||||
struct ieee80211_ht_info ht_info = node->ht_info;
|
||||
#endif
|
||||
skb = sip_alloc_ctrl_skbuf(epub->sip, sizeof(struct sip_cmd_setsta) + sizeof(struct sip_hdr), SIP_CMD_SETSTA);
|
||||
if (!skb)
|
||||
return -EINVAL;
|
||||
|
||||
setstacmd = (struct sip_cmd_setsta *)(skb->data + sizeof(struct sip_hdr));
|
||||
setstacmd->ifidx = ifidx;
|
||||
setstacmd->index = index;
|
||||
setstacmd->set = set;
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
|
||||
if(sta->aid == 0)
|
||||
setstacmd->aid = vif->bss_conf.aid;
|
||||
else
|
||||
setstacmd->aid = sta->aid;
|
||||
memcpy(setstacmd->mac, sta->addr, ETH_ALEN);
|
||||
if(set){
|
||||
if(sta->ht_cap.ht_supported){
|
||||
if(sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20)
|
||||
setstacmd->phymode = ESP_IEEE80211_T_HT20_S;
|
||||
else
|
||||
setstacmd->phymode = ESP_IEEE80211_T_HT20_L;
|
||||
setstacmd->ampdu_factor = sta->ht_cap.ampdu_factor;
|
||||
setstacmd->ampdu_density = sta->ht_cap.ampdu_density;
|
||||
} else {
|
||||
if(sta->supp_rates[IEEE80211_BAND_2GHZ] & (~(u32)CONF_HW_BIT_RATE_11B_MASK)){
|
||||
setstacmd->phymode = ESP_IEEE80211_T_OFDM;
|
||||
} else {
|
||||
setstacmd->phymode = ESP_IEEE80211_T_CCK;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
setstacmd->aid = node->aid;
|
||||
memcpy(setstacmd->mac, node->addr, ETH_ALEN);
|
||||
if(set){
|
||||
if(ht_info.ht_supported){
|
||||
if(ht_info.cap & IEEE80211_HT_CAP_SGI_20)
|
||||
setstacmd->phymode = ESP_IEEE80211_T_HT20_S;
|
||||
else
|
||||
setstacmd->phymode = ESP_IEEE80211_T_HT20_L;
|
||||
setstacmd->ampdu_factor = ht_info.ampdu_factor;
|
||||
setstacmd->ampdu_density = ht_info.ampdu_density;
|
||||
} else {
|
||||
//note supp_rates is u64[] in 2.6.27
|
||||
if(node->supp_rates[IEEE80211_BAND_2GHZ] & (~(u64)CONF_HW_BIT_RATE_11B_MASK)){
|
||||
setstacmd->phymode = ESP_IEEE80211_T_OFDM;
|
||||
} else {
|
||||
setstacmd->phymode = ESP_IEEE80211_T_CCK;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return sip_cmd_enqueue(epub->sip, skb, ENQUEUE_PRIOR_TAIL);
|
||||
}
|
||||
|
||||
int sip_send_recalc_credit(struct esp_pub *epub)
|
||||
{
|
||||
struct sk_buff *skb = NULL;
|
||||
|
||||
skb = sip_alloc_ctrl_skbuf(epub->sip, 0 + sizeof(struct sip_hdr), SIP_CMD_RECALC_CREDIT);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
return sip_cmd_enqueue(epub->sip, skb, ENQUEUE_PRIOR_HEAD);
|
||||
}
|
||||
|
||||
int sip_cmd(struct esp_pub *epub, enum sip_cmd_id cmd_id, u8 *cmd_buf, u8 cmd_len)
|
||||
{
|
||||
struct sk_buff *skb = NULL;
|
||||
|
||||
skb = sip_alloc_ctrl_skbuf(epub->sip, cmd_len + sizeof(struct sip_hdr), cmd_id);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(skb->data + sizeof(struct sip_hdr), cmd_buf, cmd_len);
|
||||
|
||||
return sip_cmd_enqueue(epub->sip, skb, ENQUEUE_PRIOR_TAIL);
|
||||
}
|
||||
54
drivers/net/wireless/esp8089/esp_ctrl.h
Executable file
54
drivers/net/wireless/esp8089/esp_ctrl.h
Executable file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2009- 2014 Espressif System.
|
||||
*
|
||||
* SIP ctrl packet parse and pack
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
#ifndef _ESP_CTRL_H_
|
||||
#define _ESP_CTRL_H_
|
||||
|
||||
int sip_send_loopback_mblk(struct esp_sip *sip, int txpacket_len, int rxpacket_len, int packet_id);
|
||||
|
||||
int sip_send_config(struct esp_pub *epub, struct ieee80211_conf * conf);
|
||||
|
||||
int sip_send_setkey(struct esp_pub *epub, u8 bssid_no, u8 *peer_addr, struct ieee80211_key_conf *key, u8 isvalid);
|
||||
|
||||
int sip_send_scan(struct esp_pub *epub);
|
||||
|
||||
void sip_scandone_process(struct esp_sip *sip, struct sip_evt_scan_report *scan_report);
|
||||
|
||||
int sip_send_bss_info_update(struct esp_pub *epub, struct esp_vif *evif, u8 *bssid, int assoc);
|
||||
|
||||
int sip_send_wmm_params(struct esp_pub *epub, u8 aci, const struct ieee80211_tx_queue_params *params);
|
||||
|
||||
int sip_send_ampdu_action(struct esp_pub *epub, u8 action_num, const u8 * addr, u16 tid, u16 ssn, u8 buf_size);
|
||||
|
||||
int sip_send_roc(struct esp_pub *epub, u16 center_freq, u16 duration);
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
|
||||
int sip_send_set_sta(struct esp_pub *epub, u8 ifidx, u8 set, struct ieee80211_sta *sta, struct ieee80211_vif *vif, u8 index);
|
||||
#else
|
||||
int sip_send_set_sta(struct esp_pub *epub, u8 ifidx, u8 set, struct esp_node *node, struct ieee80211_vif *vif, u8 index);
|
||||
#endif
|
||||
|
||||
int sip_send_suspend_config(struct esp_pub *epub, u8 suspend);
|
||||
|
||||
int sip_send_ps_config(struct esp_pub *epub, struct esp_ps *ps);
|
||||
|
||||
int sip_parse_events(struct esp_sip *sip, u8 *buf);
|
||||
|
||||
int sip_send_recalc_credit(struct esp_pub *epub);
|
||||
|
||||
int sip_cmd(struct esp_pub *epub, enum sip_cmd_id cmd_id, u8 *cmd_buf, u8 cmd_len);
|
||||
|
||||
#endif /* _ESP_CTRL_H_ */
|
||||
|
||||
304
drivers/net/wireless/esp8089/esp_debug.c
Executable file
304
drivers/net/wireless/esp8089/esp_debug.c
Executable file
@@ -0,0 +1,304 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2014 Espressif System.
|
||||
*
|
||||
* esp debug interface
|
||||
* - debugfs
|
||||
* - debug level control
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#include <net/mac80211.h>
|
||||
#include "sip2_common.h"
|
||||
|
||||
#include "esp_debug.h"
|
||||
|
||||
#if defined(CONFIG_DEBUG_FS) && defined(DEBUG_FS)
|
||||
|
||||
static struct dentry *esp_debugfs_root = NULL;
|
||||
|
||||
static int esp_debugfs_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
filp->private_data = inode->i_private;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t esp_debugfs_read(struct file *filp, char __user *buffer,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
if (*ppos >= 32)
|
||||
return 0;
|
||||
if (*ppos + count > 32)
|
||||
count = 32 - *ppos;
|
||||
|
||||
if (copy_to_user(buffer, filp->private_data + *ppos, count))
|
||||
return -EFAULT;
|
||||
|
||||
*ppos += count;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t esp_debugfs_write(struct file *filp, const char __user *buffer,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
if (*ppos >= 32)
|
||||
return 0;
|
||||
if (*ppos + count > 32)
|
||||
count = 32 - *ppos;
|
||||
|
||||
if (copy_from_user(filp->private_data + *ppos, buffer, count))
|
||||
return -EFAULT;
|
||||
|
||||
*ppos += count;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
struct file_operations esp_debugfs_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = esp_debugfs_open,
|
||||
.read = esp_debugfs_read,
|
||||
.write = esp_debugfs_write,
|
||||
};
|
||||
|
||||
|
||||
struct dentry *esp_dump_var(const char *name, struct dentry *parent, void *value, esp_type type) {
|
||||
struct dentry *rc = NULL;
|
||||
umode_t mode = 0644;
|
||||
|
||||
if(!esp_debugfs_root)
|
||||
return NULL;
|
||||
|
||||
if(!parent)
|
||||
parent = esp_debugfs_root;
|
||||
|
||||
switch(type) {
|
||||
case ESP_U8:
|
||||
rc = debugfs_create_u8(name, mode, parent, (u8*)value);
|
||||
break;
|
||||
case ESP_U16:
|
||||
rc = debugfs_create_u16(name, mode, parent, (u16*)value);
|
||||
break;
|
||||
case ESP_U32:
|
||||
rc = debugfs_create_u32(name, mode, parent, (u32*)value);
|
||||
break;
|
||||
case ESP_U64:
|
||||
rc = debugfs_create_u64(name, mode, parent, (u64*)value);
|
||||
break;
|
||||
case ESP_BOOL:
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0))
|
||||
rc = debugfs_create_bool(name, mode, parent, (u32*)value);
|
||||
#else
|
||||
rc = debugfs_create_bool(name, mode, parent, (bool*)value);
|
||||
#endif
|
||||
break;
|
||||
default: //32
|
||||
rc = debugfs_create_u32(name, mode, parent, (u32*)value);
|
||||
}
|
||||
|
||||
if (!rc)
|
||||
goto Fail;
|
||||
else
|
||||
return rc;
|
||||
Fail:
|
||||
debugfs_remove_recursive(esp_debugfs_root);
|
||||
esp_debugfs_root = NULL;
|
||||
esp_dbg(ESP_DBG_ERROR, "%s failed, debugfs root removed; var name: %s\n", __FUNCTION__, name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct dentry *esp_dump_array(const char *name, struct dentry *parent, struct debugfs_blob_wrapper *blob) {
|
||||
struct dentry * rc = NULL;
|
||||
umode_t mode = 0644;
|
||||
|
||||
if(!esp_debugfs_root)
|
||||
return NULL;
|
||||
|
||||
if(!parent)
|
||||
parent = esp_debugfs_root;
|
||||
|
||||
rc = debugfs_create_blob(name, mode, parent, blob);
|
||||
|
||||
if (!rc)
|
||||
goto Fail;
|
||||
else
|
||||
return rc;
|
||||
|
||||
Fail:
|
||||
debugfs_remove_recursive(esp_debugfs_root);
|
||||
esp_debugfs_root = NULL;
|
||||
esp_dbg(ESP_DBG_ERROR, "%s failed, debugfs root removed; var name: %s\n", __FUNCTION__, name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct dentry *esp_dump(const char *name, struct dentry *parent, void *data, int size) {
|
||||
struct dentry *rc;
|
||||
umode_t mode = 0644;
|
||||
|
||||
if(!esp_debugfs_root)
|
||||
return NULL;
|
||||
|
||||
if(!parent)
|
||||
parent = esp_debugfs_root;
|
||||
|
||||
rc = debugfs_create_file(name, mode, parent, data, &esp_debugfs_fops);
|
||||
|
||||
if (!rc)
|
||||
goto Fail;
|
||||
else
|
||||
return rc;
|
||||
|
||||
Fail:
|
||||
debugfs_remove_recursive(esp_debugfs_root);
|
||||
esp_debugfs_root = NULL;
|
||||
esp_dbg(ESP_DBG_ERROR, "%s failed, debugfs root removed; var name: %s\n", __FUNCTION__, name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct dentry *esp_debugfs_add_sub_dir(const char *name) {
|
||||
struct dentry *sub_dir = NULL;
|
||||
|
||||
sub_dir = debugfs_create_dir(name, esp_debugfs_root);
|
||||
|
||||
if (!sub_dir)
|
||||
goto Fail;
|
||||
|
||||
return sub_dir;
|
||||
|
||||
Fail:
|
||||
debugfs_remove_recursive(esp_debugfs_root);
|
||||
esp_debugfs_root = NULL;
|
||||
esp_dbg(ESP_DBG_ERROR, "%s failed, debugfs root removed; dir name: %s\n", __FUNCTION__, name);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
int esp_debugfs_init(void)
|
||||
{
|
||||
esp_dbg(ESP_DBG, "esp debugfs init\n");
|
||||
esp_debugfs_root = debugfs_create_dir("esp_debug", NULL);
|
||||
|
||||
if (!esp_debugfs_root || IS_ERR_OR_NULL(esp_debugfs_root)) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void esp_debugfs_exit(void)
|
||||
{
|
||||
esp_dbg(ESP_DBG, "esp debugfs exit");
|
||||
|
||||
debugfs_remove_recursive(esp_debugfs_root);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
inline struct dentry *esp_dump_var(const char *name, struct dentry *parent, void *value, esp_type type) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inline struct dentry *esp_dump_array(const char *name, struct dentry *parent, struct debugfs_blob_wrapper *blob) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inline struct dentry *esp_dump(const char *name, struct dentry *parent, void *data, int size) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct dentry *esp_debugfs_add_sub_dir(const char *name) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inline int esp_debugfs_init(void)
|
||||
{
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
inline void esp_debugfs_exit(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
void show_buf(u8 *buf, u32 len)
|
||||
{
|
||||
// print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 16, 1, buf, len, true);
|
||||
#if 1
|
||||
int i = 0, j;
|
||||
|
||||
printk(KERN_INFO "\n++++++++++++++++show rbuf+++++++++++++++\n");
|
||||
for (i = 0; i < (len / 16); i++) {
|
||||
j = i * 16;
|
||||
printk(KERN_INFO "0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x \n", buf[j], buf[j+1],buf[j+2],buf[j+3],buf[j+4],buf[j+5],buf[j+6],buf[j+7],buf[j+8],buf[j+9],buf[j+10],buf[j+11],buf[j+12],buf[j+13],buf[j+14],buf[j+15]);
|
||||
}
|
||||
printk(KERN_INFO "\n++++++++++++++++++++++++++++++++++++++++\n");
|
||||
#endif//0000
|
||||
}
|
||||
|
||||
#ifdef HOST_RC
|
||||
static u8 get_cnt(u32 cnt_store, int idx)
|
||||
{
|
||||
int shift = idx << 2;
|
||||
|
||||
return (u8)((cnt_store>>shift) & 0xf);
|
||||
}
|
||||
|
||||
void esp_show_rcstatus(struct sip_rc_status *rcstatus)
|
||||
{
|
||||
int i;
|
||||
char msg[82];
|
||||
char rcstr[16];
|
||||
u32 cnt_store = rcstatus->rc_cnt_store;
|
||||
|
||||
memset(msg, 0 ,sizeof(msg));
|
||||
memset(rcstr, 0 ,sizeof(rcstr));
|
||||
|
||||
printk(KERN_INFO "rcstatus map 0x%08x cntStore 0x%08x\n", rcstatus->rc_map, rcstatus->rc_cnt_store);
|
||||
|
||||
for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
|
||||
if (rcstatus->rc_map & BIT(i)) {
|
||||
sprintf(rcstr, "rcIdx %d, cnt %d ", i, get_cnt(cnt_store, i));
|
||||
strcat(msg, rcstr);
|
||||
}
|
||||
}
|
||||
printk(KERN_INFO "%s \n", msg);
|
||||
}
|
||||
|
||||
void esp_show_tx_rates(struct ieee80211_tx_rate* rates)
|
||||
{
|
||||
int i;
|
||||
char msg[128];
|
||||
char rcstr[32];
|
||||
|
||||
memset(msg, 0 ,sizeof(msg));
|
||||
memset(rcstr, 0 ,sizeof(rcstr));
|
||||
|
||||
for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
|
||||
if (rates->idx != -1 ) {
|
||||
sprintf(rcstr, "Idx %d, cnt %d, flag %02x ", rates->idx, rates->count, rates->flags);
|
||||
strcat(msg, rcstr);
|
||||
}
|
||||
rates++;
|
||||
}
|
||||
strcat(msg, "\n");
|
||||
printk(KERN_INFO "%s \n", msg);
|
||||
}
|
||||
#endif /* HOST_RC */
|
||||
98
drivers/net/wireless/esp8089/esp_debug.h
Executable file
98
drivers/net/wireless/esp8089/esp_debug.h
Executable file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2014 Espressif System.
|
||||
*
|
||||
* esp debug
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef _DEBUG_H_
|
||||
|
||||
#ifdef ASSERT_PANIC
|
||||
#define ESSERT(v) BUG_ON(!(v))
|
||||
#else
|
||||
#define ESSERT(v) if(!(v)) printk("ESSERT:%s %d\n", __FILE__, __LINE__)
|
||||
#endif
|
||||
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
typedef enum esp_type {
|
||||
ESP_BOOL,
|
||||
ESP_U8,
|
||||
ESP_U16,
|
||||
ESP_U32,
|
||||
ESP_U64
|
||||
} esp_type;
|
||||
|
||||
struct dentry *esp_dump_var(const char *name, struct dentry *parent, void *value, esp_type type);
|
||||
|
||||
struct dentry *esp_dump_array(const char *name, struct dentry *parent, struct debugfs_blob_wrapper *blob);
|
||||
|
||||
struct dentry *esp_dump(const char *name, struct dentry *parent, void *data, int size);
|
||||
|
||||
struct dentry *esp_debugfs_add_sub_dir(const char *name);
|
||||
|
||||
int esp_debugfs_init(void);
|
||||
|
||||
void esp_debugfs_exit(void);
|
||||
|
||||
enum {
|
||||
ESP_DBG_ERROR = BIT(0),
|
||||
ESP_DBG_TRACE = BIT(1),
|
||||
ESP_DBG_LOG = BIT(2),
|
||||
ESP_DBG = BIT(3),
|
||||
ESP_SHOW = BIT(4),
|
||||
ESP_DBG_TXAMPDU = BIT(5),
|
||||
ESP_DBG_OP = BIT(6),
|
||||
ESP_DBG_PS = BIT(7),
|
||||
ESP_ATE = BIT(8),
|
||||
ESP_DBG_ALL = 0xffffffff
|
||||
};
|
||||
|
||||
extern unsigned int esp_msg_level;
|
||||
|
||||
#ifdef ESP_ANDROID_LOGGER
|
||||
extern bool log_off;
|
||||
#endif /* ESP_ANDROID_LOGGER */
|
||||
|
||||
#ifdef ESP_ANDROID_LOGGER
|
||||
#include "esp_file.h"
|
||||
#define esp_dbg(mask, fmt, args...) do {\
|
||||
if (esp_msg_level & mask) \
|
||||
{ \
|
||||
if (log_off) \
|
||||
printk(fmt, ##args); \
|
||||
else \
|
||||
logger_write(4, "esp_wifi", fmt, ##args);\
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
#define esp_dbg(mask, fmt, args...) do {\
|
||||
if (esp_msg_level & mask) \
|
||||
printk(fmt, ##args); \
|
||||
} while (0)
|
||||
#endif /* ESP_ANDROID_LOGGER */
|
||||
|
||||
void show_buf(u8 *buf, u32 len);
|
||||
|
||||
#ifdef HOST_RC
|
||||
struct sip_rc_status;
|
||||
struct ieee80211_tx_rate;
|
||||
|
||||
void esp_show_rcstatus(struct sip_rc_status *rcstatus);
|
||||
|
||||
void esp_show_tx_rates(struct ieee80211_tx_rate *rates);
|
||||
#endif /* HOST_RC */
|
||||
|
||||
#endif /* _DEBUG_H_ */
|
||||
495
drivers/net/wireless/esp8089/esp_ext.c
Executable file
495
drivers/net/wireless/esp8089/esp_ext.c
Executable file
@@ -0,0 +1,495 @@
|
||||
/*
|
||||
* Copyright (c) 2010 -2013 Espressif System.
|
||||
*
|
||||
* extended gpio
|
||||
* - interface for other driver or kernel
|
||||
* - gpio control
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifdef USE_EXT_GPIO
|
||||
|
||||
#include <net/cfg80211.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/mmc/card.h>
|
||||
#include <linux/mmc/mmc.h>
|
||||
#include <linux/mmc/host.h>
|
||||
#include <linux/mmc/sdio_func.h>
|
||||
#include <linux/mmc/sdio_ids.h>
|
||||
#include <linux/mmc/sdio.h>
|
||||
#include <linux/mmc/sd.h>
|
||||
#include <linux/completion.h>
|
||||
|
||||
#include "esp_ext.h"
|
||||
#include "esp_debug.h"
|
||||
#include "esp_sip.h"
|
||||
#include "esp_sif.h"
|
||||
|
||||
#ifdef EXT_GPIO_OPS
|
||||
extern void register_ext_gpio_ops(struct esp_ext_gpio_ops *ops);
|
||||
extern void unregister_ext_gpio_ops(void);
|
||||
|
||||
static struct esp_ext_gpio_ops ext_gpio_ops = {
|
||||
.gpio_request = ext_gpio_request, /* gpio_request gpio_no from 0x0 to 0xf*/
|
||||
.gpio_release = ext_gpio_release, /* gpio_release */
|
||||
.gpio_set_mode = ext_gpio_set_mode, /* gpio_set_mode, data is irq_func of irq_mode , default level of output_mode */
|
||||
.gpio_get_mode = ext_gpio_get_mode, /* gpio_get_mode, current mode */
|
||||
.gpio_set_state = ext_gpio_set_output_state, /* only output state, high level or low level */
|
||||
.gpio_get_state = ext_gpio_get_state, /* current state */
|
||||
.irq_ack = ext_irq_ack, /* ack interrupt */
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
static struct esp_pub *ext_epub = NULL;
|
||||
|
||||
static u16 intr_mask_reg = 0x0000;
|
||||
struct workqueue_struct *ext_irq_wkq = NULL;
|
||||
struct work_struct ext_irq_work;
|
||||
static struct mutex ext_mutex_lock;
|
||||
|
||||
static struct ext_gpio_info gpio_list[EXT_GPIO_MAX_NUM] = {
|
||||
{ 0, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL},
|
||||
{ 1, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL},
|
||||
{ 2, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL},
|
||||
{ 3, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL},
|
||||
{ 4, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL},
|
||||
{ 5, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL},
|
||||
{ 6, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL},
|
||||
{ 7, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL},
|
||||
{ 8, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL},
|
||||
{ 9, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL},
|
||||
{10, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL},
|
||||
{11, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL},
|
||||
{12, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL},
|
||||
{13, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL},
|
||||
{14, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL},
|
||||
{15, EXT_GPIO_MODE_DISABLE, EXT_GPIO_STATE_IDLE, NULL},
|
||||
};
|
||||
|
||||
static struct pending_intr_list_info esp_pending_intr_list = {
|
||||
.start_pos = 0,
|
||||
.end_pos = 0,
|
||||
.curr_num = 0,
|
||||
};
|
||||
|
||||
u16 ext_gpio_get_int_mask_reg(void)
|
||||
{
|
||||
return intr_mask_reg;
|
||||
}
|
||||
|
||||
int ext_gpio_request(int gpio_no)
|
||||
{
|
||||
if (ext_epub == NULL || ext_epub->sip == NULL ||
|
||||
atomic_read(&ext_epub->sip->state) != SIP_RUN) {
|
||||
esp_dbg(ESP_DBG_ERROR, "%s esp state is not ok\n", __func__);
|
||||
return -ENOTRECOVERABLE;
|
||||
}
|
||||
|
||||
mutex_lock(&ext_mutex_lock);
|
||||
|
||||
if (gpio_no >= EXT_GPIO_MAX_NUM || gpio_no < 0) {
|
||||
mutex_unlock(&ext_mutex_lock);
|
||||
esp_dbg(ESP_DBG_ERROR, "%s unkown gpio num\n", __func__);
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
if (gpio_list[gpio_no].gpio_mode != EXT_GPIO_MODE_DISABLE) {
|
||||
mutex_unlock(&ext_mutex_lock);
|
||||
esp_dbg(ESP_DBG_ERROR, "%s gpio is already in used by other\n", __func__);
|
||||
return -EPERM;
|
||||
} else {
|
||||
gpio_list[gpio_no].gpio_mode = EXT_GPIO_MODE_MAX;
|
||||
mutex_unlock(&ext_mutex_lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(ext_gpio_request);
|
||||
|
||||
int ext_gpio_release(int gpio_no)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (ext_epub == NULL || ext_epub->sip == NULL ||
|
||||
atomic_read(&ext_epub->sip->state) != SIP_RUN) {
|
||||
esp_dbg(ESP_DBG_ERROR, "%s esp state is not ok\n", __func__);
|
||||
return -ENOTRECOVERABLE;
|
||||
}
|
||||
|
||||
mutex_lock(&ext_mutex_lock);
|
||||
|
||||
if (gpio_no >= EXT_GPIO_MAX_NUM || gpio_no < 0) {
|
||||
mutex_unlock(&ext_mutex_lock);
|
||||
esp_dbg(ESP_DBG_ERROR, "%s unkown gpio num\n", __func__);
|
||||
return -ERANGE;
|
||||
}
|
||||
sif_lock_bus(ext_epub);
|
||||
ret = sif_config_gpio_mode(ext_epub, (u8)gpio_no, EXT_GPIO_MODE_DISABLE);
|
||||
sif_unlock_bus(ext_epub);
|
||||
if (ret) {
|
||||
esp_dbg(ESP_DBG_ERROR, "%s gpio release error\n", __func__);
|
||||
mutex_unlock(&ext_mutex_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
gpio_list[gpio_no].gpio_mode = EXT_GPIO_MODE_DISABLE;
|
||||
gpio_list[gpio_no].gpio_state = EXT_GPIO_STATE_IDLE;
|
||||
gpio_list[gpio_no].irq_handler = NULL;
|
||||
intr_mask_reg &= ~(1<<gpio_no);
|
||||
|
||||
mutex_unlock(&ext_mutex_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ext_gpio_release);
|
||||
|
||||
int ext_gpio_set_mode(int gpio_no, int mode, void *data)
|
||||
{
|
||||
u8 gpio_mode;
|
||||
int ret;
|
||||
struct ext_gpio_info backup_info;
|
||||
|
||||
if (ext_epub == NULL || ext_epub->sip == NULL ||
|
||||
atomic_read(&ext_epub->sip->state) != SIP_RUN) {
|
||||
esp_dbg(ESP_DBG_LOG, "%s esp state is not ok\n", __func__);
|
||||
return -ENOTRECOVERABLE;
|
||||
}
|
||||
|
||||
mutex_lock(&ext_mutex_lock);
|
||||
|
||||
if (gpio_no >= EXT_GPIO_MAX_NUM || gpio_no < 0) {
|
||||
mutex_unlock(&ext_mutex_lock);
|
||||
esp_dbg(ESP_DBG_ERROR, "%s unkown gpio num\n", __func__);
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
if (gpio_list[gpio_no].gpio_mode == EXT_GPIO_MODE_DISABLE) {
|
||||
mutex_unlock(&ext_mutex_lock);
|
||||
esp_dbg(ESP_DBG_ERROR, "%s gpio is not in occupy, please request gpio\n", __func__);
|
||||
return -ENOTRECOVERABLE;
|
||||
}
|
||||
|
||||
if (mode <= EXT_GPIO_MODE_OOB || mode >= EXT_GPIO_MODE_MAX) {
|
||||
mutex_unlock(&ext_mutex_lock);
|
||||
esp_dbg(ESP_DBG_ERROR, "%s gpio mode unknown\n", __func__);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
memcpy(&backup_info, &gpio_list[gpio_no], sizeof(struct ext_gpio_info));
|
||||
|
||||
gpio_list[gpio_no].gpio_mode = mode;
|
||||
gpio_mode = (u8)mode;
|
||||
|
||||
switch (mode) {
|
||||
case EXT_GPIO_MODE_INTR_POSEDGE:
|
||||
case EXT_GPIO_MODE_INTR_NEGEDGE:
|
||||
case EXT_GPIO_MODE_INTR_LOLEVEL:
|
||||
case EXT_GPIO_MODE_INTR_HILEVEL:
|
||||
if (!data) {
|
||||
memcpy(&gpio_list[gpio_no], &backup_info, sizeof(struct ext_gpio_info));
|
||||
esp_dbg(ESP_DBG_ERROR, "%s irq_handler is NULL\n", __func__);
|
||||
mutex_unlock(&ext_mutex_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
gpio_list[gpio_no].irq_handler = (ext_irq_handler_t)data;
|
||||
intr_mask_reg |= (1<<gpio_no);
|
||||
break;
|
||||
case EXT_GPIO_MODE_OUTPUT:
|
||||
if (!data) {
|
||||
memcpy(&gpio_list[gpio_no], &backup_info, sizeof(struct ext_gpio_info));
|
||||
esp_dbg(ESP_DBG_ERROR, "%s output default value is NULL\n", __func__);
|
||||
mutex_unlock(&ext_mutex_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
*(int *)data = (*(int *)data == 0 ? 0 : 1);
|
||||
gpio_mode = (u8)(((*(int *)data)<<4) | gpio_mode);
|
||||
default:
|
||||
gpio_list[gpio_no].irq_handler = NULL;
|
||||
intr_mask_reg &= ~(1<<gpio_no);
|
||||
break;
|
||||
}
|
||||
|
||||
sif_lock_bus(ext_epub);
|
||||
ret = sif_config_gpio_mode(ext_epub, (u8)gpio_no, gpio_mode);
|
||||
sif_unlock_bus(ext_epub);
|
||||
if (ret) {
|
||||
memcpy(&gpio_list[gpio_no], &backup_info, sizeof(struct ext_gpio_info));
|
||||
esp_dbg(ESP_DBG_ERROR, "%s gpio set error\n", __func__);
|
||||
mutex_unlock(&ext_mutex_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
mutex_unlock(&ext_mutex_lock);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ext_gpio_set_mode);
|
||||
|
||||
int ext_gpio_get_mode(int gpio_no)
|
||||
{
|
||||
int gpio_mode;
|
||||
|
||||
if (ext_epub == NULL || ext_epub->sip == NULL ||
|
||||
atomic_read(&ext_epub->sip->state) != SIP_RUN) {
|
||||
esp_dbg(ESP_DBG_LOG, "%s esp state is not ok\n", __func__);
|
||||
return -ENOTRECOVERABLE;
|
||||
}
|
||||
|
||||
mutex_lock(&ext_mutex_lock);
|
||||
|
||||
if (gpio_no >= EXT_GPIO_MAX_NUM || gpio_no < 0) {
|
||||
esp_dbg(ESP_DBG_ERROR, "%s unkown gpio num\n", __func__);
|
||||
mutex_unlock(&ext_mutex_lock);
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
gpio_mode = gpio_list[gpio_no].gpio_mode;
|
||||
|
||||
mutex_unlock(&ext_mutex_lock);
|
||||
|
||||
return gpio_mode;
|
||||
}
|
||||
EXPORT_SYMBOL(ext_gpio_get_mode);
|
||||
|
||||
|
||||
int ext_gpio_set_output_state(int gpio_no, int state)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (ext_epub == NULL || ext_epub->sip == NULL ||
|
||||
atomic_read(&ext_epub->sip->state) != SIP_RUN) {
|
||||
esp_dbg(ESP_DBG_LOG, "%s esp state is not ok\n", __func__);
|
||||
return -ENOTRECOVERABLE;
|
||||
}
|
||||
|
||||
mutex_lock(&ext_mutex_lock);
|
||||
|
||||
if (gpio_no >= EXT_GPIO_MAX_NUM || gpio_no < 0) {
|
||||
mutex_unlock(&ext_mutex_lock);
|
||||
esp_dbg(ESP_DBG_ERROR, "%s unkown gpio num\n", __func__);
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
if (gpio_list[gpio_no].gpio_mode != EXT_GPIO_MODE_OUTPUT) {
|
||||
mutex_unlock(&ext_mutex_lock);
|
||||
esp_dbg(ESP_DBG_ERROR, "%s gpio is not in output state, please request gpio or set output state\n", __func__);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (state != EXT_GPIO_STATE_LOW && state != EXT_GPIO_STATE_HIGH) {
|
||||
mutex_unlock(&ext_mutex_lock);
|
||||
esp_dbg(ESP_DBG_ERROR, "%s gpio state unknown\n", __func__);
|
||||
return -ENOTRECOVERABLE;
|
||||
}
|
||||
|
||||
sif_lock_bus(ext_epub);
|
||||
ret = sif_set_gpio_output(ext_epub, 1<<gpio_no, state<<gpio_no);
|
||||
sif_unlock_bus(ext_epub);
|
||||
if (ret) {
|
||||
esp_dbg(ESP_DBG_ERROR, "%s gpio state set error\n", __func__);
|
||||
mutex_unlock(&ext_mutex_lock);
|
||||
return ret;
|
||||
}
|
||||
gpio_list[gpio_no].gpio_state = state;
|
||||
|
||||
mutex_unlock(&ext_mutex_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ext_gpio_set_output_state);
|
||||
|
||||
int ext_gpio_get_state(int gpio_no)
|
||||
{
|
||||
int ret;
|
||||
u16 state;
|
||||
u16 mask;
|
||||
|
||||
if (ext_epub == NULL || ext_epub->sip == NULL ||
|
||||
atomic_read(&ext_epub->sip->state) != SIP_RUN) {
|
||||
esp_dbg(ESP_DBG_LOG, "%s esp state is not ok\n", __func__);
|
||||
return -ENOTRECOVERABLE;
|
||||
}
|
||||
|
||||
mutex_lock(&ext_mutex_lock);
|
||||
|
||||
if (gpio_no >= EXT_GPIO_MAX_NUM || gpio_no < 0) {
|
||||
esp_dbg(ESP_DBG_ERROR, "%s unkown gpio num\n", __func__);
|
||||
mutex_unlock(&ext_mutex_lock);
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
if (gpio_list[gpio_no].gpio_mode == EXT_GPIO_MODE_OUTPUT) {
|
||||
state = gpio_list[gpio_no].gpio_state;
|
||||
} else if (gpio_list[gpio_no].gpio_mode == EXT_GPIO_MODE_INPUT) {
|
||||
sif_lock_bus(ext_epub);
|
||||
ret = sif_get_gpio_input(ext_epub, &mask, &state);
|
||||
sif_unlock_bus(ext_epub);
|
||||
if (ret) {
|
||||
esp_dbg(ESP_DBG_ERROR, "%s get gpio_input state error\n", __func__);
|
||||
mutex_unlock(&ext_mutex_lock);
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
esp_dbg(ESP_DBG_ERROR, "%s gpio_state is not input or output\n", __func__);
|
||||
mutex_unlock(&ext_mutex_lock);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
mutex_unlock(&ext_mutex_lock);
|
||||
|
||||
return (state & (1<<gpio_no)) ? 1 : 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ext_gpio_get_state);
|
||||
|
||||
int ext_irq_ack(int gpio_no)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (ext_epub == NULL || ext_epub->sip == NULL ||
|
||||
atomic_read(&ext_epub->sip->state) != SIP_RUN) {
|
||||
esp_dbg(ESP_DBG_LOG, "%s esp state is not ok\n", __func__);
|
||||
return -ENOTRECOVERABLE;
|
||||
}
|
||||
|
||||
mutex_lock(&ext_mutex_lock);
|
||||
if (gpio_no >= EXT_GPIO_MAX_NUM || gpio_no < 0) {
|
||||
esp_dbg(ESP_DBG_ERROR, "%s unkown gpio num\n", __func__);
|
||||
mutex_unlock(&ext_mutex_lock);
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
if (gpio_list[gpio_no].gpio_mode != EXT_GPIO_MODE_INTR_POSEDGE
|
||||
&& gpio_list[gpio_no].gpio_mode != EXT_GPIO_MODE_INTR_NEGEDGE
|
||||
&& gpio_list[gpio_no].gpio_mode != EXT_GPIO_MODE_INTR_LOLEVEL
|
||||
&& gpio_list[gpio_no].gpio_mode != EXT_GPIO_MODE_INTR_HILEVEL) {
|
||||
esp_dbg(ESP_DBG_ERROR, "%s gpio mode is not intr mode\n", __func__);
|
||||
mutex_unlock(&ext_mutex_lock);
|
||||
return -ENOTRECOVERABLE;
|
||||
}
|
||||
|
||||
sif_lock_bus(ext_epub);
|
||||
ret = sif_set_gpio_output(ext_epub, 0x00, 1<<gpio_no);
|
||||
sif_unlock_bus(ext_epub);
|
||||
if (ret) {
|
||||
esp_dbg(ESP_DBG_ERROR, "%s gpio intr ack error\n", __func__);
|
||||
mutex_unlock(&ext_mutex_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
mutex_unlock(&ext_mutex_lock);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ext_irq_ack);
|
||||
|
||||
void show_status(void)
|
||||
{
|
||||
int i=0;
|
||||
for (i = 0; i < MAX_PENDING_INTR_LIST;i++)
|
||||
esp_dbg(ESP_DBG_ERROR, "status[%d] = [0x%04x]\n", i, esp_pending_intr_list.pending_intr_list[i]);
|
||||
|
||||
esp_dbg(ESP_DBG_ERROR, "start_pos[%d]\n",esp_pending_intr_list.start_pos);
|
||||
esp_dbg(ESP_DBG_ERROR, "end_pos[%d]\n",esp_pending_intr_list.end_pos);
|
||||
esp_dbg(ESP_DBG_ERROR, "curr_num[%d]\n",esp_pending_intr_list.curr_num);
|
||||
|
||||
}
|
||||
void esp_tx_work(struct work_struct *work)
|
||||
{
|
||||
int i;
|
||||
u16 tmp_intr_status_reg;
|
||||
|
||||
esp_dbg(ESP_DBG_TRACE, "%s enter\n", __func__);
|
||||
|
||||
spin_lock(&esp_pending_intr_list.spin_lock);
|
||||
|
||||
tmp_intr_status_reg = esp_pending_intr_list.pending_intr_list[esp_pending_intr_list.start_pos];
|
||||
|
||||
esp_pending_intr_list.pending_intr_list[esp_pending_intr_list.start_pos] = 0x0000;
|
||||
esp_pending_intr_list.start_pos = (esp_pending_intr_list.start_pos + 1) % MAX_PENDING_INTR_LIST;
|
||||
esp_pending_intr_list.curr_num--;
|
||||
|
||||
spin_unlock(&esp_pending_intr_list.spin_lock);
|
||||
|
||||
for (i = 0; i < EXT_GPIO_MAX_NUM; i++) {
|
||||
if (tmp_intr_status_reg & (1<<i) && (gpio_list[i].irq_handler))
|
||||
gpio_list[i].irq_handler();
|
||||
}
|
||||
|
||||
spin_lock(&esp_pending_intr_list.spin_lock);
|
||||
if (esp_pending_intr_list.curr_num > 0)
|
||||
queue_work(ext_irq_wkq, &ext_irq_work);
|
||||
spin_unlock(&esp_pending_intr_list.spin_lock);
|
||||
}
|
||||
|
||||
void ext_gpio_int_process(u16 value) {
|
||||
if (value == 0x00)
|
||||
return;
|
||||
|
||||
esp_dbg(ESP_DBG_TRACE, "%s enter\n", __func__);
|
||||
|
||||
/* intr cycle queue is full, wait */
|
||||
while (esp_pending_intr_list.curr_num >= MAX_PENDING_INTR_LIST)
|
||||
{
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
spin_lock(&esp_pending_intr_list.spin_lock);
|
||||
|
||||
esp_pending_intr_list.pending_intr_list[esp_pending_intr_list.end_pos] = value;
|
||||
esp_pending_intr_list.end_pos = (esp_pending_intr_list.end_pos + 1) % MAX_PENDING_INTR_LIST;
|
||||
esp_pending_intr_list.curr_num++;
|
||||
|
||||
queue_work(ext_irq_wkq, &ext_irq_work);
|
||||
|
||||
spin_unlock(&esp_pending_intr_list.spin_lock);
|
||||
}
|
||||
|
||||
int ext_gpio_init(struct esp_pub *epub)
|
||||
{
|
||||
esp_dbg(ESP_DBG_ERROR, "%s enter\n", __func__);
|
||||
|
||||
ext_irq_wkq = create_singlethread_workqueue("esp_ext_irq_wkq");
|
||||
if (ext_irq_wkq == NULL) {
|
||||
esp_dbg(ESP_DBG_ERROR, "%s create workqueue error\n", __func__);
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
INIT_WORK(&ext_irq_work, esp_tx_work);
|
||||
mutex_init(&ext_mutex_lock);
|
||||
|
||||
ext_epub = epub;
|
||||
|
||||
if (ext_epub == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
#ifdef EXT_GPIO_OPS
|
||||
register_ext_gpio_ops(&ext_gpio_ops);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ext_gpio_deinit(void)
|
||||
{
|
||||
esp_dbg(ESP_DBG_ERROR, "%s enter\n", __func__);
|
||||
|
||||
#ifdef EXT_GPIO_OPS
|
||||
unregister_ext_gpio_ops();
|
||||
#endif
|
||||
ext_epub = NULL;
|
||||
cancel_work_sync(&ext_irq_work);
|
||||
|
||||
if (ext_irq_wkq)
|
||||
destroy_workqueue(ext_irq_wkq);
|
||||
}
|
||||
|
||||
#endif /* USE_EXT_GPIO */
|
||||
100
drivers/net/wireless/esp8089/esp_ext.h
Executable file
100
drivers/net/wireless/esp8089/esp_ext.h
Executable file
@@ -0,0 +1,100 @@
|
||||
#ifdef USE_EXT_GPIO
|
||||
|
||||
#ifndef _ESP_EXT_H_
|
||||
#define _ESP_EXT_H_
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/module.h>
|
||||
#include "esp_sip.h"
|
||||
|
||||
#define MAX_PENDING_INTR_LIST 16
|
||||
|
||||
#ifdef EXT_GPIO_OPS
|
||||
typedef struct esp_ext_gpio_ops {
|
||||
int (*gpio_request)(int gpio_no); /* gpio_request gpio_no from 0x0 to 0xf*/
|
||||
int (*gpio_release)(int gpio_no); /* gpio_release */
|
||||
int (*gpio_set_mode)(int gpio_no, int mode , void *data); /* gpio_set_mode, data is irq_func of irq_mode , default level of output_mode */
|
||||
int (*gpio_get_mode)(int gpio_no); /* gpio_get_mode, current mode */
|
||||
int (*gpio_set_state)(int gpio_no, int state); /* only output state, high level or low level */
|
||||
int (*gpio_get_state)(int gpio_no); /* current state */
|
||||
int (*irq_ack)(int gpio_no); /* ack interrupt */
|
||||
} esp_ext_gpio_ops_t;
|
||||
#endif
|
||||
|
||||
typedef enum EXT_GPIO_NO {
|
||||
EXT_GPIO_GPIO0 = 0,
|
||||
EXT_GPIO_U0TXD,
|
||||
EXT_GPIO_GPIO2,
|
||||
EXT_GPIO_U0RXD,
|
||||
EXT_GPIO_GPIO4,
|
||||
EXT_GPIO_GPIO5,
|
||||
EXT_GPIO_SD_CLK,
|
||||
EXT_GPIO_SD_DATA0,
|
||||
EXT_GPIO_SD_DATA1,
|
||||
EXT_GPIO_SD_DATA2,
|
||||
EXT_GPIO_SD_DATA3,
|
||||
EXT_GPIO_SD_CMD,
|
||||
EXT_GPIO_MTDI,
|
||||
EXT_GPIO_MTCK,
|
||||
EXT_GPIO_MTMS,
|
||||
EXT_GPIO_MTDO,
|
||||
EXT_GPIO_MAX_NUM
|
||||
} EXT_GPIO_NO_T;
|
||||
|
||||
typedef enum EXT_GPIO_MODE { //dir def pullup mode wake
|
||||
EXT_GPIO_MODE_OOB = 0, //output 1 0 n/a n/a
|
||||
EXT_GPIO_MODE_OUTPUT, //output / 0 n/a n/a
|
||||
EXT_GPIO_MODE_DISABLE, //input n/a 0 DIS n/a
|
||||
EXT_GPIO_MODE_INTR_POSEDGE, //input n/a 0 POS 1
|
||||
EXT_GPIO_MODE_INTR_NEGEDGE, //input n/a 1 NEG 1
|
||||
EXT_GPIO_MODE_INPUT, //input n/a 0 ANY 1
|
||||
EXT_GPIO_MODE_INTR_LOLEVEL, //input n/a 1 LOW 1
|
||||
EXT_GPIO_MODE_INTR_HILEVEL, //input n/a 0 HIGH 1
|
||||
EXT_GPIO_MODE_MAX,
|
||||
} EXT_GPIO_MODE_T;
|
||||
|
||||
typedef enum EXT_GPIO_STATE {
|
||||
EXT_GPIO_STATE_LOW,
|
||||
EXT_GPIO_STATE_HIGH,
|
||||
EXT_GPIO_STATE_IDLE
|
||||
} EXT_GPIO_STATE_T;
|
||||
|
||||
typedef irqreturn_t (*ext_irq_handler_t)(void);
|
||||
|
||||
struct ext_gpio_info {
|
||||
int gpio_no;
|
||||
int gpio_mode;
|
||||
int gpio_state;
|
||||
ext_irq_handler_t irq_handler;
|
||||
};
|
||||
|
||||
struct pending_intr_list_info {
|
||||
u16 pending_intr_list[MAX_PENDING_INTR_LIST];
|
||||
int start_pos;
|
||||
int end_pos;
|
||||
int curr_num;
|
||||
spinlock_t spin_lock;
|
||||
};
|
||||
|
||||
u16 ext_gpio_get_int_mask_reg(void);
|
||||
|
||||
/* for extern user start */
|
||||
int ext_gpio_request(int gpio_no);
|
||||
int ext_gpio_release(int gpio_no);
|
||||
|
||||
int ext_gpio_set_mode(int gpio_no, int mode, void *data);
|
||||
int ext_gpio_get_mode(int gpio_no);
|
||||
|
||||
int ext_gpio_set_output_state(int gpio_no, int state);
|
||||
int ext_gpio_get_state(int gpio_no);
|
||||
|
||||
int ext_irq_ack(int gpio_no);
|
||||
/* for extern user end */
|
||||
|
||||
void ext_gpio_int_process(u16 value);
|
||||
|
||||
int ext_gpio_init(struct esp_pub *epub);
|
||||
void ext_gpio_deinit(void);
|
||||
#endif /* _ESP_EXT_H_ */
|
||||
|
||||
#endif /* USE_EXT_GPIO */
|
||||
419
drivers/net/wireless/esp8089/esp_file.c
Normal file
419
drivers/net/wireless/esp8089/esp_file.c
Normal file
@@ -0,0 +1,419 @@
|
||||
/*
|
||||
* Copyright (c) 2010 -2014 Espressif System.
|
||||
*
|
||||
* file operation in kernel space
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/aio.h>
|
||||
|
||||
#include "esp_file.h"
|
||||
#include "esp_debug.h"
|
||||
#include "esp_sif.h"
|
||||
|
||||
#include "esp_path.h"
|
||||
#include "esp_conf.h"
|
||||
|
||||
int esp_readwrite_file(const char *filename, char *rbuf, const char *wbuf, size_t length)
|
||||
{
|
||||
int ret = 0;
|
||||
struct file *filp = (struct file *)-ENOENT;
|
||||
mm_segment_t oldfs;
|
||||
oldfs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
do {
|
||||
int mode = (wbuf) ? O_RDWR | O_CREAT : O_RDONLY;
|
||||
filp = filp_open(filename, mode, (S_IRUSR | S_IWUSR));
|
||||
if (IS_ERR(filp) || !filp->f_op) {
|
||||
esp_dbg(ESP_DBG_ERROR, "%s: file %s filp_open error\n", __FUNCTION__, filename);
|
||||
ret = -ENOENT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (length==0) {
|
||||
/* Read the length of the file only */
|
||||
struct inode *inode;
|
||||
|
||||
inode = GET_INODE_FROM_FILEP(filp);
|
||||
if (!inode) {
|
||||
esp_dbg(ESP_DBG_ERROR, "%s: Get inode from %s failed\n", __FUNCTION__, filename);
|
||||
ret = -ENOENT;
|
||||
break;
|
||||
}
|
||||
ret = i_size_read(inode->i_mapping->host);
|
||||
break;
|
||||
}
|
||||
|
||||
if (wbuf) {
|
||||
if ( (ret=vfs_write(filp, wbuf, length, &filp->f_pos)) < 0) {
|
||||
esp_dbg(ESP_DBG_ERROR, "%s: Write %u bytes to file %s error %d\n", __FUNCTION__,
|
||||
(unsigned int)length, filename, ret);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if ( (ret=filp->f_op->read(filp, rbuf, length, &filp->f_pos)) < 0) {
|
||||
esp_dbg(ESP_DBG_ERROR, "%s: Read %u bytes from file %s error %d\n", __FUNCTION__,
|
||||
(unsigned int)length, filename, ret);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (0);
|
||||
|
||||
if (!IS_ERR(filp)) {
|
||||
filp_close(filp, NULL);
|
||||
}
|
||||
set_fs(oldfs);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int esp_request_firmware(const struct firmware **firmware_p, const char *name,
|
||||
struct device *device)
|
||||
{
|
||||
int ret = 0;
|
||||
struct firmware *firmware;
|
||||
char filename[256];
|
||||
const char *raw_filename = name;
|
||||
*firmware_p = firmware = kmalloc((sizeof(*firmware)), GFP_KERNEL);
|
||||
if (!firmware)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(firmware, 0, sizeof(*firmware));
|
||||
|
||||
if (mod_eagle_path_get() == NULL)
|
||||
sprintf(filename, "%s/%s", FWPATH, raw_filename);
|
||||
else
|
||||
sprintf(filename, "%s/%s", mod_eagle_path_get(), raw_filename);
|
||||
|
||||
do {
|
||||
size_t length, bufsize, bmisize;
|
||||
|
||||
if ( (ret=esp_readwrite_file(filename, NULL, NULL, 0)) < 0) {
|
||||
break;
|
||||
} else {
|
||||
length = ret;
|
||||
}
|
||||
|
||||
bufsize = ALIGN(length, PAGE_SIZE);
|
||||
bmisize = E_ROUND_UP(length, 4);
|
||||
bufsize = max(bmisize, bufsize);
|
||||
firmware->data = vmalloc(bufsize);
|
||||
firmware->size = length;
|
||||
if (!firmware->data) {
|
||||
esp_dbg(ESP_DBG_ERROR, "%s: Cannot allocate buffer for firmware\n", __FUNCTION__);
|
||||
ret = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( (ret=esp_readwrite_file(filename, (char*)firmware->data, NULL, length)) != length) {
|
||||
esp_dbg(ESP_DBG_ERROR, "%s: file read error, ret %d request %d\n", __FUNCTION__, ret, (unsigned int)length);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
} while (0);
|
||||
|
||||
if (ret<0) {
|
||||
if (firmware) {
|
||||
if (firmware->data)
|
||||
vfree(firmware->data);
|
||||
|
||||
kfree(firmware);
|
||||
}
|
||||
*firmware_p = NULL;
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void esp_release_firmware(const struct firmware *firmware)
|
||||
{
|
||||
if (firmware) {
|
||||
if (firmware->data)
|
||||
vfree(firmware->data);
|
||||
|
||||
kfree((struct firmware *)firmware);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ESP_ANDROID_LOGGER
|
||||
int logger_write( const unsigned char prio,
|
||||
const char __kernel * const tag,
|
||||
const char __kernel * const fmt,
|
||||
...)
|
||||
{
|
||||
int ret = 0;
|
||||
va_list vargs;
|
||||
struct file *filp = (struct file *)-ENOENT;
|
||||
mm_segment_t oldfs;
|
||||
struct iovec vec[3];
|
||||
int tag_bytes = strlen(tag) + 1, msg_bytes;
|
||||
char *msg;
|
||||
va_start(vargs, fmt);
|
||||
msg = kvasprintf(GFP_ATOMIC, fmt, vargs);
|
||||
va_end(vargs);
|
||||
if (!msg)
|
||||
return -ENOMEM;
|
||||
if (in_interrupt()) {
|
||||
/* we have no choice since aio_write may be blocked */
|
||||
printk(KERN_ALERT "%s", msg);
|
||||
goto out_free_message;
|
||||
}
|
||||
msg_bytes = strlen(msg) + 1;
|
||||
if (msg_bytes <= 1) /* empty message? */
|
||||
goto out_free_message; /* don't bother, then */
|
||||
if ((msg_bytes + tag_bytes + 1) > 2048) {
|
||||
ret = -E2BIG;
|
||||
goto out_free_message;
|
||||
}
|
||||
|
||||
vec[0].iov_base = (unsigned char *) &prio;
|
||||
vec[0].iov_len = 1;
|
||||
vec[1].iov_base = (void *) tag;
|
||||
vec[1].iov_len = strlen(tag) + 1;
|
||||
vec[2].iov_base = (void *) msg;
|
||||
vec[2].iov_len = strlen(msg) + 1;
|
||||
|
||||
oldfs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
do {
|
||||
filp = filp_open("/dev/log/main", O_WRONLY, S_IRUSR);
|
||||
if (IS_ERR(filp) || !filp->f_op) {
|
||||
|
||||
esp_dbg(ESP_DBG_ERROR, "%s: filp open /dev/log/main error\n", __FUNCTION__);
|
||||
ret = -ENOENT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (filp->f_op->aio_write) {
|
||||
int nr_segs = sizeof(vec) / sizeof(vec[0]);
|
||||
int len = vec[0].iov_len + vec[1].iov_len + vec[2].iov_len;
|
||||
struct kiocb kiocb;
|
||||
init_sync_kiocb(&kiocb, filp);
|
||||
kiocb.ki_pos = 0;
|
||||
kiocb.ki_left = len;
|
||||
kiocb.ki_nbytes = len;
|
||||
ret = filp->f_op->aio_write(&kiocb, vec, nr_segs, kiocb.ki_pos);
|
||||
}
|
||||
|
||||
} while (0);
|
||||
|
||||
if (!IS_ERR(filp)) {
|
||||
filp_close(filp, NULL);
|
||||
}
|
||||
set_fs(oldfs);
|
||||
out_free_message:
|
||||
if (msg) {
|
||||
kfree(msg);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
struct esp_init_table_elem esp_init_table[MAX_ATTR_NUM] = {
|
||||
{"crystal_26M_en", 48, -1},
|
||||
{"test_xtal", 49, -1},
|
||||
{"sdio_configure", 50, -1},
|
||||
{"bt_configure", 51, -1},
|
||||
{"bt_protocol", 52, -1},
|
||||
{"dual_ant_configure", 53, -1},
|
||||
{"test_uart_configure", 54, -1},
|
||||
{"share_xtal", 55, -1},
|
||||
{"gpio_wake", 56, -1},
|
||||
{"no_auto_sleep", 57, -1},
|
||||
{"speed_suspend", 58, -1},
|
||||
{"attr11", -1, -1},
|
||||
{"attr12", -1, -1},
|
||||
{"attr13", -1, -1},
|
||||
{"attr14", -1, -1},
|
||||
{"attr15", -1, -1},
|
||||
//attr that is not send to target
|
||||
{"ext_rst", -1, -1},
|
||||
{"wakeup_gpio", -1, -1},
|
||||
{"ate_test", -1, -1},
|
||||
{"attr19", -1, -1},
|
||||
{"attr20", -1, -1},
|
||||
{"attr21", -1, -1},
|
||||
{"attr22", -1, -1},
|
||||
{"attr23", -1, -1},
|
||||
|
||||
};
|
||||
|
||||
int esp_atoi(char *str)
|
||||
{
|
||||
int num = 0;
|
||||
int ng_flag = 0;
|
||||
|
||||
if (*str == '-') {
|
||||
str++;
|
||||
ng_flag = 1;
|
||||
}
|
||||
|
||||
while(*str != '\0') {
|
||||
num = num * 10 + *str++ - '0';
|
||||
}
|
||||
|
||||
return ng_flag ? 0-num : num;
|
||||
}
|
||||
|
||||
void show_esp_init_table(struct esp_init_table_elem *econf)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_ATTR_NUM; i++)
|
||||
if (esp_init_table[i].offset > -1)
|
||||
esp_dbg(ESP_DBG_ERROR, "%s: esp_init_table[%d] attr[%s] offset[%d] value[%d]\n",
|
||||
__FUNCTION__, i,
|
||||
esp_init_table[i].attr,
|
||||
esp_init_table[i].offset,
|
||||
esp_init_table[i].value);
|
||||
}
|
||||
|
||||
int request_init_conf(void)
|
||||
{
|
||||
|
||||
u8 *conf_buf;
|
||||
u8 *pbuf;
|
||||
int flag;
|
||||
int str_len;
|
||||
int length;
|
||||
int ret;
|
||||
int i;
|
||||
char attr_name[CONF_ATTR_LEN];
|
||||
char num_buf[CONF_VAL_LEN];
|
||||
#ifdef INIT_DATA_CONF
|
||||
char filename[256];
|
||||
|
||||
if (mod_eagle_path_get() == NULL)
|
||||
sprintf(filename, "%s/%s", FWPATH, INIT_CONF_FILE);
|
||||
else
|
||||
sprintf(filename, "%s/%s", mod_eagle_path_get(), INIT_CONF_FILE);
|
||||
|
||||
if ((ret=esp_readwrite_file(filename, NULL, NULL, 0)) < 0 || ret > MAX_BUF_LEN) {
|
||||
esp_dbg(ESP_DBG_ERROR, "%s: file read length error, ret %d\n", __FUNCTION__, ret);
|
||||
return ret;
|
||||
} else {
|
||||
length = ret;
|
||||
}
|
||||
#endif /* INIT_DATA_CONF */
|
||||
conf_buf = (u8 *)kmalloc(MAX_BUF_LEN, GFP_KERNEL);
|
||||
if (conf_buf == NULL) {
|
||||
esp_dbg(ESP_DBG_ERROR, "%s: failed kmalloc memory for read init_data_conf", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
#ifdef INIT_DATA_CONF
|
||||
if ((ret=esp_readwrite_file(filename, conf_buf, NULL, length)) != length) {
|
||||
esp_dbg(ESP_DBG_ERROR, "%s: file read error, ret %d request %d\n", __FUNCTION__, ret, length);
|
||||
goto failed;
|
||||
}
|
||||
#else
|
||||
length = strlen(INIT_DATA_CONF_BUF);
|
||||
strncpy(conf_buf, INIT_DATA_CONF_BUF, length);
|
||||
#endif
|
||||
conf_buf[length] = '\0';
|
||||
|
||||
flag = 0;
|
||||
str_len = 0;
|
||||
for (pbuf = conf_buf; *pbuf != '$' && *pbuf != '\n'; pbuf++) {
|
||||
if (*pbuf == '=') {
|
||||
flag = 1;
|
||||
*(attr_name+str_len) = '\0';
|
||||
str_len = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*pbuf == ';') {
|
||||
int value;
|
||||
flag = 0;
|
||||
*(num_buf+str_len) = '\0';
|
||||
if((value = esp_atoi(num_buf)) > 255 || value < 0){
|
||||
esp_dbg(ESP_DBG_ERROR, "%s: value is too big", __FUNCTION__);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_ATTR_NUM; i++) {
|
||||
if (strcmp(esp_init_table[i].attr, attr_name) == 0) {
|
||||
esp_dbg(ESP_DBG_TRACE, "%s: attr_name[%s]", __FUNCTION__, attr_name); /* add by th */
|
||||
esp_init_table[i].value = value;
|
||||
}
|
||||
|
||||
if (esp_init_table[i].value < 0)
|
||||
continue;
|
||||
|
||||
if(strcmp(esp_init_table[i].attr, "share_xtal") == 0){
|
||||
sif_record_bt_config(esp_init_table[i].value);
|
||||
}
|
||||
|
||||
if(strcmp(esp_init_table[i].attr, "ext_rst") == 0){
|
||||
sif_record_rst_config(esp_init_table[i].value);
|
||||
}
|
||||
|
||||
if(strcmp(esp_init_table[i].attr, "wakeup_gpio") == 0){
|
||||
sif_record_wakeup_gpio_config(esp_init_table[i].value);
|
||||
}
|
||||
|
||||
if(strcmp(esp_init_table[i].attr, "ate_test") == 0){
|
||||
sif_record_ate_config(esp_init_table[i].value);
|
||||
}
|
||||
|
||||
}
|
||||
str_len = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (flag == 0) {
|
||||
*(attr_name+str_len) = *pbuf;
|
||||
if (++str_len > CONF_ATTR_LEN) {
|
||||
esp_dbg(ESP_DBG_ERROR, "%s: attr len is too long", __FUNCTION__);
|
||||
goto failed;
|
||||
}
|
||||
} else {
|
||||
*(num_buf+str_len) = *pbuf;
|
||||
if (++str_len > CONF_VAL_LEN) {
|
||||
esp_dbg(ESP_DBG_ERROR, "%s: value len is too long", __FUNCTION__);
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//show_esp_init_table(esp_init_table);
|
||||
|
||||
ret = 0;
|
||||
failed:
|
||||
if (conf_buf)
|
||||
kfree(conf_buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void fix_init_data(u8 *init_data_buf, int buf_size)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_FIX_ATTR_NUM; i++) {
|
||||
if (esp_init_table[i].offset > -1 && esp_init_table[i].offset < buf_size && esp_init_table[i].value > -1) {
|
||||
*(u8 *)(init_data_buf + esp_init_table[i].offset) = esp_init_table[i].value;
|
||||
} else if (esp_init_table[i].offset > buf_size) {
|
||||
esp_dbg(ESP_DBG_ERROR, "%s: offset[%d] longer than init_data_buf len[%d] Ignore\n", __FUNCTION__, esp_init_table[i].offset, buf_size);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
68
drivers/net/wireless/esp8089/esp_file.h
Normal file
68
drivers/net/wireless/esp8089/esp_file.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2010 -2014 Espressif System.
|
||||
*
|
||||
* file operation in kernel space
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef _ESP_FILE_H_
|
||||
#define _ESP_FILE_H_
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/firmware.h>
|
||||
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
|
||||
#define GET_INODE_FROM_FILEP(filp) \
|
||||
(filp)->f_path.dentry->d_inode
|
||||
#else
|
||||
#define GET_INODE_FROM_FILEP(filp) \
|
||||
(filp)->f_dentry->d_inode
|
||||
#endif
|
||||
|
||||
#define E_ROUND_UP(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
|
||||
|
||||
int esp_readwrite_file(const char *filename, char *rbuf, const char *wbuf, size_t length);
|
||||
|
||||
int esp_request_firmware(const struct firmware **firmware_p, const char *name, struct device *device);
|
||||
|
||||
void esp_release_firmware(const struct firmware *firmware);
|
||||
|
||||
#ifdef INIT_DATA_CONF
|
||||
#define INIT_CONF_FILE "init_data.conf"
|
||||
#endif /* def INIT_DATA_CONF */
|
||||
|
||||
#define CONF_ATTR_LEN 24
|
||||
#define CONF_VAL_LEN 3
|
||||
#define MAX_ATTR_NUM 24
|
||||
#define MAX_FIX_ATTR_NUM 16
|
||||
#define MAX_BUF_LEN ((CONF_ATTR_LEN + CONF_VAL_LEN + 2) * MAX_ATTR_NUM + 2)
|
||||
|
||||
struct esp_init_table_elem {
|
||||
char attr[CONF_ATTR_LEN];
|
||||
int offset;
|
||||
short value;
|
||||
};
|
||||
|
||||
int request_init_conf(void);
|
||||
void fix_init_data(u8 *init_data_buf, int buf_size);
|
||||
|
||||
|
||||
#ifdef ESP_ANDROID_LOGGER
|
||||
extern int logger_write( const unsigned char prio,
|
||||
const char __kernel * const tag,
|
||||
const char __kernel * const fmt,
|
||||
...);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _ESP_FILE_H_ */
|
||||
1
drivers/net/wireless/esp8089/esp_init_data.h
Executable file
1
drivers/net/wireless/esp8089/esp_init_data.h
Executable file
@@ -0,0 +1 @@
|
||||
static char esp_init_data[] = {0x5,0x0,4,2,5,5,5,2,5,0,4,5,5,4,5,5,4,-2,-3,-1,-16,-16,-16,-32,-32,-32,204,1,0xff,0xff,0,0,0,0,82,78,74,68,64,56,0,0,1,1,2,3,4,5,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,240,10,0x0,0x0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
649
drivers/net/wireless/esp8089/esp_io.c
Executable file
649
drivers/net/wireless/esp8089/esp_io.c
Executable file
@@ -0,0 +1,649 @@
|
||||
/*
|
||||
* Copyright (c) 2009 - 2014 Espressif System.
|
||||
* IO interface
|
||||
* - sdio/spi common i/f driver
|
||||
* - target sdio hal
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/mmc/sdio_func.h>
|
||||
#include "esp_sif.h"
|
||||
#include "slc_host_register.h"
|
||||
#include "esp_debug.h"
|
||||
|
||||
#ifdef SIF_DEBUG_DSR_DUMP_REG
|
||||
static void dump_slc_regs(struct slc_host_regs *regs);
|
||||
#endif /* SIF_DEBUG_DSR_DUMP_REG */
|
||||
|
||||
int esp_common_read(struct esp_pub *epub, u8 *buf, u32 len, int sync, bool noround)
|
||||
{
|
||||
if (sync) {
|
||||
#ifdef ESP_USE_SDIO
|
||||
return sif_lldesc_read_sync(epub, buf, len);
|
||||
#endif
|
||||
#ifdef ESP_USE_SPI
|
||||
return sif_spi_read_sync(epub, buf, len, NOT_DUMMYMODE);
|
||||
#endif
|
||||
} else {
|
||||
#ifdef ESP_USE_SDIO
|
||||
return sif_lldesc_read_raw(epub, buf, len, noround);
|
||||
#endif
|
||||
#ifdef ESP_USE_SPI
|
||||
return sif_spi_read_nosync(epub, buf, len, NOT_DUMMYMODE, noround);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
int esp_common_write(struct esp_pub *epub, u8 *buf, u32 len, int sync)
|
||||
{
|
||||
if (sync) {
|
||||
#ifdef ESP_USE_SDIO
|
||||
return sif_lldesc_write_sync(epub, buf, len);
|
||||
#endif
|
||||
#ifdef ESP_USE_SPI
|
||||
return sif_spi_write_sync(epub, buf, len, NOT_DUMMYMODE);
|
||||
#endif
|
||||
} else {
|
||||
#ifdef ESP_USE_SDIO
|
||||
return sif_lldesc_write_raw(epub, buf, len);
|
||||
#endif
|
||||
#ifdef ESP_USE_SPI
|
||||
return sif_spi_write_nosync(epub, buf, len, NOT_DUMMYMODE);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
int esp_common_read_with_addr(struct esp_pub *epub, u32 addr, u8 *buf, u32 len, int sync)
|
||||
{
|
||||
if (sync) {
|
||||
#ifdef ESP_USE_SDIO
|
||||
return sif_io_sync(epub, addr, buf, len, SIF_FROM_DEVICE | SIF_SYNC | SIF_BYTE_BASIS | SIF_INC_ADDR);
|
||||
#endif
|
||||
#ifdef ESP_USE_SPI
|
||||
return sif_spi_epub_read_mix_sync(epub, addr, buf, len, NOT_DUMMYMODE);
|
||||
#endif
|
||||
} else {
|
||||
#ifdef ESP_USE_SDIO
|
||||
return sif_io_raw(epub, addr, buf, len, SIF_FROM_DEVICE | SIF_BYTE_BASIS | SIF_INC_ADDR);
|
||||
#endif
|
||||
#ifdef ESP_USE_SPI
|
||||
return sif_spi_epub_read_mix_nosync(epub, addr, buf, len, NOT_DUMMYMODE);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
int esp_common_write_with_addr(struct esp_pub *epub, u32 addr, u8 *buf, u32 len, int sync)
|
||||
{
|
||||
if (sync) {
|
||||
#ifdef ESP_USE_SDIO
|
||||
return sif_io_sync(epub, addr, buf, len, SIF_TO_DEVICE | SIF_SYNC | SIF_BYTE_BASIS | SIF_INC_ADDR);
|
||||
#endif
|
||||
#ifdef ESP_USE_SPI
|
||||
return sif_spi_epub_write_mix_sync(epub, addr, buf, len, NOT_DUMMYMODE);
|
||||
#endif
|
||||
} else {
|
||||
#ifdef ESP_USE_SDIO
|
||||
return sif_io_raw(epub, addr, buf, len, SIF_TO_DEVICE | SIF_BYTE_BASIS | SIF_INC_ADDR);
|
||||
#endif
|
||||
#ifdef ESP_USE_SPI
|
||||
return sif_spi_epub_write_mix_nosync(epub, addr, buf, len, NOT_DUMMYMODE);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
int esp_common_readbyte_with_addr(struct esp_pub *epub, u32 addr, u8 *buf, int sync)
|
||||
{
|
||||
if(sync){
|
||||
#ifdef ESP_USE_SDIO
|
||||
int res;
|
||||
sif_lock_bus(epub);
|
||||
*buf = sdio_io_readb(epub, addr, &res);
|
||||
sif_unlock_bus(epub);
|
||||
return res;
|
||||
#endif
|
||||
#ifdef ESP_USE_SPI
|
||||
return sif_spi_epub_read_mix_sync(epub, addr, buf, 1, NOT_DUMMYMODE);
|
||||
#endif
|
||||
} else {
|
||||
#ifdef ESP_USE_SDIO
|
||||
int res;
|
||||
*buf = sdio_io_readb(epub, addr, &res);
|
||||
return res;
|
||||
#endif
|
||||
#ifdef ESP_USE_SPI
|
||||
return sif_spi_epub_read_mix_nosync(epub, addr, buf, 1, NOT_DUMMYMODE);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
int esp_common_writebyte_with_addr(struct esp_pub *epub, u32 addr, u8 buf, int sync)
|
||||
{
|
||||
if(sync){
|
||||
#ifdef ESP_USE_SDIO
|
||||
int res;
|
||||
sif_lock_bus(epub);
|
||||
sdio_io_writeb(epub, buf, addr, &res);
|
||||
sif_unlock_bus(epub);
|
||||
return res;
|
||||
#endif
|
||||
#ifdef ESP_USE_SPI
|
||||
return sif_spi_epub_write_mix_sync(epub, addr, &buf, 1, NOT_DUMMYMODE);
|
||||
#endif
|
||||
} else {
|
||||
#ifdef ESP_USE_SDIO
|
||||
int res;
|
||||
sdio_io_writeb(epub, buf, addr, &res);
|
||||
return res;
|
||||
#endif
|
||||
#ifdef ESP_USE_SPI
|
||||
return sif_spi_epub_write_mix_nosync(epub, addr, &buf, 1, NOT_DUMMYMODE);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
int sif_read_reg_window(struct esp_pub *epub, unsigned int reg_addr, u8 *value)
|
||||
{
|
||||
u8 *p_tbuf = NULL;
|
||||
int ret = 0;
|
||||
int retry = 20;
|
||||
|
||||
reg_addr >>= 2;
|
||||
if(reg_addr > 0x1f)
|
||||
return -1;
|
||||
|
||||
p_tbuf = kzalloc(4, GFP_KERNEL);
|
||||
if(p_tbuf == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
p_tbuf[0] = 0x80 | (reg_addr & 0x1f);
|
||||
|
||||
ret = esp_common_write_with_addr(epub, SLC_HOST_WIN_CMD, p_tbuf, 1, ESP_SIF_NOSYNC);
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
do{
|
||||
if(retry < 20)
|
||||
mdelay(10);
|
||||
retry --;
|
||||
ret = esp_common_read_with_addr(epub, SLC_HOST_STATE_W0, p_tbuf, 4, ESP_SIF_NOSYNC);
|
||||
}while(retry >0 && ret != 0);
|
||||
}
|
||||
|
||||
if(ret ==0)
|
||||
memcpy(value,p_tbuf,4);
|
||||
|
||||
kfree(p_tbuf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sif_write_reg_window(struct esp_pub *epub, unsigned int reg_addr,u8 *value)
|
||||
{
|
||||
u8 *p_tbuf = NULL;
|
||||
int ret = 0;
|
||||
|
||||
reg_addr >>= 2;
|
||||
if(reg_addr > 0x1f)
|
||||
return -1;
|
||||
|
||||
p_tbuf = kzalloc(8, GFP_KERNEL);
|
||||
if(p_tbuf == NULL)
|
||||
return -ENOMEM;
|
||||
memcpy(p_tbuf,value,4);
|
||||
p_tbuf[4] = 0xc0 |(reg_addr & 0x1f);
|
||||
|
||||
ret = esp_common_write_with_addr(epub, SLC_HOST_CONF_W5, p_tbuf, 5, ESP_SIF_NOSYNC);
|
||||
|
||||
kfree(p_tbuf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sif_ack_target_read_err(struct esp_pub *epub)
|
||||
{
|
||||
u32 value[1];
|
||||
int ret;
|
||||
|
||||
ret = sif_read_reg_window(epub, SLC_RX_LINK, (u8 *)value);
|
||||
if(ret)
|
||||
return ret;
|
||||
value[0] |= SLC_RXLINK_START;
|
||||
ret = sif_write_reg_window(epub, SLC_RX_LINK, (u8 *)value);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sif_had_io_enable(struct esp_pub *epub)
|
||||
{
|
||||
u32 *p_tbuf = NULL;
|
||||
int ret;
|
||||
|
||||
p_tbuf = kzalloc(sizeof(u32), GFP_KERNEL);
|
||||
if(p_tbuf == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
*p_tbuf = SLC_TXEOF_ENA | (0x4 << SLC_FIFO_MAP_ENA_S) | SLC_TX_DUMMY_MODE | SLC_HDA_MAP_128K | (0xFE << SLC_TX_PUSH_IDLE_NUM_S);
|
||||
ret = sif_write_reg_window(epub, SLC_BRIDGE_CONF, (u8 *)p_tbuf);
|
||||
|
||||
if(ret)
|
||||
goto _err;
|
||||
|
||||
*p_tbuf = 0x30;
|
||||
ret = esp_common_write_with_addr((epub), SLC_HOST_CONF_W4 + 1, (u8 *)p_tbuf, 1, ESP_SIF_NOSYNC);
|
||||
|
||||
if(ret)
|
||||
goto _err;
|
||||
//set w3 0
|
||||
*p_tbuf = 0x1;
|
||||
ret = esp_common_write_with_addr((epub), SLC_HOST_CONF_W3, (u8 *)p_tbuf, 1, ESP_SIF_NOSYNC);
|
||||
|
||||
_err:
|
||||
kfree(p_tbuf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
typedef enum _SDIO_INTR_MODE {
|
||||
SDIO_INTR_IB = 0,
|
||||
SDIO_INTR_OOB_TOGGLE,
|
||||
SDIO_INTR_OOB_HIGH_LEVEL,
|
||||
SDIO_INTR_OOB_LOW_LEVEL,
|
||||
} SDIO_INTR_MODE;
|
||||
|
||||
#define GEN_GPIO_SEL(_gpio_num, _sel_func, _intr_mode, _offset) (((_offset)<< 9 ) |((_intr_mode) << 7)|((_sel_func) << 4)|(_gpio_num))
|
||||
//bit[3:0] = gpio num, 2
|
||||
//bit[6:4] = gpio sel func, 0
|
||||
//bit[8:7] = gpio intr mode, SDIO_INTR_OOB_TOGGLE
|
||||
//bit[15:9] = register offset, 0x38
|
||||
|
||||
u16 gpio_sel_sets[17] = {
|
||||
GEN_GPIO_SEL(0, 0, SDIO_INTR_OOB_TOGGLE, 0x34),//GPIO0
|
||||
GEN_GPIO_SEL(1, 3, SDIO_INTR_OOB_TOGGLE, 0x18),//U0TXD
|
||||
GEN_GPIO_SEL(2, 0, SDIO_INTR_OOB_TOGGLE, 0x38),//GPIO2
|
||||
GEN_GPIO_SEL(3, 3, SDIO_INTR_OOB_TOGGLE, 0x14),//U0RXD
|
||||
GEN_GPIO_SEL(4, 0, SDIO_INTR_OOB_TOGGLE, 0x3C),//GPIO4
|
||||
GEN_GPIO_SEL(5, 0, SDIO_INTR_OOB_TOGGLE, 0x40),//GPIO5
|
||||
GEN_GPIO_SEL(6, 3, SDIO_INTR_OOB_TOGGLE, 0x1C),//SD_CLK
|
||||
GEN_GPIO_SEL(7, 3, SDIO_INTR_OOB_TOGGLE, 0x20),//SD_DATA0
|
||||
GEN_GPIO_SEL(8, 3, SDIO_INTR_OOB_TOGGLE, 0x24),//SD_DATA1
|
||||
GEN_GPIO_SEL(9, 3, SDIO_INTR_OOB_TOGGLE, 0x28),//SD_DATA2
|
||||
GEN_GPIO_SEL(10, 3, SDIO_INTR_OOB_TOGGLE, 0x2C),//SD_DATA3
|
||||
GEN_GPIO_SEL(11, 3, SDIO_INTR_OOB_TOGGLE, 0x30),//SD_CMD
|
||||
GEN_GPIO_SEL(12, 3, SDIO_INTR_OOB_TOGGLE, 0x04),//MTDI
|
||||
GEN_GPIO_SEL(13, 3, SDIO_INTR_OOB_TOGGLE, 0x08),//MTCK
|
||||
GEN_GPIO_SEL(14, 3, SDIO_INTR_OOB_TOGGLE, 0x0C),//MTMS
|
||||
GEN_GPIO_SEL(15, 3, SDIO_INTR_OOB_TOGGLE, 0x10),//MTDO
|
||||
//pls do not change sel before, if you want to change intr mode,change the one blow
|
||||
//GEN_GPIO_SEL(2, 0, SDIO_INTR_OOB_TOGGLE, 0x38)
|
||||
GEN_GPIO_SEL(2, 0, SDIO_INTR_OOB_LOW_LEVEL, 0x38)
|
||||
};
|
||||
#if defined(USE_EXT_GPIO)
|
||||
u16 gpio_forbidden = 0;
|
||||
#endif
|
||||
|
||||
int sif_interrupt_target(struct esp_pub *epub, u8 index)
|
||||
{
|
||||
u8 low_byte = BIT(index);
|
||||
return esp_common_writebyte_with_addr(epub, SLC_HOST_CONF_W4 + 2, low_byte, ESP_SIF_NOSYNC);
|
||||
}
|
||||
|
||||
#ifdef USE_EXT_GPIO
|
||||
int sif_config_gpio_mode(struct esp_pub *epub, u8 gpio_num, u8 gpio_mode)
|
||||
{
|
||||
u32 *p_tbuf = NULL;
|
||||
int err;
|
||||
|
||||
if((BIT(gpio_num) & gpio_forbidden) || gpio_num > 15)
|
||||
return -EINVAL;
|
||||
|
||||
p_tbuf = kzalloc(sizeof(u32), GFP_KERNEL);
|
||||
if(p_tbuf == NULL)
|
||||
return -ENOMEM;
|
||||
*p_tbuf = (gpio_mode << 16) | gpio_sel_sets[gpio_num];
|
||||
err = esp_common_write_with_addr(epub, SLC_HOST_CONF_W1, (u8*)p_tbuf, sizeof(u32), ESP_SIF_NOSYNC);
|
||||
kfree(p_tbuf);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return sif_interrupt_target(epub, 4);
|
||||
}
|
||||
|
||||
int sif_set_gpio_output(struct esp_pub *epub, u16 mask, u16 value)
|
||||
{
|
||||
u32 *p_tbuf = NULL;
|
||||
int err;
|
||||
|
||||
mask &= ~gpio_forbidden;
|
||||
p_tbuf = kzalloc(sizeof(u32), GFP_KERNEL);
|
||||
if(p_tbuf == NULL)
|
||||
return -ENOMEM;
|
||||
*p_tbuf = (mask << 16) | value;
|
||||
err = esp_common_write_with_addr(epub, SLC_HOST_CONF_W2, (u8*)p_tbuf, sizeof(u32), ESP_SIF_NOSYNC);
|
||||
kfree(p_tbuf);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return sif_interrupt_target(epub, 5);
|
||||
}
|
||||
|
||||
int sif_get_gpio_intr(struct esp_pub *epub, u16 intr_mask, u16 *value)
|
||||
{
|
||||
u32 *p_tbuf = NULL;
|
||||
int err;
|
||||
|
||||
p_tbuf = kzalloc(sizeof(u32), GFP_KERNEL);
|
||||
if(p_tbuf == NULL)
|
||||
return -ENOMEM;
|
||||
*p_tbuf = 0;
|
||||
err = esp_common_read_with_addr(epub, SLC_HOST_CONF_W3, (u8*)p_tbuf, sizeof(u32), ESP_SIF_NOSYNC);
|
||||
if (err){
|
||||
kfree(p_tbuf);
|
||||
return err;
|
||||
}
|
||||
|
||||
*value = *p_tbuf & intr_mask;
|
||||
kfree(p_tbuf);
|
||||
if(*value == 0)
|
||||
return 0;
|
||||
return sif_interrupt_target(epub, 6);
|
||||
}
|
||||
|
||||
int sif_get_gpio_input(struct esp_pub *epub, u16 *mask, u16 *value)
|
||||
{
|
||||
u32 *p_tbuf = NULL;
|
||||
int err;
|
||||
|
||||
err = sif_interrupt_target(epub, 3);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
udelay(20);
|
||||
p_tbuf = kzalloc(sizeof(u32), GFP_KERNEL);
|
||||
if(p_tbuf == NULL)
|
||||
return -ENOMEM;
|
||||
*p_tbuf = 0;
|
||||
err = esp_common_read_with_addr(epub, SLC_HOST_CONF_W3, (u8*)p_tbuf, sizeof(u32), ESP_SIF_NOSYNC);
|
||||
if (err){
|
||||
kfree(p_tbuf);
|
||||
return err;
|
||||
}
|
||||
|
||||
*mask = *p_tbuf >> 16;
|
||||
*value = *p_tbuf & *mask;
|
||||
kfree(p_tbuf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void check_target_id(struct esp_pub *epub)
|
||||
{
|
||||
u32 date;
|
||||
int err = 0;
|
||||
int i;
|
||||
|
||||
EPUB_CTRL_CHECK(epub, _err);
|
||||
|
||||
sif_lock_bus(epub);
|
||||
|
||||
for(i = 0; i < 4; i++) {
|
||||
err = esp_common_readbyte_with_addr(epub, SLC_HOST_DATE + i, (u8 *)&date + i, ESP_SIF_NOSYNC);
|
||||
err = esp_common_readbyte_with_addr(epub, SLC_HOST_ID + i, (u8 *)&EPUB_TO_CTRL(epub)->target_id + i, ESP_SIF_NOSYNC);
|
||||
}
|
||||
|
||||
sif_unlock_bus(epub);
|
||||
|
||||
esp_dbg(ESP_DBG_LOG, "\n\n \t\t SLC data 0x%08x, ID 0x%08x\n\n", date, EPUB_TO_CTRL(epub)->target_id);
|
||||
|
||||
switch(EPUB_TO_CTRL(epub)->target_id) {
|
||||
case 0x100:
|
||||
EPUB_TO_CTRL(epub)->slc_window_end_addr = 0x20000;
|
||||
break;
|
||||
case 0x600:
|
||||
EPUB_TO_CTRL(epub)->slc_window_end_addr = 0x20000 - 0x800;
|
||||
|
||||
do{
|
||||
u16 gpio_sel;
|
||||
u8 low_byte = 0;
|
||||
u8 high_byte = 0;
|
||||
u8 byte2 = 0;
|
||||
u8 byte3 = 0;
|
||||
#ifdef USE_OOB_INTR
|
||||
gpio_sel = gpio_sel_sets[16];
|
||||
low_byte = gpio_sel;
|
||||
high_byte = gpio_sel >> 8;
|
||||
#ifdef USE_EXT_GPIO
|
||||
gpio_forbidden |= BIT(gpio_sel & 0xf);
|
||||
#endif /* USE_EXT_GPIO */
|
||||
#endif /* USE_OOB_INTR */
|
||||
|
||||
if(sif_get_bt_config() == 1 && sif_get_rst_config() != 1){
|
||||
u8 gpio_num = sif_get_wakeup_gpio_config();
|
||||
gpio_sel = gpio_sel_sets[gpio_num];
|
||||
byte2 = gpio_sel;
|
||||
byte3 = gpio_sel >> 8;
|
||||
#ifdef USE_EXT_GPIO
|
||||
gpio_forbidden |= BIT(gpio_num);
|
||||
#endif
|
||||
}
|
||||
sif_lock_bus(epub);
|
||||
err = esp_common_writebyte_with_addr(epub, SLC_HOST_CONF_W1, low_byte, ESP_SIF_NOSYNC);
|
||||
err = esp_common_writebyte_with_addr(epub, SLC_HOST_CONF_W1 + 1, high_byte, ESP_SIF_NOSYNC);
|
||||
err = esp_common_writebyte_with_addr(epub, SLC_HOST_CONF_W1 + 2, byte2, ESP_SIF_NOSYNC);
|
||||
err = esp_common_writebyte_with_addr(epub, SLC_HOST_CONF_W1 + 3, byte3, ESP_SIF_NOSYNC);
|
||||
sif_unlock_bus(epub);
|
||||
}while(0);
|
||||
break;
|
||||
default:
|
||||
EPUB_TO_CTRL(epub)->slc_window_end_addr = 0x20000;
|
||||
break;
|
||||
}
|
||||
_err:
|
||||
return;
|
||||
}
|
||||
|
||||
u32 sif_get_blksz(struct esp_pub *epub)
|
||||
{
|
||||
EPUB_CTRL_CHECK(epub, _err);
|
||||
|
||||
return EPUB_TO_CTRL(epub)->slc_blk_sz;
|
||||
_err:
|
||||
return 512;
|
||||
}
|
||||
|
||||
u32 sif_get_target_id(struct esp_pub *epub)
|
||||
{
|
||||
EPUB_CTRL_CHECK(epub, _err);
|
||||
|
||||
return EPUB_TO_CTRL(epub)->target_id;
|
||||
_err:
|
||||
return 0x600;
|
||||
}
|
||||
|
||||
#ifdef ESP_USE_SDIO
|
||||
void sif_dsr(struct sdio_func *func)
|
||||
{
|
||||
struct esp_sdio_ctrl *sctrl = sdio_get_drvdata(func);
|
||||
#else
|
||||
void sif_dsr(struct spi_device *spi)
|
||||
{
|
||||
struct esp_spi_ctrl *sctrl = spi_get_drvdata(spi);
|
||||
u32 buf[1];
|
||||
#endif
|
||||
static int dsr_cnt = 0, real_intr_cnt = 0, bogus_intr_cnt = 0;
|
||||
struct slc_host_regs *regs = &(sctrl->slc_regs);
|
||||
esp_dbg(ESP_DBG_TRACE, " %s enter %d \n", __func__, dsr_cnt++);
|
||||
|
||||
#ifdef ESP_USE_SPI
|
||||
|
||||
if(sctrl->epub->wait_reset == 1)
|
||||
{
|
||||
mdelay(50);
|
||||
return;
|
||||
}
|
||||
|
||||
if(sctrl->epub->enable_int == 1)
|
||||
{
|
||||
sif_read_reg_window(sctrl->epub, SLC_INT_ENA, (u8 *)buf);
|
||||
buf[0] &= ~(SLC_RX_EOF_INT_ENA);
|
||||
buf[0] |= SLC_FRHOST_BIT2_INT_ENA;
|
||||
sif_write_reg_window(sctrl->epub, SLC_INT_ENA, (u8 *)buf);
|
||||
|
||||
sctrl->epub->enable_int = 0;
|
||||
}
|
||||
#endif
|
||||
atomic_set(&sctrl->irq_handling, 1);
|
||||
|
||||
#ifdef ESP_USE_SDIO
|
||||
sdio_release_host(sctrl->func);
|
||||
#endif
|
||||
|
||||
sif_lock_bus(sctrl->epub);
|
||||
|
||||
do {
|
||||
int ret =0;
|
||||
|
||||
memset(regs, 0x0, sizeof(struct slc_host_regs));
|
||||
|
||||
ret = esp_common_read_with_addr(sctrl->epub, REG_SLC_HOST_BASE + 8, (u8 *)regs, sizeof(struct slc_host_regs), ESP_SIF_NOSYNC);
|
||||
|
||||
if ( (regs->intr_raw & SLC_HOST_RX_ST) && (ret == 0) ) {
|
||||
esp_dbg(ESP_DBG_TRACE, "%s eal intr cnt: %d", __func__, ++real_intr_cnt);
|
||||
|
||||
esp_dsr(sctrl->epub);
|
||||
|
||||
} else {
|
||||
#ifdef ESP_ACK_INTERRUPT
|
||||
sif_platform_ack_interrupt(sctrl->epub);
|
||||
#endif //ESP_ACK_INTERRUPT
|
||||
sif_unlock_bus(sctrl->epub);
|
||||
|
||||
esp_dbg(ESP_DBG_TRACE, "%s bogus_intr_cnt %d\n", __func__, ++bogus_intr_cnt);
|
||||
}
|
||||
|
||||
#ifdef SIF_DEBUG_DSR_DUMP_REG
|
||||
dump_slc_regs(regs);
|
||||
#endif /* SIF_DEBUG_DUMP_DSR */
|
||||
|
||||
} while (0);
|
||||
|
||||
#ifdef ESP_USE_SDIO
|
||||
sdio_claim_host(func);
|
||||
#endif
|
||||
|
||||
atomic_set(&sctrl->irq_handling, 0);
|
||||
}
|
||||
|
||||
|
||||
struct slc_host_regs * sif_get_regs(struct esp_pub *epub)
|
||||
{
|
||||
EPUB_CTRL_CHECK(epub, _err);
|
||||
|
||||
return &EPUB_TO_CTRL(epub)->slc_regs;
|
||||
_err:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void sif_disable_target_interrupt(struct esp_pub *epub)
|
||||
{
|
||||
EPUB_FUNC_CHECK(epub, _exit);
|
||||
sif_lock_bus(epub);
|
||||
#ifdef HOST_RESET_BUG
|
||||
mdelay(10);
|
||||
#endif
|
||||
memset(EPUB_TO_CTRL(epub)->dma_buffer, 0x00, sizeof(u32));
|
||||
esp_common_write_with_addr(epub, SLC_HOST_INT_ENA, EPUB_TO_CTRL(epub)->dma_buffer, sizeof(u32), ESP_SIF_NOSYNC);
|
||||
#ifdef HOST_RESET_BUG
|
||||
mdelay(10);
|
||||
#endif
|
||||
|
||||
sif_unlock_bus(epub);
|
||||
|
||||
mdelay(1);
|
||||
|
||||
sif_lock_bus(epub);
|
||||
sif_interrupt_target(epub, 7);
|
||||
sif_unlock_bus(epub);
|
||||
_exit:
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef SIF_DEBUG_DSR_DUMP_REG
|
||||
static void dump_slc_regs(struct slc_host_regs *regs)
|
||||
{
|
||||
esp_dbg(ESP_DBG_TRACE, "\n\n ------- %s --------------\n", __func__);
|
||||
|
||||
esp_dbg(ESP_DBG_TRACE, " \
|
||||
intr_raw 0x%08X \t \n \
|
||||
state_w0 0x%08X \t state_w1 0x%08X \n \
|
||||
config_w0 0x%08X \t config_w1 0x%08X \n \
|
||||
intr_status 0x%08X \t config_w2 0x%08X \n \
|
||||
config_w3 0x%08X \t config_w4 0x%08X \n \
|
||||
token_wdata 0x%08X \t intr_clear 0x%08X \n \
|
||||
intr_enable 0x%08X \n\n", regs->intr_raw, \
|
||||
regs->state_w0, regs->state_w1, regs->config_w0, regs->config_w1, \
|
||||
regs->intr_status, \
|
||||
regs->config_w2, regs->config_w3, regs->config_w4, regs->token_wdata, \
|
||||
regs->intr_clear, regs->intr_enable);
|
||||
}
|
||||
#endif /* SIF_DEBUG_DSR_DUMP_REG */
|
||||
|
||||
static int bt_config = 0;
|
||||
void sif_record_bt_config(int value)
|
||||
{
|
||||
bt_config = value;
|
||||
}
|
||||
|
||||
int sif_get_bt_config(void)
|
||||
{
|
||||
return bt_config;
|
||||
}
|
||||
|
||||
static int rst_config = 0;
|
||||
void sif_record_rst_config(int value)
|
||||
{
|
||||
rst_config = value;
|
||||
}
|
||||
|
||||
int sif_get_rst_config(void)
|
||||
{
|
||||
return rst_config;
|
||||
}
|
||||
|
||||
static int ate_test = 0;
|
||||
void sif_record_ate_config(int value)
|
||||
{
|
||||
ate_test =value;
|
||||
}
|
||||
|
||||
int sif_get_ate_config(void)
|
||||
{
|
||||
return ate_test;
|
||||
}
|
||||
|
||||
static int retry_reset = 0;
|
||||
void sif_record_retry_config(void)
|
||||
{
|
||||
retry_reset = 1;
|
||||
}
|
||||
|
||||
int sif_get_retry_config(void)
|
||||
{
|
||||
return retry_reset;
|
||||
}
|
||||
|
||||
static int wakeup_gpio = 12;
|
||||
void sif_record_wakeup_gpio_config(int value)
|
||||
{
|
||||
wakeup_gpio = value;
|
||||
}
|
||||
|
||||
int sif_get_wakeup_gpio_config(void)
|
||||
{
|
||||
return wakeup_gpio;
|
||||
}
|
||||
2329
drivers/net/wireless/esp8089/esp_mac80211.c
Executable file
2329
drivers/net/wireless/esp8089/esp_mac80211.c
Executable file
File diff suppressed because it is too large
Load Diff
36
drivers/net/wireless/esp8089/esp_mac80211.h
Normal file
36
drivers/net/wireless/esp8089/esp_mac80211.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2014 Espressif System.
|
||||
*
|
||||
* MAC80211 support module
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
#ifndef _ESP_MAC80211_H_
|
||||
#define _ESP_MAC80211_H_
|
||||
|
||||
struct esp_80211_wmm_ac_param {
|
||||
u8 aci_aifsn; /* AIFSN, ACM, ACI */
|
||||
u8 cw; /* ECWmin, ECWmax (CW = 2^ECW - 1) */
|
||||
u16 txop_limit;
|
||||
};
|
||||
|
||||
struct esp_80211_wmm_param_element {
|
||||
/* Element ID: 221 (0xdd); length: 24 */
|
||||
/* required fields for WMM version 1 */
|
||||
u8 oui[3]; /* 00:50:f2 */
|
||||
u8 oui_type; /* 2 */
|
||||
u8 oui_subtype; /* 1 */
|
||||
u8 version; /* 1 for WMM version 1.0 */
|
||||
u8 qos_info; /* AP/STA specif QoS info */
|
||||
u8 reserved; /* 0 */
|
||||
struct esp_80211_wmm_ac_param ac[4]; /* AC_BE, AC_BK, AC_VI, AC_VO */
|
||||
};
|
||||
#endif /* _ESP_MAC80211_H_ */
|
||||
269
drivers/net/wireless/esp8089/esp_main.c
Executable file
269
drivers/net/wireless/esp8089/esp_main.c
Executable file
@@ -0,0 +1,269 @@
|
||||
/*
|
||||
* Copyright (c) 2010 - 2014 Espressif System.
|
||||
*
|
||||
* main routine
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/sched.h>
|
||||
#include <net/cfg80211.h>
|
||||
#include <net/mac80211.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/moduleparam.h>
|
||||
|
||||
#include "esp_pub.h"
|
||||
#include "esp_sip.h"
|
||||
#include "esp_sif.h"
|
||||
#include "esp_debug.h"
|
||||
#include "esp_file.h"
|
||||
#include "esp_wl.h"
|
||||
|
||||
struct completion *gl_bootup_cplx = NULL;
|
||||
|
||||
#ifndef FPGA_DEBUG
|
||||
static int esp_download_fw(struct esp_pub * epub);
|
||||
#endif /* !FGPA_DEBUG */
|
||||
|
||||
static int modparam_no_txampdu = 0;
|
||||
static int modparam_no_rxampdu = 0;
|
||||
module_param_named(no_txampdu, modparam_no_txampdu, int, 0444);
|
||||
MODULE_PARM_DESC(no_txampdu, "Disable tx ampdu.");
|
||||
module_param_named(no_rxampdu, modparam_no_rxampdu, int, 0444);
|
||||
MODULE_PARM_DESC(no_rxampdu, "Disable rx ampdu.");
|
||||
|
||||
static char *modparam_eagle_path = "";
|
||||
module_param_named(eagle_path, modparam_eagle_path, charp, 0444);
|
||||
MODULE_PARM_DESC(eagle_path, "eagle path");
|
||||
|
||||
bool mod_support_no_txampdu()
|
||||
{
|
||||
return modparam_no_txampdu;
|
||||
}
|
||||
|
||||
bool mod_support_no_rxampdu()
|
||||
{
|
||||
return modparam_no_rxampdu;
|
||||
}
|
||||
|
||||
void mod_support_no_txampdu_set(bool value)
|
||||
{
|
||||
modparam_no_txampdu = value;
|
||||
}
|
||||
|
||||
char *mod_eagle_path_get(void)
|
||||
{
|
||||
if (modparam_eagle_path[0] == '\0')
|
||||
return NULL;
|
||||
|
||||
return modparam_eagle_path;
|
||||
}
|
||||
|
||||
int esp_pub_init_all(struct esp_pub *epub)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
/* completion for bootup event poll*/
|
||||
DECLARE_COMPLETION_ONSTACK(complete);
|
||||
atomic_set(&epub->ps.state, ESP_PM_OFF);
|
||||
if(epub->sdio_state == ESP_SDIO_STATE_FIRST_INIT){
|
||||
epub->sip = sip_attach(epub);
|
||||
if (epub->sip == NULL) {
|
||||
printk(KERN_ERR "%s sip alloc failed\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
esp_dump_var("esp_msg_level", NULL, &esp_msg_level, ESP_U32);
|
||||
|
||||
#ifdef ESP_ANDROID_LOGGER
|
||||
esp_dump_var("log_off", NULL, &log_off, ESP_U32);
|
||||
#endif /* ESP_ANDROID_LOGGER */
|
||||
} else {
|
||||
atomic_set(&epub->sip->state, SIP_PREPARE_BOOT);
|
||||
atomic_set(&epub->sip->tx_credits, 0);
|
||||
}
|
||||
|
||||
epub->sip->to_host_seq = 0;
|
||||
|
||||
#ifdef TEST_MODE
|
||||
if(sif_get_ate_config() != 0 && sif_get_ate_config() != 1 && sif_get_ate_config() !=6 )
|
||||
{
|
||||
esp_test_init(epub);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef FPGA_DEBUG
|
||||
ret = esp_download_fw(epub);
|
||||
#ifdef ESP_USE_SPI
|
||||
if(sif_get_ate_config() != 1)
|
||||
epub->enable_int = 1;
|
||||
#endif
|
||||
#ifdef TEST_MODE
|
||||
if(sif_get_ate_config() == 6)
|
||||
{
|
||||
sif_enable_irq(epub);
|
||||
mdelay(500);
|
||||
sif_disable_irq(epub);
|
||||
mdelay(1000);
|
||||
esp_test_init(epub);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
if (ret) {
|
||||
esp_dbg(ESP_DBG_ERROR, "download firmware failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_dbg(ESP_DBG_TRACE, "download firmware OK \n");
|
||||
#else
|
||||
sip_send_bootup(epub->sip);
|
||||
#endif /* FPGA_DEBUG */
|
||||
|
||||
gl_bootup_cplx = &complete;
|
||||
epub->wait_reset = 0;
|
||||
sif_enable_irq(epub);
|
||||
|
||||
if(epub->sdio_state == ESP_SDIO_STATE_SECOND_INIT || sif_get_ate_config() == 1){
|
||||
ret = sip_poll_bootup_event(epub->sip);
|
||||
} else {
|
||||
ret = sip_poll_resetting_event(epub->sip);
|
||||
if (ret == 0) {
|
||||
sif_lock_bus(epub);
|
||||
sif_interrupt_target(epub, 7);
|
||||
sif_unlock_bus(epub);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
gl_bootup_cplx = NULL;
|
||||
|
||||
if (sif_get_ate_config() == 1)
|
||||
ret = -EOPNOTSUPP;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
esp_dsr(struct esp_pub *epub)
|
||||
{
|
||||
sip_rx(epub);
|
||||
}
|
||||
|
||||
|
||||
struct esp_fw_hdr {
|
||||
u8 magic;
|
||||
u8 blocks;
|
||||
u8 pad[2];
|
||||
u32 entry_addr;
|
||||
} __packed;
|
||||
|
||||
struct esp_fw_blk_hdr {
|
||||
u32 load_addr;
|
||||
u32 data_len;
|
||||
} __packed;
|
||||
|
||||
#define ESP_FW_NAME1 "eagle_fw1.bin"
|
||||
#define ESP_FW_NAME2 "eagle_fw2.bin"
|
||||
#define ESP_FW_NAME3 "eagle_fw3.bin"
|
||||
|
||||
#ifndef FPGA_DEBUG
|
||||
static int esp_download_fw(struct esp_pub * epub)
|
||||
{
|
||||
#ifndef HAS_FW
|
||||
const struct firmware *fw_entry;
|
||||
#endif /* !HAS_FW */
|
||||
u8 * fw_buf = NULL;
|
||||
u32 offset = 0;
|
||||
int ret = 0;
|
||||
u8 blocks;
|
||||
struct esp_fw_hdr *fhdr;
|
||||
struct esp_fw_blk_hdr *bhdr=NULL;
|
||||
struct sip_cmd_bootup bootcmd;
|
||||
|
||||
#ifndef HAS_FW
|
||||
|
||||
if(sif_get_ate_config() == 1) {
|
||||
char * esp_fw_name = ESP_FW_NAME3;
|
||||
} else {
|
||||
char * esp_fw_name = epub->sdio_state == ESP_SDIO_STATE_FIRST_INIT ? ESP_FW_NAME1 : ESP_FW_NAME2;
|
||||
}
|
||||
ret = esp_request_firmware(&fw_entry, esp_fw_name, epub->dev);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
fw_buf = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);
|
||||
|
||||
esp_release_firmware(fw_entry);
|
||||
|
||||
if (fw_buf == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
#else
|
||||
|
||||
#include "eagle_fw1.h"
|
||||
#include "eagle_fw2.h"
|
||||
#include "eagle_fw3.h"
|
||||
if(sif_get_ate_config() == 1){
|
||||
fw_buf = &eagle_fw3[0];
|
||||
} else {
|
||||
fw_buf = epub->sdio_state == ESP_SDIO_STATE_FIRST_INIT ? &eagle_fw1[0] : &eagle_fw2[0];
|
||||
}
|
||||
#endif /* HAS_FW */
|
||||
|
||||
fhdr = (struct esp_fw_hdr *)fw_buf;
|
||||
|
||||
if (fhdr->magic != 0xE9) {
|
||||
esp_dbg(ESP_DBG_ERROR, "%s wrong magic! \n", __func__);
|
||||
goto _err;
|
||||
}
|
||||
|
||||
blocks = fhdr->blocks;
|
||||
offset += sizeof(struct esp_fw_hdr);
|
||||
|
||||
while (blocks) {
|
||||
|
||||
bhdr = (struct esp_fw_blk_hdr *)(&fw_buf[offset]);
|
||||
offset += sizeof(struct esp_fw_blk_hdr);
|
||||
|
||||
ret = sip_write_memory(epub->sip, bhdr->load_addr, &fw_buf[offset], bhdr->data_len);
|
||||
|
||||
if (ret) {
|
||||
esp_dbg(ESP_DBG_ERROR, "%s Failed to write fw, err: %d\n", __func__, ret);
|
||||
goto _err;
|
||||
}
|
||||
|
||||
blocks--;
|
||||
offset += bhdr->data_len;
|
||||
}
|
||||
|
||||
/* TODO: last byte should be the checksum and skip checksum for now */
|
||||
|
||||
bootcmd.boot_addr = fhdr->entry_addr;
|
||||
ret = sip_send_cmd(epub->sip, SIP_CMD_BOOTUP, sizeof(struct sip_cmd_bootup), &bootcmd);
|
||||
|
||||
if (ret) {
|
||||
goto _err;
|
||||
}
|
||||
|
||||
_err:
|
||||
#ifndef HAS_FW
|
||||
kfree(fw_buf);
|
||||
#endif /* !HAS_FW */
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* !FPGA_DEBUG */
|
||||
6
drivers/net/wireless/esp8089/esp_path.h
Executable file
6
drivers/net/wireless/esp8089/esp_path.h
Executable file
@@ -0,0 +1,6 @@
|
||||
#ifndef _ESP_PATH_H_
|
||||
#define _ESP_PATH_H_
|
||||
#define FWPATH "/system/lib/modules"
|
||||
//module_param_string(fwpath, fwpath, sizeof(fwpath), 0644);
|
||||
|
||||
#endif /* _ESP_PATH_H_ */
|
||||
77
drivers/net/wireless/esp8089/esp_pm.c
Executable file
77
drivers/net/wireless/esp8089/esp_pm.c
Executable file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2010 -2014 Espressif System.
|
||||
*
|
||||
* power save control of system
|
||||
*/
|
||||
#ifdef CONFIG_HAS_WAKELOCK
|
||||
#include <linux/wakelock.h>
|
||||
#endif
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
#include <linux/earlysuspend.h>
|
||||
#endif
|
||||
#include "esp_pub.h"
|
||||
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
|
||||
static void esp_early_suspend(struct early_suspend *h)
|
||||
{
|
||||
printk("%s\n", __func__);
|
||||
}
|
||||
|
||||
static void esp_late_resume(struct early_suspend*h)
|
||||
{
|
||||
printk("%s\n", __func__);
|
||||
}
|
||||
|
||||
static struct early_suspend esp_early_suspend_ctrl = {
|
||||
.suspend = esp_early_suspend,
|
||||
.resume = esp_late_resume,
|
||||
.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN - 20,
|
||||
};
|
||||
#endif /* EARLYSUSPEND */
|
||||
|
||||
void esp_register_early_suspend(void)
|
||||
{
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
register_early_suspend(&esp_early_suspend_ctrl);
|
||||
#endif
|
||||
}
|
||||
|
||||
void esp_unregister_early_suspend(void)
|
||||
{
|
||||
#ifdef CONFIG_HAS_EARLYSUSPEND
|
||||
unregister_early_suspend(&esp_early_suspend_ctrl);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HAS_WAKELOCK
|
||||
static struct wake_lock esp_wake_lock_;
|
||||
#endif /* WAKELOCK */
|
||||
|
||||
void esp_wakelock_init(void)
|
||||
{
|
||||
#ifdef CONFIG_HAS_WAKELOCK
|
||||
wake_lock_init(&esp_wake_lock_, WAKE_LOCK_SUSPEND, "eagle");
|
||||
#endif
|
||||
}
|
||||
|
||||
void esp_wakelock_destroy(void)
|
||||
{
|
||||
#ifdef CONFIG_HAS_WAKELOCK
|
||||
wake_lock_destroy(&esp_wake_lock_);
|
||||
#endif
|
||||
}
|
||||
|
||||
void esp_wake_lock(void)
|
||||
{
|
||||
#ifdef CONFIG_HAS_WAKELOCK
|
||||
wake_lock(&esp_wake_lock_);
|
||||
#endif
|
||||
}
|
||||
|
||||
void esp_wake_unlock(void)
|
||||
{
|
||||
#ifdef CONFIG_HAS_WAKELOCK
|
||||
wake_unlock(&esp_wake_lock_);
|
||||
#endif
|
||||
}
|
||||
254
drivers/net/wireless/esp8089/esp_pub.h
Executable file
254
drivers/net/wireless/esp8089/esp_pub.h
Executable file
@@ -0,0 +1,254 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2014 Espressif System.
|
||||
*
|
||||
* wlan device header file
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef _ESP_PUB_H_
|
||||
#define _ESP_PUB_H_
|
||||
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/sched.h>
|
||||
#include <net/mac80211.h>
|
||||
#include <net/cfg80211.h>
|
||||
#include <linux/nl80211.h>
|
||||
#include <linux/version.h>
|
||||
#include "sip2_common.h"
|
||||
|
||||
// to support kernel < 2.6.28 there's no ieee80211_sta
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28))
|
||||
#include <net/wireless.h>
|
||||
#endif
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
|
||||
enum ieee80211_band {
|
||||
IEEE80211_BAND_2GHZ = NL80211_BAND_2GHZ,
|
||||
IEEE80211_BAND_5GHZ = NL80211_BAND_5GHZ,
|
||||
IEEE80211_BAND_60GHZ = NL80211_BAND_60GHZ,
|
||||
|
||||
/* keep last */
|
||||
IEEE80211_NUM_BANDS
|
||||
};
|
||||
#endif
|
||||
|
||||
enum esp_sdio_state{
|
||||
ESP_SDIO_STATE_FIRST_INIT,
|
||||
ESP_SDIO_STATE_FIRST_NORMAL_EXIT,
|
||||
ESP_SDIO_STATE_FIRST_ERROR_EXIT,
|
||||
ESP_SDIO_STATE_SECOND_INIT,
|
||||
ESP_SDIO_STATE_SECOND_ERROR_EXIT,
|
||||
};
|
||||
|
||||
enum esp_tid_state {
|
||||
ESP_TID_STATE_INIT,
|
||||
ESP_TID_STATE_TRIGGER,
|
||||
ESP_TID_STATE_PROGRESS,
|
||||
ESP_TID_STATE_OPERATIONAL,
|
||||
ESP_TID_STATE_WAIT_STOP,
|
||||
ESP_TID_STATE_STOP,
|
||||
};
|
||||
|
||||
struct esp_tx_tid {
|
||||
u8 state;
|
||||
u8 cnt;
|
||||
u16 ssn;
|
||||
};
|
||||
|
||||
#define WME_NUM_TID 16
|
||||
struct esp_node {
|
||||
struct esp_tx_tid tid[WME_NUM_TID];
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
|
||||
struct ieee80211_sta *sta;
|
||||
#else
|
||||
u8 addr[ETH_ALEN];
|
||||
u16 aid;
|
||||
u64 supp_rates[IEEE80211_NUM_BANDS];
|
||||
struct ieee80211_ht_info ht_info;
|
||||
#endif
|
||||
u8 ifidx;
|
||||
u8 index;
|
||||
};
|
||||
|
||||
#define WME_AC_BE 2
|
||||
#define WME_AC_BK 3
|
||||
#define WME_AC_VI 1
|
||||
#define WME_AC_VO 0
|
||||
|
||||
struct llc_snap_hdr {
|
||||
u8 dsap;
|
||||
u8 ssap;
|
||||
u8 cntl;
|
||||
u8 org_code[3];
|
||||
__be16 eth_type;
|
||||
} __packed;
|
||||
|
||||
struct esp_vif {
|
||||
struct esp_pub *epub;
|
||||
u8 index;
|
||||
u32 beacon_interval;
|
||||
bool ap_up;
|
||||
struct timer_list beacon_timer;
|
||||
};
|
||||
|
||||
/* WLAN related, mostly... */
|
||||
/*struct hw_scan_timeout {
|
||||
struct delayed_work w;
|
||||
struct ieee80211_hw *hw;
|
||||
};*/
|
||||
|
||||
typedef struct esp_wl {
|
||||
u8 bssid[ETH_ALEN];
|
||||
u8 req_bssid[ETH_ALEN];
|
||||
|
||||
//struct hw_scan_timeout *hsd;
|
||||
struct cfg80211_scan_request *scan_req;
|
||||
atomic_t ptk_cnt;
|
||||
atomic_t gtk_cnt;
|
||||
atomic_t tkip_key_set;
|
||||
|
||||
/* so far only 2G band */
|
||||
struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
|
||||
|
||||
unsigned long flags;
|
||||
atomic_t off;
|
||||
} esp_wl_t;
|
||||
|
||||
typedef struct esp_hw_idx_map {
|
||||
u8 mac[ETH_ALEN];
|
||||
u8 flag;
|
||||
} esp_hw_idx_map_t;
|
||||
|
||||
#define ESP_WL_FLAG_RFKILL BIT(0)
|
||||
#define ESP_WL_FLAG_HW_REGISTERED BIT(1)
|
||||
#define ESP_WL_FLAG_CONNECT BIT(2)
|
||||
#define ESP_WL_FLAG_STOP_TXQ BIT(3)
|
||||
|
||||
#define ESP_PUB_MAX_VIF 2
|
||||
#define ESP_PUB_MAX_STA 4 //for one interface
|
||||
#define ESP_PUB_MAX_RXAMPDU 8 //for all interfaces
|
||||
|
||||
enum {
|
||||
ESP_PM_OFF = 0,
|
||||
ESP_PM_TURNING_ON,
|
||||
ESP_PM_ON,
|
||||
ESP_PM_TURNING_OFF, /* Do NOT change the order */
|
||||
};
|
||||
|
||||
struct esp_ps {
|
||||
u32 dtim_period;
|
||||
u32 max_sleep_period;
|
||||
unsigned long last_config_time;
|
||||
atomic_t state;
|
||||
bool nulldata_pm_on;
|
||||
};
|
||||
|
||||
struct esp_mac_prefix {
|
||||
u8 mac_index;
|
||||
u8 mac_addr_prefix[3];
|
||||
};
|
||||
|
||||
struct esp_pub {
|
||||
struct device *dev;
|
||||
#ifdef ESP_NO_MAC80211
|
||||
struct net_device *net_dev;
|
||||
struct wireless_dev *wdev;
|
||||
struct net_device_stats *net_stats;
|
||||
#else
|
||||
struct ieee80211_hw *hw;
|
||||
struct ieee80211_vif *vif;
|
||||
u8 vif_slot;
|
||||
#endif /* ESP_MAC80211 */
|
||||
|
||||
void *sif; /* serial interface control block, e.g. sdio */
|
||||
enum esp_sdio_state sdio_state;
|
||||
struct esp_sip *sip;
|
||||
struct esp_wl wl;
|
||||
struct esp_hw_idx_map hi_map[19];
|
||||
struct esp_hw_idx_map low_map[ESP_PUB_MAX_VIF][2];
|
||||
//u32 flags; //flags to represent rfkill switch,start
|
||||
u8 roc_flags; //0: not in remain on channel state, 1: in roc state
|
||||
|
||||
struct work_struct tx_work; /* attach to ieee80211 workqueue */
|
||||
/* latest mac80211 has multiple tx queue, but we stick with single queue now */
|
||||
spinlock_t rx_lock;
|
||||
spinlock_t tx_ampdu_lock;
|
||||
spinlock_t rx_ampdu_lock;
|
||||
spinlock_t tx_lock;
|
||||
struct mutex tx_mtx;
|
||||
struct sk_buff_head txq;
|
||||
atomic_t txq_stopped;
|
||||
|
||||
struct work_struct sendup_work; /* attach to ieee80211 workqueue */
|
||||
struct sk_buff_head txdoneq;
|
||||
struct sk_buff_head rxq;
|
||||
|
||||
struct workqueue_struct *esp_wkq;
|
||||
|
||||
//u8 bssid[ETH_ALEN];
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
|
||||
u32 rx_filter;
|
||||
unsigned long scan_permit;
|
||||
bool scan_permit_valid;
|
||||
struct delayed_work scan_timeout_work;
|
||||
u32 enodes_map;
|
||||
u8 rxampdu_map;
|
||||
u32 enodes_maps[ESP_PUB_MAX_VIF];
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28))
|
||||
struct esp_node nodes[ESP_PUB_MAX_STA + 1];
|
||||
#endif
|
||||
struct esp_node * enodes[ESP_PUB_MAX_STA + 1];
|
||||
struct esp_node * rxampdu_node[ESP_PUB_MAX_RXAMPDU];
|
||||
u8 rxampdu_tid[ESP_PUB_MAX_RXAMPDU];
|
||||
struct esp_ps ps;
|
||||
int enable_int;
|
||||
int wait_reset;
|
||||
};
|
||||
|
||||
typedef struct esp_pub esp_pub_t;
|
||||
|
||||
struct esp_pub *esp_pub_alloc_mac80211(struct device *dev);
|
||||
int esp_pub_dealloc_mac80211(struct esp_pub *epub);
|
||||
int esp_register_mac80211(struct esp_pub *epub);
|
||||
|
||||
int esp_pub_init_all(struct esp_pub *epub);
|
||||
|
||||
char *mod_eagle_path_get(void);
|
||||
|
||||
void esp_dsr(struct esp_pub *epub);
|
||||
void hw_scan_done(struct esp_pub *epub, bool aborted);
|
||||
void esp_rocdone_process(struct ieee80211_hw *hw, struct sip_evt_roc *report);
|
||||
|
||||
void esp_ps_config(struct esp_pub *epub, struct esp_ps *ps, bool on);
|
||||
|
||||
|
||||
void esp_register_early_suspend(void);
|
||||
void esp_unregister_early_suspend(void);
|
||||
void esp_wakelock_init(void);
|
||||
void esp_wakelock_destroy(void);
|
||||
void esp_wake_lock(void);
|
||||
void esp_wake_unlock(void);
|
||||
struct esp_node * esp_get_node_by_addr(struct esp_pub * epub, const u8 *addr);
|
||||
struct esp_node * esp_get_node_by_index(struct esp_pub * epub, u8 index);
|
||||
int esp_get_empty_rxampdu(struct esp_pub * epub, const u8 *addr, u8 tid);
|
||||
int esp_get_exist_rxampdu(struct esp_pub * epub, const u8 *addr, u8 tid);
|
||||
|
||||
#ifdef TEST_MODE
|
||||
int test_init_netlink(struct esp_sip *sip);
|
||||
void test_exit_netlink(void);
|
||||
void esp_test_cmd_event(u32 cmd_type, char *reply_info);
|
||||
void esp_test_init(struct esp_pub *epub);
|
||||
#endif
|
||||
#endif /* _ESP_PUB_H_ */
|
||||
301
drivers/net/wireless/esp8089/esp_sif.h
Executable file
301
drivers/net/wireless/esp8089/esp_sif.h
Executable file
@@ -0,0 +1,301 @@
|
||||
/*
|
||||
* Copyright (c) 2011 - 2014 Espressif System.
|
||||
*
|
||||
* Serial I/F wrapper layer for eagle WLAN device,
|
||||
* abstraction of buses like SDIO/SIP, and provides
|
||||
* flow control for tx/rx layer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef _ESP_SIF_H_
|
||||
#define _ESP_SIF_H_
|
||||
|
||||
#include "esp_pub.h"
|
||||
#include <linux/mmc/host.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
/*
|
||||
* H/W SLC module definitions
|
||||
*/
|
||||
|
||||
#define SIF_SLC_BLOCK_SIZE 512
|
||||
|
||||
|
||||
/* S/W struct mapping to slc registers */
|
||||
typedef struct slc_host_regs {
|
||||
/* do NOT read token_rdata
|
||||
*
|
||||
u32 pf_data;
|
||||
u32 token_rdata;
|
||||
*/
|
||||
u32 intr_raw;
|
||||
u32 state_w0;
|
||||
u32 state_w1;
|
||||
u32 config_w0;
|
||||
u32 config_w1;
|
||||
u32 intr_status;
|
||||
u32 config_w2;
|
||||
u32 config_w3;
|
||||
u32 config_w4;
|
||||
u32 token_wdata;
|
||||
u32 intr_clear;
|
||||
u32 intr_enable;
|
||||
} sif_slc_reg_t;
|
||||
|
||||
|
||||
enum io_sync_type {
|
||||
ESP_SIF_NOSYNC = 0,
|
||||
ESP_SIF_SYNC,
|
||||
};
|
||||
|
||||
#ifdef ESP_USE_SDIO
|
||||
typedef struct esp_sdio_ctrl {
|
||||
struct sdio_func *func;
|
||||
#else
|
||||
typedef struct esp_spi_ctrl {
|
||||
struct spi_device *spi;
|
||||
#endif
|
||||
struct esp_pub *epub;
|
||||
|
||||
|
||||
struct list_head free_req;
|
||||
|
||||
u8 *dma_buffer;
|
||||
|
||||
spinlock_t scat_lock;
|
||||
struct list_head scat_req;
|
||||
|
||||
bool off;
|
||||
atomic_t irq_handling;
|
||||
#ifdef ESP_USE_SDIO
|
||||
const struct sdio_device_id *id;
|
||||
#else
|
||||
const struct spi_device_id *id;
|
||||
#endif
|
||||
u32 slc_blk_sz;
|
||||
u32 target_id;
|
||||
u32 slc_window_end_addr;
|
||||
|
||||
struct slc_host_regs slc_regs;
|
||||
atomic_t irq_installed;
|
||||
|
||||
#ifdef ESP_USE_SDIO
|
||||
} esp_sdio_ctrl_t;
|
||||
#else
|
||||
} esp_spi_ctrl_t;
|
||||
#endif
|
||||
|
||||
#ifdef ESP_USE_SPI
|
||||
struct esp_spi_resp {
|
||||
u32 max_dataW_resp_size;
|
||||
u32 max_dataR_resp_size;
|
||||
u32 max_block_dataW_resp_size;
|
||||
u32 max_block_dataR_resp_size;
|
||||
u32 max_cmd_resp_size;
|
||||
u32 data_resp_size_w;
|
||||
u32 data_resp_size_r;
|
||||
u32 block_w_data_resp_size_final;
|
||||
u32 block_r_data_resp_size_final;
|
||||
};
|
||||
#endif
|
||||
|
||||
#define SIF_TO_DEVICE 0x1
|
||||
#define SIF_FROM_DEVICE 0x2
|
||||
|
||||
#define SIF_SYNC 0x00000010
|
||||
#define SIF_ASYNC 0x00000020
|
||||
|
||||
#define SIF_BYTE_BASIS 0x00000040
|
||||
#define SIF_BLOCK_BASIS 0x00000080
|
||||
|
||||
#define SIF_FIXED_ADDR 0x00000100
|
||||
#define SIF_INC_ADDR 0x00000200
|
||||
|
||||
#ifdef ESP_USE_SDIO
|
||||
#define EPUB_CTRL_CHECK(_epub, _go_err) do{\
|
||||
if (_epub == NULL) {\
|
||||
ESSERT(0);\
|
||||
goto _go_err;\
|
||||
}\
|
||||
if ((_epub)->sif == NULL) {\
|
||||
ESSERT(0);\
|
||||
goto _go_err;\
|
||||
}\
|
||||
}while(0)
|
||||
|
||||
#define EPUB_FUNC_CHECK(_epub, _go_err) do{\
|
||||
if (_epub == NULL) {\
|
||||
ESSERT(0);\
|
||||
goto _go_err;\
|
||||
}\
|
||||
if ((_epub)->sif == NULL) {\
|
||||
ESSERT(0);\
|
||||
goto _go_err;\
|
||||
}\
|
||||
if (((struct esp_sdio_ctrl *)(_epub)->sif)->func == NULL) {\
|
||||
ESSERT(0);\
|
||||
goto _go_err;\
|
||||
}\
|
||||
}while(0)
|
||||
|
||||
#define EPUB_TO_CTRL(_epub) (((struct esp_sdio_ctrl *)(_epub)->sif))
|
||||
|
||||
#define EPUB_TO_FUNC(_epub) (((struct esp_sdio_ctrl *)(_epub)->sif)->func)
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef ESP_USE_SPI
|
||||
#define EPUB_CTRL_CHECK(_epub, _go_err) do{\
|
||||
if (_epub == NULL) {\
|
||||
ESSERT(0);\
|
||||
goto _go_err;\
|
||||
}\
|
||||
if ((_epub)->sif == NULL) {\
|
||||
ESSERT(0);\
|
||||
goto _go_err;\
|
||||
}\
|
||||
}while(0)
|
||||
|
||||
#define EPUB_FUNC_CHECK(_epub, _go_err) do{\
|
||||
if (_epub == NULL) {\
|
||||
ESSERT(0);\
|
||||
goto _go_err;\
|
||||
}\
|
||||
if ((_epub)->sif == NULL) {\
|
||||
ESSERT(0);\
|
||||
goto _go_err;\
|
||||
}\
|
||||
if (((struct esp_spi_ctrl *)(_epub)->sif)->spi == NULL) {\
|
||||
ESSERT(0);\
|
||||
goto _go_err;\
|
||||
}\
|
||||
}while(0)
|
||||
|
||||
#define EPUB_TO_CTRL(_epub) (((struct esp_spi_ctrl *)(_epub)->sif))
|
||||
|
||||
#define EPUB_TO_FUNC(_epub) (((struct esp_spi_ctrl *)(_epub)->sif)->spi)
|
||||
#endif
|
||||
|
||||
void sdio_io_writeb(struct esp_pub *epub, u8 value, int addr, int *res);
|
||||
u8 sdio_io_readb(struct esp_pub *epub, int addr, int *res);
|
||||
|
||||
|
||||
void sif_enable_irq(struct esp_pub *epub);
|
||||
void sif_disable_irq(struct esp_pub *epub);
|
||||
void sif_disable_target_interrupt(struct esp_pub *epub);
|
||||
|
||||
u32 sif_get_blksz(struct esp_pub *epub);
|
||||
u32 sif_get_target_id(struct esp_pub *epub);
|
||||
|
||||
#ifdef ESP_USE_SDIO
|
||||
void sif_dsr(struct sdio_func *func);
|
||||
int sif_io_raw(struct esp_pub *epub, u32 addr, u8 *buf, u32 len, u32 flag);
|
||||
int sif_io_sync(struct esp_pub *epub, u32 addr, u8 *buf, u32 len, u32 flag);
|
||||
int sif_io_async(struct esp_pub *epub, u32 addr, u8 *buf, u32 len, u32 flag, void * context);
|
||||
int sif_lldesc_read_sync(struct esp_pub *epub, u8 *buf, u32 len);
|
||||
int sif_lldesc_write_sync(struct esp_pub *epub, u8 *buf, u32 len);
|
||||
int sif_lldesc_read_raw(struct esp_pub *epub, u8 *buf, u32 len, bool noround);
|
||||
int sif_lldesc_write_raw(struct esp_pub *epub, u8 *buf, u32 len);
|
||||
void sif_platform_check_r1_ready(struct esp_pub *epub);
|
||||
#endif
|
||||
|
||||
#ifdef ESP_USE_SPI
|
||||
enum if_dummymode {
|
||||
NOT_DUMMYMODE = 0,
|
||||
DUMMYMODE,
|
||||
};
|
||||
|
||||
#ifdef REGISTER_SPI_BOARD_INFO
|
||||
void sif_platform_register_board_info(void);
|
||||
#endif
|
||||
|
||||
void sif_dsr(struct spi_device *spi);
|
||||
int sif_spi_read_mix_nosync(struct spi_device *spi, unsigned int addr, unsigned char *buf, int len, int dummymode);
|
||||
int sif_spi_epub_read_mix_sync(struct esp_pub *epub, unsigned int addr,unsigned char *buf, int len, int dummymode);
|
||||
int sif_spi_epub_read_mix_nosync(struct esp_pub *epub, unsigned int addr,unsigned char *buf, int len, int dummymode);
|
||||
int sif_spi_read_sync(struct esp_pub *epub, unsigned char *buf, int len, int dummymode);
|
||||
int sif_spi_read_nosync(struct esp_pub *epub, unsigned char *buf, int len, int dummymode, bool noround);
|
||||
|
||||
int sif_spi_write_mix_nosync(struct spi_device *spi, unsigned int addr, unsigned char *buf, int len, int dummymode);
|
||||
int sif_spi_epub_write_mix_sync(struct esp_pub *epub, unsigned int addr,unsigned char *buf, int len, int dummymode);
|
||||
int sif_spi_epub_write_mix_nosync(struct esp_pub *epub, unsigned int addr,unsigned char *buf, int len, int dummymode);
|
||||
int sif_spi_write_sync(struct esp_pub *epub, unsigned char *buf, int len, int dummymode);
|
||||
int sif_spi_write_nosync(struct esp_pub *epub, unsigned char *buf, int len, int dummymode);
|
||||
|
||||
int sif_platform_get_irq_no(void);
|
||||
int sif_platform_is_irq_occur(void);
|
||||
void sif_platform_irq_clear(void);
|
||||
void sif_platform_irq_mask(int enable_mask);
|
||||
int sif_platform_irq_init(void);
|
||||
void sif_platform_irq_deinit(void);
|
||||
|
||||
int sif_spi_write_bytes(struct spi_device *spi, unsigned int addr,unsigned char *dst, int count, int check_idle);
|
||||
int sif_spi_read_bytes(struct spi_device *spi, unsigned int addr,unsigned char *dst, int count, int check_idle);
|
||||
struct esp_spi_resp *sif_get_spi_resp(void);
|
||||
#endif
|
||||
|
||||
int esp_common_read(struct esp_pub *epub, u8 *buf, u32 len, int sync, bool noround);
|
||||
int esp_common_write(struct esp_pub *epub, u8 *buf, u32 len, int sync);
|
||||
int esp_common_read_with_addr(struct esp_pub *epub, u32 addr, u8 *buf, u32 len, int sync);
|
||||
int esp_common_write_with_addr(struct esp_pub *epub, u32 addr, u8 *buf, u32 len, int sync);
|
||||
|
||||
int esp_common_readbyte_with_addr(struct esp_pub *epub, u32 addr, u8 *buf, int sync);
|
||||
int esp_common_writebyte_with_addr(struct esp_pub *epub, u32 addr, u8 buf, int sync);
|
||||
|
||||
int sif_read_reg_window(struct esp_pub *epub, unsigned int reg_addr, unsigned char *value);
|
||||
int sif_write_reg_window(struct esp_pub *epub, unsigned int reg_addr, unsigned char *value);
|
||||
int sif_ack_target_read_err(struct esp_pub *epub);
|
||||
int sif_had_io_enable(struct esp_pub *epub);
|
||||
|
||||
struct slc_host_regs * sif_get_regs(struct esp_pub *epub);
|
||||
|
||||
void sif_lock_bus(struct esp_pub *epub);
|
||||
void sif_unlock_bus(struct esp_pub *epub);
|
||||
|
||||
void sif_platform_target_poweroff(void);
|
||||
void sif_platform_target_poweron(void);
|
||||
void sif_platform_target_speed(int high_speed);
|
||||
|
||||
void sif_platform_reset_target(void);
|
||||
void sif_platform_rescan_card(unsigned insert);
|
||||
|
||||
int sif_interrupt_target(struct esp_pub *epub, u8 index);
|
||||
#ifdef USE_EXT_GPIO
|
||||
int sif_config_gpio_mode(struct esp_pub *epub, u8 gpio_num, u8 gpio_mode);
|
||||
int sif_set_gpio_output(struct esp_pub *epub, u16 mask, u16 value);
|
||||
int sif_get_gpio_intr(struct esp_pub *epub, u16 intr_mask, u16 *value);
|
||||
int sif_get_gpio_input(struct esp_pub *epub, u16 *mask, u16 *value);
|
||||
#endif
|
||||
|
||||
void check_target_id(struct esp_pub *epub);
|
||||
|
||||
void sif_record_bt_config(int value);
|
||||
int sif_get_bt_config(void);
|
||||
void sif_record_rst_config(int value);
|
||||
int sif_get_rst_config(void);
|
||||
void sif_record_ate_config(int value);
|
||||
int sif_get_ate_config(void);
|
||||
void sif_record_retry_config(void);
|
||||
int sif_get_retry_config(void);
|
||||
void sif_record_wakeup_gpio_config(int value);
|
||||
int sif_get_wakeup_gpio_config(void);
|
||||
|
||||
#ifdef ESP_ACK_INTERRUPT
|
||||
//extern void sif_platform_ack_interrupt(struct mmc_host *mmc);
|
||||
extern void sif_platform_ack_interrupt(struct esp_pub *epub);
|
||||
#endif //ESP_ACK_INTERRUPT
|
||||
|
||||
#define sif_reg_read_sync(epub, addr, buf, len) sif_io_sync((epub), (addr), (buf), (len), SIF_FROM_DEVICE | SIF_BYTE_BASIS | SIF_INC_ADDR)
|
||||
|
||||
#define sif_reg_write_sync(epub, addr, buf, len) sif_io_sync((epub), (addr), (buf), (len), SIF_TO_DEVICE | SIF_BYTE_BASIS | SIF_INC_ADDR)
|
||||
|
||||
#endif /* _ESP_SIF_H_ */
|
||||
2375
drivers/net/wireless/esp8089/esp_sip.c
Executable file
2375
drivers/net/wireless/esp8089/esp_sip.c
Executable file
File diff suppressed because it is too large
Load Diff
174
drivers/net/wireless/esp8089/esp_sip.h
Executable file
174
drivers/net/wireless/esp8089/esp_sip.h
Executable file
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* Copyright (c) 2009- 2014 Espressif System.
|
||||
*
|
||||
* Serial Interconnctor Protocol
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef _ESP_SIP_H
|
||||
#define _ESP_SIP_H
|
||||
|
||||
#include "sip2_common.h"
|
||||
|
||||
#define SIP_CTRL_CREDIT_RESERVE 2
|
||||
|
||||
#define SIP_PKT_MAX_LEN (1024*16)
|
||||
|
||||
/* 16KB on normal X86 system, should check before porting to orhters */
|
||||
|
||||
#define SIP_TX_AGGR_BUF_SIZE (4 * PAGE_SIZE)
|
||||
#define SIP_RX_AGGR_BUF_SIZE (4 * PAGE_SIZE)
|
||||
|
||||
struct sk_buff;
|
||||
|
||||
struct sip_pkt {
|
||||
struct list_head list;
|
||||
|
||||
u8 * buf_begin;
|
||||
u32 buf_len;
|
||||
u8 * buf;
|
||||
};
|
||||
|
||||
typedef enum RECALC_CREDIT_STATE {
|
||||
RECALC_CREDIT_DISABLE = 0,
|
||||
RECALC_CREDIT_ENABLE = 1,
|
||||
} RECALC_CREDIT_STATE;
|
||||
|
||||
typedef enum ENQUEUE_PRIOR {
|
||||
ENQUEUE_PRIOR_TAIL = 0,
|
||||
ENQUEUE_PRIOR_HEAD,
|
||||
} ENQUEUE_PRIOR;
|
||||
|
||||
typedef enum SIP_STATE {
|
||||
SIP_INIT = 0,
|
||||
SIP_PREPARE_BOOT,
|
||||
SIP_BOOT,
|
||||
SIP_SEND_INIT,
|
||||
SIP_WAIT_BOOTUP,
|
||||
SIP_RUN,
|
||||
SIP_SUSPEND,
|
||||
SIP_STOP
|
||||
} SIP_STATE;
|
||||
|
||||
enum sip_notifier {
|
||||
SIP_TX_DONE = 1,
|
||||
SIP_RX_DONE = 2,
|
||||
};
|
||||
|
||||
#define SIP_CREDITS_LOW_THRESHOLD 64 //i.e. 4k
|
||||
|
||||
struct esp_sip {
|
||||
struct list_head free_ctrl_txbuf;
|
||||
struct list_head free_ctrl_rxbuf;
|
||||
|
||||
u32 rxseq; /* sip pkt seq, should match target side */
|
||||
u32 txseq;
|
||||
u32 txdataseq;
|
||||
|
||||
u8 to_host_seq;
|
||||
|
||||
atomic_t state;
|
||||
spinlock_t lock;
|
||||
atomic_t tx_credits;
|
||||
|
||||
atomic_t tx_ask_credit_update;
|
||||
|
||||
u8 * rawbuf; /* used in boot stage, free once chip is fully up */
|
||||
u8 * tx_aggr_buf;
|
||||
u8 * tx_aggr_write_ptr; /* update after insertion of each pkt */
|
||||
u8 * tx_aggr_lastpkt_ptr;
|
||||
|
||||
struct mutex rx_mtx;
|
||||
struct sk_buff_head rxq;
|
||||
struct work_struct rx_process_work;
|
||||
|
||||
u16 tx_blksz;
|
||||
u16 rx_blksz;
|
||||
|
||||
bool dump_rpbm_err;
|
||||
bool sendup_rpbm_pkt;
|
||||
bool rxabort_fixed;
|
||||
bool support_bgscan;
|
||||
u8 credit_to_reserve;
|
||||
|
||||
atomic_t credit_status;
|
||||
struct timer_list credit_timer;
|
||||
|
||||
atomic_t noise_floor;
|
||||
|
||||
u32 tx_tot_len; /* total len for one transaction */
|
||||
u32 rx_tot_len;
|
||||
|
||||
atomic_t rx_handling;
|
||||
atomic_t tx_data_pkt_queued;
|
||||
|
||||
#ifndef FAST_TX_STATUS
|
||||
atomic_t pending_tx_status;
|
||||
#endif /* !FAST_TX_STATUS */
|
||||
|
||||
atomic_t data_tx_stopped;
|
||||
atomic_t tx_stopped;
|
||||
|
||||
struct esp_pub *epub;
|
||||
};
|
||||
|
||||
int sip_rx(struct esp_pub * epub);
|
||||
//int sip_download_fw(struct esp_sip *sip, u32 load_addr, u32 boot_addr);
|
||||
|
||||
|
||||
int sip_write_memory(struct esp_sip *, u32 addr, u8* buf, u16 len);
|
||||
|
||||
void sip_credit_process(struct esp_pub *, u8 credits);
|
||||
|
||||
int sip_send_cmd(struct esp_sip *sip, int cid, u32 cmdlen, void * cmd);
|
||||
|
||||
struct esp_sip * sip_attach(struct esp_pub *);
|
||||
|
||||
int sip_post_init(struct esp_sip *sip, struct sip_evt_bootup2 *bevt);
|
||||
|
||||
void sip_detach(struct esp_sip *sip);
|
||||
|
||||
void sip_txq_process(struct esp_pub *epub);
|
||||
|
||||
struct sk_buff * sip_alloc_ctrl_skbuf(struct esp_sip *sip, u16 len, u32 cid);
|
||||
|
||||
void sip_free_ctrl_skbuff(struct esp_sip *sip, struct sk_buff* skb);
|
||||
|
||||
bool sip_queue_need_stop(struct esp_sip *sip);
|
||||
bool sip_queue_may_resume(struct esp_sip *sip);
|
||||
bool sip_tx_data_need_stop(struct esp_sip *sip);
|
||||
bool sip_tx_data_may_resume(struct esp_sip *sip);
|
||||
|
||||
void sip_tx_data_pkt_enqueue(struct esp_pub *epub, struct sk_buff *skb);
|
||||
void sip_rx_data_pkt_enqueue(struct esp_pub *epub, struct sk_buff *skb);
|
||||
|
||||
int sip_cmd_enqueue(struct esp_sip *sip, struct sk_buff *skb, int prior);
|
||||
|
||||
int sip_poll_bootup_event(struct esp_sip *sip);
|
||||
|
||||
int sip_poll_resetting_event(struct esp_sip *sip);
|
||||
|
||||
void sip_trigger_txq_process(struct esp_sip *sip);
|
||||
|
||||
void sip_send_chip_init(struct esp_sip *sip);
|
||||
|
||||
bool mod_support_no_txampdu(void);
|
||||
|
||||
bool mod_support_no_rxampdu(void);
|
||||
|
||||
void mod_support_no_txampdu_set(bool value);
|
||||
|
||||
#ifdef FPGA_DEBUG
|
||||
int sip_send_bootup(struct esp_sip *sip);
|
||||
#endif /* FPGA_DEBUG */
|
||||
void sip_debug_show(struct esp_sip *sip);
|
||||
#endif
|
||||
242
drivers/net/wireless/esp8089/esp_utils.c
Executable file
242
drivers/net/wireless/esp8089/esp_utils.c
Executable file
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
* Copyright (c) 2009 - 2014 Espressif System.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "linux/types.h"
|
||||
#include "linux/kernel.h"
|
||||
#include <linux/ieee80211.h>
|
||||
#include <net/mac80211.h>
|
||||
#include <linux/skbuff.h>
|
||||
|
||||
#include <net/tcp.h>
|
||||
#include <linux/ip.h>
|
||||
#include <asm/checksum.h>
|
||||
|
||||
#include "esp_pub.h"
|
||||
#include "esp_utils.h"
|
||||
#include "esp_wmac.h"
|
||||
#include "esp_debug.h"
|
||||
|
||||
/*
|
||||
* Convert IEEE channel number to MHz frequency.
|
||||
*/
|
||||
u32 esp_ieee2mhz(u8 chan)
|
||||
{
|
||||
if (chan == 14)
|
||||
return 2484;
|
||||
|
||||
if (chan < 14)
|
||||
return 2407 + chan*5;
|
||||
else
|
||||
return 2512 + ((chan-15)*20);
|
||||
//TODO, add 5GHz
|
||||
}
|
||||
enum {
|
||||
ESP_RATE_1_LONG = 0x0,
|
||||
ESP_RATE_2_LONG = 0x1,
|
||||
ESP_RATE_2_SHORT = 0x5,
|
||||
ESP_RATE_5_SHORT = 0x6,
|
||||
ESP_RATE_5_LONG = 0x2,
|
||||
ESP_RATE_11_SHORT = 0x7,
|
||||
ESP_RATE_11_LONG = 0x3,
|
||||
ESP_RATE_6 = 0xb,
|
||||
ESP_RATE_9 = 0xf,
|
||||
ESP_RATE_12 = 0xa,
|
||||
ESP_RATE_18 = 0xe,
|
||||
ESP_RATE_24 = 0x9,
|
||||
ESP_RATE_36 = 0xd,
|
||||
ESP_RATE_48 = 0x8,
|
||||
ESP_RATE_54 = 0xc,
|
||||
/* ESP_RATE_MCS0 =0x10,
|
||||
ESP_RATE_MCS1 =0x11,
|
||||
ESP_RATE_MCS2 =0x12,
|
||||
ESP_RATE_MCS3 =0x13,
|
||||
ESP_RATE_MCS4 =0x14,
|
||||
ESP_RATE_MCS5 =0x15,
|
||||
ESP_RATE_MCS6 =0x16,
|
||||
ESP_RATE_MCS7 =0x17,
|
||||
*/
|
||||
};
|
||||
|
||||
static u8 esp_rate_table[20] = {
|
||||
ESP_RATE_1_LONG,
|
||||
ESP_RATE_2_SHORT,
|
||||
ESP_RATE_5_SHORT,
|
||||
ESP_RATE_11_SHORT,
|
||||
ESP_RATE_6,
|
||||
ESP_RATE_9,
|
||||
ESP_RATE_12,
|
||||
ESP_RATE_18,
|
||||
ESP_RATE_24,
|
||||
ESP_RATE_36,
|
||||
ESP_RATE_48,
|
||||
ESP_RATE_54,
|
||||
/* ESP_RATE_MCS0,
|
||||
ESP_RATE_MCS1,
|
||||
ESP_RATE_MCS2,
|
||||
ESP_RATE_MCS3,
|
||||
ESP_RATE_MCS4,
|
||||
ESP_RATE_MCS5,
|
||||
ESP_RATE_MCS6,
|
||||
ESP_RATE_MCS7,
|
||||
*/
|
||||
};
|
||||
|
||||
s8 esp_wmac_rate2idx(u8 rate)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (rate == ESP_RATE_2_LONG)
|
||||
return 1;
|
||||
if (rate == ESP_RATE_5_LONG)
|
||||
return 2;
|
||||
if (rate == ESP_RATE_11_LONG)
|
||||
return 3;
|
||||
|
||||
for (i = 0; i < 20; i++) {
|
||||
if (rate == esp_rate_table[i])
|
||||
return i;
|
||||
}
|
||||
|
||||
esp_dbg(ESP_DBG_ERROR,"%s unknown rate 0x%02x \n", __func__, rate);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool esp_wmac_rxsec_error(u8 error)
|
||||
{
|
||||
return (error >= RX_SECOV_ERR && error <= RX_SECFIFO_TIMEOUT) || (error >= RX_WEPICV_ERR && error <= RX_WAPIMIC_ERR);
|
||||
}
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
|
||||
int esp_cipher2alg(int cipher)
|
||||
{
|
||||
if (cipher == WLAN_CIPHER_SUITE_TKIP)
|
||||
return ALG_TKIP;
|
||||
|
||||
if (cipher == WLAN_CIPHER_SUITE_CCMP)
|
||||
return ALG_CCMP;
|
||||
|
||||
if (cipher == WLAN_CIPHER_SUITE_WEP40 || cipher == WLAN_CIPHER_SUITE_WEP104)
|
||||
return ALG_WEP;
|
||||
|
||||
if (cipher == WLAN_CIPHER_SUITE_AES_CMAC)
|
||||
return ALG_AES_CMAC;
|
||||
|
||||
//printk("%s wrong cipher 0x%x!\n",__func__,cipher);
|
||||
|
||||
return -1;
|
||||
}
|
||||
#endif /* NEW_KERNEL */
|
||||
|
||||
#ifdef RX_CHECKSUM_TEST
|
||||
atomic_t g_iv_len;
|
||||
void esp_rx_checksum_test(struct sk_buff *skb)
|
||||
{
|
||||
static u32 ip_err = 0;
|
||||
static u32 tcp_err = 0;
|
||||
struct ieee80211_hdr *pwh = (struct ieee80211_hdr *)skb->data;
|
||||
int hdrlen = ieee80211_hdrlen(pwh->frame_control);
|
||||
|
||||
if(ieee80211_has_protected(pwh->frame_control))
|
||||
hdrlen += atomic_read(&g_iv_len);
|
||||
|
||||
if (ieee80211_is_data(pwh->frame_control)) {
|
||||
struct llc_snap_hdr * llc = (struct llc_snap_hdr *)(skb->data + hdrlen);
|
||||
if (ntohs(llc->eth_type) == ETH_P_IP) {
|
||||
int llclen = sizeof(struct llc_snap_hdr);
|
||||
struct iphdr *iph = (struct iphdr *)(skb->data + hdrlen + llclen);
|
||||
__sum16 csum_bak = iph->check;
|
||||
|
||||
iph->check = 0;
|
||||
iph->check = ip_fast_csum(iph, iph->ihl);
|
||||
if (iph->check != csum_bak) {
|
||||
esp_dbg(ESP_DBG_ERROR, "total ip checksum error %d\n", ++ip_err);
|
||||
}
|
||||
iph->check = csum_bak;
|
||||
|
||||
if (iph->protocol == 0x06) {
|
||||
struct tcphdr *tcph = (struct tcphdr *)(skb->data + hdrlen + llclen + iph->ihl * 4);
|
||||
int datalen = skb->len - (hdrlen + llclen + iph->ihl * 4);
|
||||
csum_bak = tcph->check;
|
||||
|
||||
tcph->check = 0;
|
||||
tcph->check = tcp_v4_check(datalen, iph->saddr, iph->daddr, csum_partial((char *)tcph, datalen, 0));
|
||||
if (tcph->check != csum_bak)
|
||||
{
|
||||
esp_dbg(ESP_DBG_ERROR, "total tcp checksum error %d\n", ++tcp_err);
|
||||
}
|
||||
tcph->check = csum_bak;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef GEN_ERR_CHECKSUM
|
||||
|
||||
void esp_gen_err_checksum(struct sk_buff *skb)
|
||||
{
|
||||
static u32 tx_seq = 0;
|
||||
if ((tx_seq++ % 16) == 0)
|
||||
{
|
||||
struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data;
|
||||
int hdrlen = ieee80211_hdrlen(hdr->frame_control);
|
||||
|
||||
if(ieee80211_has_protected(pwh->frame_control))
|
||||
hdrlen += IEEE80211_SKB_CB(skb)->control.hw_key->iv_len;
|
||||
|
||||
struct llc_snap_hdr * llc = (struct llc_snap_hdr *)(skb->data + hdrlen);
|
||||
if (ntohs(llc->eth_type) == ETH_P_IP) {
|
||||
int llclen = sizeof(struct llc_snap_hdr);
|
||||
struct iphdr *iph = (struct iphdr *)(skb->data + hdrlen + llclen);
|
||||
|
||||
iph->check = ~iph->check;
|
||||
|
||||
if (iph->protocol == 0x06) {
|
||||
struct tcphdr *tcph = (struct tcphdr *)(skb->data + hdrlen + llclen + iph->ihl * 4);
|
||||
tcph->check = ~tcph->check;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
bool esp_is_ip_pkt(struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data;
|
||||
int hdrlen;
|
||||
struct llc_snap_hdr * llc;
|
||||
|
||||
if (!ieee80211_is_data(hdr->frame_control))
|
||||
return false;
|
||||
|
||||
hdrlen = ieee80211_hdrlen(hdr->frame_control);
|
||||
if(ieee80211_has_protected(hdr->frame_control))
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 27))
|
||||
hdrlen += IEEE80211_SKB_CB(skb)->control.hw_key->iv_len;
|
||||
#else
|
||||
hdrlen += IEEE80211_SKB_CB(skb)->control.iv_len;
|
||||
#endif
|
||||
#ifdef RX_CHECKSUM_TEST
|
||||
atomic_set(&g_iv_len, IEEE80211_SKB_CB(skb)->control.hw_key->iv_len);
|
||||
#endif
|
||||
if(skb->len < hdrlen + sizeof(struct llc_snap_hdr))
|
||||
return false;
|
||||
llc = (struct llc_snap_hdr *)(skb->data + hdrlen);
|
||||
if (ntohs(llc->eth_type) != ETH_P_IP)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
44
drivers/net/wireless/esp8089/esp_utils.h
Executable file
44
drivers/net/wireless/esp8089/esp_utils.h
Executable file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2012 Espressif System.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef _ESP_UTILS_H_
|
||||
#define _ESP_UTILS_H_
|
||||
|
||||
#include "linux/types.h"
|
||||
#include <linux/version.h>
|
||||
|
||||
#ifndef BIT
|
||||
#define BIT(x) (0x1 << (x))
|
||||
#endif
|
||||
|
||||
u32 esp_ieee2mhz(u8 chan);
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
|
||||
enum ieee80211_key_alg {
|
||||
ALG_WEP,
|
||||
ALG_TKIP,
|
||||
ALG_CCMP,
|
||||
ALG_AES_CMAC
|
||||
};
|
||||
|
||||
int esp_cipher2alg(int cipher);
|
||||
|
||||
void esp_rx_checksum_test(struct sk_buff *skb);
|
||||
void esp_gen_err_checksum(struct sk_buff *skb);
|
||||
|
||||
#endif /* NEW_KERNEL */
|
||||
|
||||
bool esp_is_ip_pkt(struct sk_buff *skb);
|
||||
|
||||
#endif
|
||||
1
drivers/net/wireless/esp8089/esp_version.h
Executable file
1
drivers/net/wireless/esp8089/esp_version.h
Executable file
@@ -0,0 +1 @@
|
||||
#define DRIVER_VER 0xbdf5087c3debll
|
||||
61
drivers/net/wireless/esp8089/esp_wl.h
Executable file
61
drivers/net/wireless/esp8089/esp_wl.h
Executable file
@@ -0,0 +1,61 @@
|
||||
#ifndef _ESP_WL_H_
|
||||
#define _ESP_WL_H_
|
||||
|
||||
//#define MAX_PROBED_SSID_INDEX 9
|
||||
|
||||
|
||||
enum {
|
||||
CONF_HW_BIT_RATE_1MBPS = BIT(0),
|
||||
CONF_HW_BIT_RATE_2MBPS = BIT(1),
|
||||
CONF_HW_BIT_RATE_5_5MBPS = BIT(2),
|
||||
CONF_HW_BIT_RATE_11MBPS = BIT(3),
|
||||
CONF_HW_BIT_RATE_6MBPS = BIT(4),
|
||||
CONF_HW_BIT_RATE_9MBPS = BIT(5),
|
||||
CONF_HW_BIT_RATE_12MBPS = BIT(6),
|
||||
CONF_HW_BIT_RATE_18MBPS = BIT(7),
|
||||
CONF_HW_BIT_RATE_22MBPS = BIT(8),
|
||||
CONF_HW_BIT_RATE_24MBPS = BIT(9),
|
||||
CONF_HW_BIT_RATE_36MBPS = BIT(10),
|
||||
CONF_HW_BIT_RATE_48MBPS = BIT(11),
|
||||
CONF_HW_BIT_RATE_54MBPS = BIT(12),
|
||||
CONF_HW_BIT_RATE_11B_MASK = (CONF_HW_BIT_RATE_1MBPS | CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS | CONF_HW_BIT_RATE_11MBPS),
|
||||
};
|
||||
|
||||
#if 0
|
||||
enum {
|
||||
CONF_HW_RATE_INDEX_1MBPS = 0,
|
||||
CONF_HW_RATE_INDEX_2MBPS = 1,
|
||||
CONF_HW_RATE_INDEX_5_5MBPS = 2,
|
||||
CONF_HW_RATE_INDEX_6MBPS = 3,
|
||||
CONF_HW_RATE_INDEX_9MBPS = 4,
|
||||
CONF_HW_RATE_INDEX_11MBPS = 5,
|
||||
CONF_HW_RATE_INDEX_12MBPS = 6,
|
||||
CONF_HW_RATE_INDEX_18MBPS = 7,
|
||||
CONF_HW_RATE_INDEX_22MBPS = 8,
|
||||
CONF_HW_RATE_INDEX_24MBPS = 9,
|
||||
CONF_HW_RATE_INDEX_36MBPS = 10,
|
||||
CONF_HW_RATE_INDEX_48MBPS = 11,
|
||||
CONF_HW_RATE_INDEX_54MBPS = 12,
|
||||
CONF_HW_RATE_INDEX_MAX,
|
||||
};
|
||||
|
||||
enum {
|
||||
CONF_HW_RXTX_RATE_54 = 0,
|
||||
CONF_HW_RXTX_RATE_48,
|
||||
CONF_HW_RXTX_RATE_36,
|
||||
CONF_HW_RXTX_RATE_24,
|
||||
CONF_HW_RXTX_RATE_22,
|
||||
CONF_HW_RXTX_RATE_18,
|
||||
CONF_HW_RXTX_RATE_12,
|
||||
CONF_HW_RXTX_RATE_11,
|
||||
CONF_HW_RXTX_RATE_9,
|
||||
CONF_HW_RXTX_RATE_6,
|
||||
CONF_HW_RXTX_RATE_5_5,
|
||||
CONF_HW_RXTX_RATE_2,
|
||||
CONF_HW_RXTX_RATE_1,
|
||||
CONF_HW_RXTX_RATE_MAX,
|
||||
CONF_HW_RXTX_RATE_UNSUPPORTED = 0xff
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* _ESP_WL_H_ */
|
||||
98
drivers/net/wireless/esp8089/esp_wmac.h
Executable file
98
drivers/net/wireless/esp8089/esp_wmac.h
Executable file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2012 Espressif System.
|
||||
*
|
||||
* MAC header
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef _ESP_WMAC_H_
|
||||
#define _ESP_WMAC_H_
|
||||
|
||||
struct esp_mac_rx_ctrl {
|
||||
signed rssi:8;
|
||||
unsigned rate:4;
|
||||
unsigned is_group:1;
|
||||
unsigned:1;
|
||||
unsigned sig_mode:2;
|
||||
unsigned legacy_length:12;
|
||||
unsigned damatch0:1;
|
||||
unsigned damatch1:1;
|
||||
unsigned bssidmatch0:1;
|
||||
unsigned bssidmatch1:1;
|
||||
unsigned MCS:7;
|
||||
unsigned CWB:1;
|
||||
unsigned HT_length:16;
|
||||
unsigned Smoothing:1;
|
||||
unsigned Not_Sounding:1;
|
||||
unsigned:1;
|
||||
unsigned Aggregation:1;
|
||||
unsigned STBC:2;
|
||||
unsigned FEC_CODING:1;
|
||||
unsigned SGI:1;
|
||||
unsigned rxend_state:8;
|
||||
unsigned ampdu_cnt:8;
|
||||
unsigned channel:4;
|
||||
unsigned:4;
|
||||
signed noise_floor:8;
|
||||
};
|
||||
|
||||
struct esp_rx_ampdu_len {
|
||||
unsigned substate:8;
|
||||
unsigned sublen:12;
|
||||
unsigned :12;
|
||||
};
|
||||
|
||||
struct esp_tx_ampdu_entry {
|
||||
u32 sub_len:12,
|
||||
dili_num:7,
|
||||
:1,
|
||||
null_byte:2,
|
||||
data:1,
|
||||
enc:1,
|
||||
seq:8;
|
||||
};
|
||||
|
||||
//rxend_state flags
|
||||
#define RX_PYH_ERR_MIN 0x42
|
||||
#define RX_AGC_ERR_MIN 0x42
|
||||
#define RX_AGC_ERR_MAX 0x47
|
||||
#define RX_OFDM_ERR_MIN 0x50
|
||||
#define RX_OFDM_ERR_MAX 0x58
|
||||
#define RX_CCK_ERR_MIN 0x59
|
||||
#define RX_CCK_ERR_MAX 0x5F
|
||||
#define RX_ABORT 0x80
|
||||
#define RX_SF_ERR 0x40
|
||||
#define RX_FCS_ERR 0x41
|
||||
#define RX_AHBOV_ERR 0xC0
|
||||
#define RX_BUFOV_ERR 0xC1
|
||||
#define RX_BUFINV_ERR 0xC2
|
||||
#define RX_AMPDUSF_ERR 0xC3
|
||||
#define RX_AMPDUBUFOV_ERR 0xC4
|
||||
#define RX_MACBBFIFOOV_ERR 0xC5
|
||||
#define RX_RPBM_ERR 0xC6
|
||||
#define RX_BTFORCE_ERR 0xC7
|
||||
#define RX_SECOV_ERR 0xE1
|
||||
#define RX_SECPROT_ERR0 0xE2
|
||||
#define RX_SECPROT_ERR1 0xE3
|
||||
#define RX_SECKEY_ERR 0xE4
|
||||
#define RX_SECCRLEN_ERR 0xE5
|
||||
#define RX_SECFIFO_TIMEOUT 0xE6
|
||||
#define RX_WEPICV_ERR 0xF0
|
||||
#define RX_TKIPICV_ERR 0xF4
|
||||
#define RX_TKIPMIC_ERR 0xF5
|
||||
#define RX_CCMPMIC_ERR 0xF8
|
||||
#define RX_WAPIMIC_ERR 0xFC
|
||||
|
||||
s8 esp_wmac_rate2idx(u8 rate);
|
||||
bool esp_wmac_rxsec_error(u8 error);
|
||||
|
||||
#endif /* _ESP_WMAC_H_ */
|
||||
203
drivers/net/wireless/esp8089/firmware/LICENSE-2.0.txt
Normal file
203
drivers/net/wireless/esp8089/firmware/LICENSE-2.0.txt
Normal file
@@ -0,0 +1,203 @@
|
||||
The esp8089 firmware files are licensed under the Apache License, Version 2.0:
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
1
drivers/net/wireless/esp8089/init_data.conf
Executable file
1
drivers/net/wireless/esp8089/init_data.conf
Executable file
@@ -0,0 +1 @@
|
||||
crystal_26M_en=1;test_xtal=0;sdio_configure=2;bt_configure=0;bt_protocol=0;dual_ant_configure=0;test_uart_configure=2;share_xtal=0;gpio_wake=0;no_auto_sleep=0;ext_rst=0;wakeup_gpio=12;ate_test=0;speed_suspend=0;$
|
||||
939
drivers/net/wireless/esp8089/sdio_sif_esp.c
Executable file
939
drivers/net/wireless/esp8089/sdio_sif_esp.c
Executable file
@@ -0,0 +1,939 @@
|
||||
/*
|
||||
* Copyright (c) 2010 -2013 Espressif System.
|
||||
*
|
||||
* sdio serial i/f driver
|
||||
* - sdio device control routines
|
||||
* - sync/async DMA/PIO read/write
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
#ifdef ESP_USE_SDIO
|
||||
#include <linux/mmc/card.h>
|
||||
#include <linux/mmc/mmc.h>
|
||||
#include <linux/mmc/core.h>
|
||||
#include <linux/mmc/host.h>
|
||||
#include <linux/mmc/sdio_func.h>
|
||||
#include <linux/mmc/sdio_ids.h>
|
||||
#include <linux/mmc/sdio.h>
|
||||
#include <linux/mmc/sd.h>
|
||||
#include <linux/module.h>
|
||||
#include <net/mac80211.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/pm.h>
|
||||
|
||||
#include "esp_pub.h"
|
||||
#include "esp_sif.h"
|
||||
#include "esp_sip.h"
|
||||
#include "esp_debug.h"
|
||||
#include "slc_host_register.h"
|
||||
#include "esp_version.h"
|
||||
#include "esp_ctrl.h"
|
||||
#include "esp_file.h"
|
||||
#ifdef USE_EXT_GPIO
|
||||
#include "esp_ext.h"
|
||||
#endif /* USE_EXT_GPIO */
|
||||
|
||||
static int /*__init*/ esp_sdio_init(void);
|
||||
static void /*__exit*/ esp_sdio_exit(void);
|
||||
|
||||
|
||||
#define ESP_DMA_IBUFSZ 2048
|
||||
|
||||
//unsigned int esp_msg_level = 0;
|
||||
unsigned int esp_msg_level = ESP_DBG_ERROR | ESP_SHOW;
|
||||
|
||||
/* HdG: Note:
|
||||
* 1) MMC_HAS_FORCE_DETECT_CHANGE is a hack which is set by my sunxi-wip
|
||||
* tree. FIXME replace with a version check once mmc_force_detect_change()
|
||||
* is added to the mainline kernel.
|
||||
* 2) This version does NOT implement keep_power, the dts must mark the
|
||||
* regulators as regulator-always-on and not use mmc-pwrseq for this stub
|
||||
* to work.
|
||||
*/
|
||||
#ifndef MMC_HAS_FORCE_DETECT_CHANGE
|
||||
void mmc_force_detect_change(struct mmc_host *host, unsigned long delay,
|
||||
bool keep_power)
|
||||
{
|
||||
host->caps &= ~MMC_CAP_NONREMOVABLE;
|
||||
host->caps |= MMC_CAP_NEEDS_POLL;
|
||||
mmc_detect_change(host, delay);
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct semaphore esp_powerup_sem;
|
||||
|
||||
static enum esp_sdio_state sif_sdio_state;
|
||||
struct esp_sdio_ctrl *sif_sctrl = NULL;
|
||||
|
||||
#ifdef ESP_ANDROID_LOGGER
|
||||
bool log_off = false;
|
||||
#endif /* ESP_ANDROID_LOGGER */
|
||||
|
||||
static int esdio_power_off(struct esp_sdio_ctrl *sctrl);
|
||||
static int esdio_power_on(struct esp_sdio_ctrl *sctrl);
|
||||
|
||||
void sif_set_clock(struct sdio_func *func, int clk);
|
||||
|
||||
#include "sdio_stub.c"
|
||||
|
||||
void sif_lock_bus(struct esp_pub *epub)
|
||||
{
|
||||
EPUB_FUNC_CHECK(epub, _exit);
|
||||
|
||||
sdio_claim_host(EPUB_TO_FUNC(epub));
|
||||
_exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void sif_unlock_bus(struct esp_pub *epub)
|
||||
{
|
||||
EPUB_FUNC_CHECK(epub, _exit);
|
||||
|
||||
sdio_release_host(EPUB_TO_FUNC(epub));
|
||||
_exit:
|
||||
return;
|
||||
}
|
||||
|
||||
static inline bool bad_buf(u8 * buf)
|
||||
{
|
||||
return ((unsigned long) buf & 0x3) || !virt_addr_valid(buf);
|
||||
}
|
||||
|
||||
u8 sdio_io_readb(struct esp_pub *epub, int addr, int *res)
|
||||
{
|
||||
struct esp_sdio_ctrl *sctrl = NULL;
|
||||
struct sdio_func *func = NULL;
|
||||
sctrl = (struct esp_sdio_ctrl *)epub->sif;
|
||||
func = sctrl->func;
|
||||
|
||||
if(func->num == 0)
|
||||
return sdio_f0_readb(func, addr, res);
|
||||
else
|
||||
return sdio_readb(func, addr, res);
|
||||
}
|
||||
|
||||
void sdio_io_writeb(struct esp_pub *epub, u8 value, int addr, int *res)
|
||||
{
|
||||
struct esp_sdio_ctrl *sctrl = NULL;
|
||||
struct sdio_func *func = NULL;
|
||||
sctrl = (struct esp_sdio_ctrl *)epub->sif;
|
||||
func = sctrl->func;
|
||||
|
||||
if(func->num == 0)
|
||||
sdio_f0_writeb(func, value, addr, res);
|
||||
else
|
||||
sdio_writeb(func, value, addr, res);
|
||||
sif_platform_check_r1_ready(epub);
|
||||
}
|
||||
|
||||
int sif_io_raw(struct esp_pub *epub, u32 addr, u8 *buf, u32 len, u32 flag)
|
||||
{
|
||||
int err = 0;
|
||||
u8 *ibuf = NULL;
|
||||
bool need_ibuf = false;
|
||||
struct esp_sdio_ctrl *sctrl = NULL;
|
||||
struct sdio_func *func = NULL;
|
||||
|
||||
if (epub == NULL || buf == NULL) {
|
||||
ESSERT(0);
|
||||
err = -EINVAL;
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
sctrl = (struct esp_sdio_ctrl *)epub->sif;
|
||||
func = sctrl->func;
|
||||
if (func == NULL) {
|
||||
ESSERT(0);
|
||||
err = -EINVAL;
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
if (bad_buf(buf)) {
|
||||
esp_dbg(ESP_DBG_TRACE, "%s dst 0x%08x, len %d badbuf\n", __func__, addr, len);
|
||||
need_ibuf = true;
|
||||
ibuf = sctrl->dma_buffer;
|
||||
} else {
|
||||
ibuf = buf;
|
||||
}
|
||||
|
||||
if (flag & SIF_BLOCK_BASIS) {
|
||||
/* round up for block data transcation */
|
||||
}
|
||||
|
||||
if (flag & SIF_TO_DEVICE) {
|
||||
|
||||
if (need_ibuf)
|
||||
memcpy(ibuf, buf, len);
|
||||
|
||||
if (flag & SIF_FIXED_ADDR)
|
||||
err = sdio_writesb(func, addr, ibuf, len);
|
||||
else if (flag & SIF_INC_ADDR) {
|
||||
err = sdio_memcpy_toio(func, addr, ibuf, len);
|
||||
}
|
||||
sif_platform_check_r1_ready(epub);
|
||||
} else if (flag & SIF_FROM_DEVICE) {
|
||||
|
||||
if (flag & SIF_FIXED_ADDR)
|
||||
err = sdio_readsb(func, ibuf, addr, len);
|
||||
else if (flag & SIF_INC_ADDR) {
|
||||
err = sdio_memcpy_fromio(func, ibuf, addr, len);
|
||||
}
|
||||
|
||||
|
||||
if (!err && need_ibuf)
|
||||
memcpy(buf, ibuf, len);
|
||||
}
|
||||
|
||||
_exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
int sif_io_sync(struct esp_pub *epub, u32 addr, u8 *buf, u32 len, u32 flag)
|
||||
{
|
||||
int err = 0;
|
||||
u8 * ibuf = NULL;
|
||||
bool need_ibuf = false;
|
||||
struct esp_sdio_ctrl *sctrl = NULL;
|
||||
struct sdio_func *func = NULL;
|
||||
|
||||
if (epub == NULL || buf == NULL) {
|
||||
ESSERT(0);
|
||||
err = -EINVAL;
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
sctrl = (struct esp_sdio_ctrl *)epub->sif;
|
||||
func = sctrl->func;
|
||||
if (func == NULL) {
|
||||
ESSERT(0);
|
||||
err = -EINVAL;
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
if (bad_buf(buf)) {
|
||||
esp_dbg(ESP_DBG_TRACE, "%s dst 0x%08x, len %d badbuf\n", __func__, addr, len);
|
||||
need_ibuf = true;
|
||||
ibuf = sctrl->dma_buffer;
|
||||
} else {
|
||||
ibuf = buf;
|
||||
}
|
||||
|
||||
if (flag & SIF_BLOCK_BASIS) {
|
||||
/* round up for block data transcation */
|
||||
}
|
||||
|
||||
if (flag & SIF_TO_DEVICE) {
|
||||
|
||||
esp_dbg(ESP_DBG_TRACE, "%s to addr 0x%08x, len %d \n", __func__, addr, len);
|
||||
if (need_ibuf)
|
||||
memcpy(ibuf, buf, len);
|
||||
|
||||
sdio_claim_host(func);
|
||||
|
||||
if (flag & SIF_FIXED_ADDR)
|
||||
err = sdio_writesb(func, addr, ibuf, len);
|
||||
else if (flag & SIF_INC_ADDR) {
|
||||
err = sdio_memcpy_toio(func, addr, ibuf, len);
|
||||
}
|
||||
sif_platform_check_r1_ready(epub);
|
||||
sdio_release_host(func);
|
||||
} else if (flag & SIF_FROM_DEVICE) {
|
||||
|
||||
esp_dbg(ESP_DBG_TRACE, "%s from addr 0x%08x, len %d \n", __func__, addr, len);
|
||||
|
||||
sdio_claim_host(func);
|
||||
|
||||
if (flag & SIF_FIXED_ADDR)
|
||||
err = sdio_readsb(func, ibuf, addr, len);
|
||||
else if (flag & SIF_INC_ADDR) {
|
||||
err = sdio_memcpy_fromio(func, ibuf, addr, len);
|
||||
}
|
||||
|
||||
sdio_release_host(func);
|
||||
|
||||
if (!err && need_ibuf)
|
||||
memcpy(buf, ibuf, len);
|
||||
}
|
||||
|
||||
_exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
int sif_lldesc_read_sync(struct esp_pub *epub, u8 *buf, u32 len)
|
||||
{
|
||||
struct esp_sdio_ctrl *sctrl = NULL;
|
||||
u32 read_len;
|
||||
|
||||
if (epub == NULL || buf == NULL) {
|
||||
ESSERT(0);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sctrl = (struct esp_sdio_ctrl *)epub->sif;
|
||||
|
||||
switch(sctrl->target_id) {
|
||||
case 0x100:
|
||||
read_len = len;
|
||||
break;
|
||||
case 0x600:
|
||||
read_len = roundup(len, sctrl->slc_blk_sz);
|
||||
break;
|
||||
default:
|
||||
read_len = len;
|
||||
break;
|
||||
}
|
||||
|
||||
return sif_io_sync((epub), (sctrl->slc_window_end_addr - 2 - (len)), (buf), (read_len), SIF_FROM_DEVICE | SIF_BYTE_BASIS | SIF_INC_ADDR);
|
||||
}
|
||||
|
||||
int sif_lldesc_write_sync(struct esp_pub *epub, u8 *buf, u32 len)
|
||||
{
|
||||
struct esp_sdio_ctrl *sctrl = NULL;
|
||||
u32 write_len;
|
||||
|
||||
if (epub == NULL || buf == NULL) {
|
||||
ESSERT(0);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sctrl = (struct esp_sdio_ctrl *)epub->sif;
|
||||
|
||||
switch(sctrl->target_id) {
|
||||
case 0x100:
|
||||
write_len = len;
|
||||
break;
|
||||
case 0x600:
|
||||
write_len = roundup(len, sctrl->slc_blk_sz);
|
||||
break;
|
||||
default:
|
||||
write_len = len;
|
||||
break;
|
||||
}
|
||||
|
||||
return sif_io_sync((epub), (sctrl->slc_window_end_addr - (len)), (buf), (write_len), SIF_TO_DEVICE | SIF_BYTE_BASIS | SIF_INC_ADDR);
|
||||
}
|
||||
|
||||
int sif_lldesc_read_raw(struct esp_pub *epub, u8 *buf, u32 len, bool noround)
|
||||
{
|
||||
struct esp_sdio_ctrl *sctrl = NULL;
|
||||
u32 read_len;
|
||||
|
||||
if (epub == NULL || buf == NULL) {
|
||||
ESSERT(0);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sctrl = (struct esp_sdio_ctrl *)epub->sif;
|
||||
|
||||
switch(sctrl->target_id) {
|
||||
case 0x100:
|
||||
read_len = len;
|
||||
break;
|
||||
case 0x600:
|
||||
if(!noround)
|
||||
read_len = roundup(len, sctrl->slc_blk_sz);
|
||||
else
|
||||
read_len = len;
|
||||
break;
|
||||
default:
|
||||
read_len = len;
|
||||
break;
|
||||
}
|
||||
|
||||
return sif_io_raw((epub), (sctrl->slc_window_end_addr - 2 - (len)), (buf), (read_len), SIF_FROM_DEVICE | SIF_BYTE_BASIS | SIF_INC_ADDR);
|
||||
}
|
||||
|
||||
int sif_lldesc_write_raw(struct esp_pub *epub, u8 *buf, u32 len)
|
||||
{
|
||||
struct esp_sdio_ctrl *sctrl = NULL;
|
||||
u32 write_len;
|
||||
|
||||
if (epub == NULL || buf == NULL) {
|
||||
ESSERT(0);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sctrl = (struct esp_sdio_ctrl *)epub->sif;
|
||||
|
||||
switch(sctrl->target_id) {
|
||||
case 0x100:
|
||||
write_len = len;
|
||||
break;
|
||||
case 0x600:
|
||||
write_len = roundup(len, sctrl->slc_blk_sz);
|
||||
break;
|
||||
default:
|
||||
write_len = len;
|
||||
break;
|
||||
}
|
||||
return sif_io_raw((epub), (sctrl->slc_window_end_addr - (len)), (buf), (write_len), SIF_TO_DEVICE | SIF_BYTE_BASIS | SIF_INC_ADDR);
|
||||
|
||||
}
|
||||
|
||||
#define MANUFACTURER_ID_EAGLE_BASE 0x1110
|
||||
#define MANUFACTURER_ID_EAGLE_BASE_MASK 0xFF00
|
||||
#define MANUFACTURER_CODE 0x6666
|
||||
|
||||
static const struct sdio_device_id esp_sdio_devices[] = {
|
||||
{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_EAGLE_BASE | 0x1))},
|
||||
{},
|
||||
};
|
||||
|
||||
static int esdio_power_on(struct esp_sdio_ctrl *sctrl)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (sctrl->off == false)
|
||||
return err;
|
||||
|
||||
sdio_claim_host(sctrl->func);
|
||||
err = sdio_enable_func(sctrl->func);
|
||||
|
||||
if (err) {
|
||||
esp_dbg(ESP_DBG_ERROR, "Unable to enable sdio func: %d\n", err);
|
||||
sdio_release_host(sctrl->func);
|
||||
return err;
|
||||
}
|
||||
|
||||
sdio_release_host(sctrl->func);
|
||||
|
||||
/* ensure device is up */
|
||||
msleep(5);
|
||||
|
||||
sctrl->off = false;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int esdio_power_off(struct esp_sdio_ctrl *sctrl)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (sctrl->off)
|
||||
return 0;
|
||||
|
||||
sdio_claim_host(sctrl->func);
|
||||
err = sdio_disable_func(sctrl->func);
|
||||
sdio_release_host(sctrl->func);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
sctrl->off = true;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void sif_enable_irq(struct esp_pub *epub)
|
||||
{
|
||||
int err;
|
||||
struct esp_sdio_ctrl *sctrl = NULL;
|
||||
|
||||
sctrl = (struct esp_sdio_ctrl *)epub->sif;
|
||||
|
||||
sdio_claim_host(sctrl->func);
|
||||
|
||||
err = sdio_claim_irq(sctrl->func, sif_dsr);
|
||||
|
||||
if (err)
|
||||
esp_dbg(ESP_DBG_ERROR, "sif %s failed\n", __func__);
|
||||
|
||||
atomic_set(&epub->sip->state, SIP_BOOT);
|
||||
|
||||
atomic_set(&sctrl->irq_installed, 1);
|
||||
|
||||
sdio_release_host(sctrl->func);
|
||||
}
|
||||
|
||||
void sif_disable_irq(struct esp_pub *epub)
|
||||
{
|
||||
int err;
|
||||
struct esp_sdio_ctrl *sctrl = (struct esp_sdio_ctrl *)epub->sif;
|
||||
int i = 0;
|
||||
|
||||
if (atomic_read(&sctrl->irq_installed) == 0)
|
||||
return;
|
||||
|
||||
sdio_claim_host(sctrl->func);
|
||||
|
||||
while (atomic_read(&sctrl->irq_handling)) {
|
||||
sdio_release_host(sctrl->func);
|
||||
schedule_timeout(HZ / 100);
|
||||
sdio_claim_host(sctrl->func);
|
||||
if (i++ >= 400) {
|
||||
esp_dbg(ESP_DBG_ERROR, "%s force to stop irq\n", __func__);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
err = sdio_release_irq(sctrl->func);
|
||||
|
||||
if (err) {
|
||||
esp_dbg(ESP_DBG_ERROR, "%s release irq failed\n", __func__);
|
||||
}
|
||||
|
||||
atomic_set(&sctrl->irq_installed, 0);
|
||||
|
||||
sdio_release_host(sctrl->func);
|
||||
}
|
||||
|
||||
void sif_set_clock(struct sdio_func *func, int clk)
|
||||
{
|
||||
struct mmc_host *host = NULL;
|
||||
struct mmc_card *card = NULL;
|
||||
|
||||
card = func->card;
|
||||
host = card->host;
|
||||
|
||||
sdio_claim_host(func);
|
||||
|
||||
//currently only set clock
|
||||
host->ios.clock = clk * 1000000;
|
||||
|
||||
esp_dbg(ESP_SHOW, "%s clock is %u\n", __func__, host->ios.clock);
|
||||
if (host->ios.clock > host->f_max) {
|
||||
host->ios.clock = host->f_max;
|
||||
}
|
||||
host->ops->set_ios(host, &host->ios);
|
||||
|
||||
mdelay(2);
|
||||
|
||||
sdio_release_host(func);
|
||||
}
|
||||
|
||||
static int esp_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id);
|
||||
static void esp_sdio_remove(struct sdio_func *func);
|
||||
|
||||
static int esp_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
|
||||
{
|
||||
int err = 0;
|
||||
struct esp_pub *epub;
|
||||
struct esp_sdio_ctrl *sctrl;
|
||||
struct mmc_host *host = func->card->host;
|
||||
|
||||
esp_dbg(ESP_DBG_TRACE,
|
||||
"sdio_func_num: 0x%X, vendor id: 0x%X, dev id: 0x%X, block size: 0x%X/0x%X\n",
|
||||
func->num, func->vendor, func->device, func->max_blksize,
|
||||
func->cur_blksize);
|
||||
if(sif_sdio_state == ESP_SDIO_STATE_FIRST_INIT){
|
||||
sctrl = kzalloc(sizeof(struct esp_sdio_ctrl), GFP_KERNEL);
|
||||
|
||||
if (sctrl == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* temp buffer reserved for un-dma-able request */
|
||||
sctrl->dma_buffer = kzalloc(ESP_DMA_IBUFSZ, GFP_KERNEL);
|
||||
|
||||
if (sctrl->dma_buffer == NULL) {
|
||||
err = -ENOMEM;
|
||||
goto _err_last;
|
||||
}
|
||||
sif_sctrl = sctrl;
|
||||
sctrl->slc_blk_sz = SIF_SLC_BLOCK_SIZE;
|
||||
|
||||
epub = esp_pub_alloc_mac80211(&func->dev);
|
||||
|
||||
if (epub == NULL) {
|
||||
esp_dbg(ESP_DBG_ERROR, "no mem for epub \n");
|
||||
err = -ENOMEM;
|
||||
goto _err_dma;
|
||||
}
|
||||
epub->sif = (void *)sctrl;
|
||||
sctrl->epub = epub;
|
||||
|
||||
#ifdef USE_EXT_GPIO
|
||||
if (sif_get_ate_config() == 0) {
|
||||
err = ext_gpio_init(epub);
|
||||
if (err) {
|
||||
esp_dbg(ESP_DBG_ERROR, "ext_irq_work_init failed %d\n", err);
|
||||
goto _err_epub;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
} else {
|
||||
sctrl = sif_sctrl;
|
||||
sif_sctrl = NULL;
|
||||
epub = sctrl->epub;
|
||||
SET_IEEE80211_DEV(epub->hw, &func->dev);
|
||||
epub->dev = &func->dev;
|
||||
}
|
||||
|
||||
epub->sdio_state = sif_sdio_state;
|
||||
|
||||
sctrl->func = func;
|
||||
sdio_set_drvdata(func, sctrl);
|
||||
|
||||
sctrl->id = id;
|
||||
sctrl->off = true;
|
||||
|
||||
/* give us some time to enable, in ms */
|
||||
func->enable_timeout = 100;
|
||||
|
||||
err = esdio_power_on(sctrl);
|
||||
esp_dbg(ESP_DBG_TRACE, " %s >> power_on err %d \n", __func__, err);
|
||||
|
||||
if (err){
|
||||
if(sif_sdio_state == ESP_SDIO_STATE_FIRST_INIT)
|
||||
goto _err_ext_gpio;
|
||||
else
|
||||
goto _err_second_init;
|
||||
}
|
||||
check_target_id(epub);
|
||||
|
||||
sdio_claim_host(func);
|
||||
|
||||
err = sdio_set_block_size(func, sctrl->slc_blk_sz);
|
||||
|
||||
if (err) {
|
||||
esp_dbg(ESP_DBG_ERROR, "Set sdio block size %d failed: %d)\n",
|
||||
sctrl->slc_blk_sz, err);
|
||||
sdio_release_host(func);
|
||||
if(sif_sdio_state == ESP_SDIO_STATE_FIRST_INIT)
|
||||
goto _err_off;
|
||||
else
|
||||
goto _err_second_init;
|
||||
}
|
||||
|
||||
sdio_release_host(func);
|
||||
|
||||
#ifdef LOWER_CLK
|
||||
/* fix clock for dongle */
|
||||
sif_set_clock(func, 23);
|
||||
#endif //LOWER_CLK
|
||||
|
||||
err = esp_pub_init_all(epub);
|
||||
|
||||
if (err) {
|
||||
esp_dbg(ESP_DBG_ERROR, "esp_init_all failed: %d\n", err);
|
||||
if(sif_sdio_state == ESP_SDIO_STATE_FIRST_INIT){
|
||||
err = 0;
|
||||
goto _err_first_init;
|
||||
}
|
||||
if(sif_sdio_state == ESP_SDIO_STATE_SECOND_INIT)
|
||||
goto _err_second_init;
|
||||
}
|
||||
|
||||
esp_dbg(ESP_DBG_TRACE, " %s return %d\n", __func__, err);
|
||||
if(sif_sdio_state == ESP_SDIO_STATE_FIRST_INIT){
|
||||
esp_dbg(ESP_DBG_ERROR, "first normal exit\n");
|
||||
sif_sdio_state = ESP_SDIO_STATE_FIRST_NORMAL_EXIT;
|
||||
|
||||
/* Rescan the esp8089 after loading the initial firmware */
|
||||
mmc_force_detect_change(host, msecs_to_jiffies(100), true);
|
||||
|
||||
up(&esp_powerup_sem);
|
||||
}
|
||||
|
||||
return err;
|
||||
|
||||
_err_off:
|
||||
esdio_power_off(sctrl);
|
||||
_err_ext_gpio:
|
||||
#ifdef USE_EXT_GPIO
|
||||
if (sif_get_ate_config() == 0)
|
||||
ext_gpio_deinit();
|
||||
_err_epub:
|
||||
#endif
|
||||
esp_pub_dealloc_mac80211(epub);
|
||||
_err_dma:
|
||||
kfree(sctrl->dma_buffer);
|
||||
_err_last:
|
||||
kfree(sctrl);
|
||||
_err_first_init:
|
||||
if(sif_sdio_state == ESP_SDIO_STATE_FIRST_INIT){
|
||||
esp_dbg(ESP_DBG_ERROR, "first error exit\n");
|
||||
sif_sdio_state = ESP_SDIO_STATE_FIRST_ERROR_EXIT;
|
||||
up(&esp_powerup_sem);
|
||||
}
|
||||
return err;
|
||||
_err_second_init:
|
||||
sif_sdio_state = ESP_SDIO_STATE_SECOND_ERROR_EXIT;
|
||||
esp_sdio_remove(func);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void esp_sdio_remove(struct sdio_func *func)
|
||||
{
|
||||
struct esp_sdio_ctrl *sctrl = NULL;
|
||||
|
||||
esp_dbg(ESP_SHOW, "%s enter\n", __func__);
|
||||
|
||||
sctrl = sdio_get_drvdata(func);
|
||||
|
||||
if (sctrl == NULL) {
|
||||
esp_dbg(ESP_DBG_ERROR, "%s no sctrl\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
if (sctrl->epub == NULL) {
|
||||
esp_dbg(ESP_DBG_ERROR, "%s epub null\n", __func__);
|
||||
break;
|
||||
}
|
||||
sctrl->epub->sdio_state = sif_sdio_state;
|
||||
if(sif_sdio_state != ESP_SDIO_STATE_FIRST_NORMAL_EXIT){
|
||||
if (sctrl->epub->sip) {
|
||||
sip_detach(sctrl->epub->sip);
|
||||
sctrl->epub->sip = NULL;
|
||||
esp_dbg(ESP_DBG_TRACE, "%s sip detached \n", __func__);
|
||||
}
|
||||
#ifdef USE_EXT_GPIO
|
||||
if (sif_get_ate_config() == 0)
|
||||
ext_gpio_deinit();
|
||||
#endif
|
||||
} else {
|
||||
//sif_disable_target_interrupt(sctrl->epub);
|
||||
atomic_set(&sctrl->epub->sip->state, SIP_STOP);
|
||||
sif_disable_irq(sctrl->epub);
|
||||
}
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0))
|
||||
esdio_power_off(sctrl);
|
||||
esp_dbg(ESP_DBG_TRACE, "%s power off \n", __func__);
|
||||
#endif /* kernel < 3.3.0 */
|
||||
|
||||
#ifdef TEST_MODE
|
||||
test_exit_netlink();
|
||||
#endif /* TEST_MODE */
|
||||
if(sif_sdio_state != ESP_SDIO_STATE_FIRST_NORMAL_EXIT){
|
||||
esp_pub_dealloc_mac80211(sctrl->epub);
|
||||
esp_dbg(ESP_DBG_TRACE, "%s dealloc mac80211 \n", __func__);
|
||||
|
||||
if (sctrl->dma_buffer) {
|
||||
kfree(sctrl->dma_buffer);
|
||||
sctrl->dma_buffer = NULL;
|
||||
esp_dbg(ESP_DBG_TRACE, "%s free dma_buffer \n", __func__);
|
||||
}
|
||||
|
||||
kfree(sctrl);
|
||||
}
|
||||
|
||||
} while (0);
|
||||
|
||||
sdio_set_drvdata(func,NULL);
|
||||
|
||||
esp_dbg(ESP_DBG_TRACE, "eagle sdio remove complete\n");
|
||||
}
|
||||
|
||||
MODULE_DEVICE_TABLE(sdio, esp_sdio_devices);
|
||||
|
||||
static int esp_sdio_suspend(struct device *dev)
|
||||
{
|
||||
//#define dev_to_sdio_func(d) container_of(d, struct sdio_func, dev)
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32))
|
||||
struct sdio_func *func = dev_to_sdio_func(dev);
|
||||
#else
|
||||
struct sdio_func *func = container_of(dev, struct sdio_func, dev);
|
||||
#endif
|
||||
struct esp_sdio_ctrl *sctrl = sdio_get_drvdata(func);
|
||||
struct esp_pub *epub = sctrl->epub;
|
||||
|
||||
printk("%s", __func__);
|
||||
#if 0
|
||||
sip_send_suspend_config(epub, 1);
|
||||
#endif
|
||||
atomic_set(&epub->ps.state, ESP_PM_ON);
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34))
|
||||
do{
|
||||
u32 sdio_flags = 0;
|
||||
int ret = 0;
|
||||
sdio_flags = sdio_get_host_pm_caps(func);
|
||||
|
||||
if (!(sdio_flags & MMC_PM_KEEP_POWER)) {
|
||||
printk("%s can't keep power while host is suspended\n", __func__);
|
||||
}
|
||||
|
||||
/* keep power while host suspended */
|
||||
ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
|
||||
if (ret) {
|
||||
printk("%s error while trying to keep power\n", __func__);
|
||||
}
|
||||
}while(0);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int esp_sdio_resume(struct device *dev)
|
||||
{
|
||||
esp_dbg(ESP_DBG_ERROR, "%s", __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
|
||||
static const struct dev_pm_ops esp_sdio_pm_ops = {
|
||||
.suspend= esp_sdio_suspend,
|
||||
.resume= esp_sdio_resume,
|
||||
};
|
||||
#else
|
||||
static struct pm_ops esp_sdio_pm_ops = {
|
||||
.suspend= esp_sdio_suspend,
|
||||
.resume= esp_sdio_resume,
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct sdio_driver esp_sdio_driver = {
|
||||
.name = "eagle_sdio",
|
||||
.id_table = esp_sdio_devices,
|
||||
.probe = esp_sdio_probe,
|
||||
.remove = esp_sdio_remove,
|
||||
.drv = { .pm = &esp_sdio_pm_ops, },
|
||||
};
|
||||
|
||||
static int esp_sdio_dummy_probe(struct sdio_func *func, const struct sdio_device_id *id)
|
||||
{
|
||||
esp_dbg(ESP_DBG_ERROR, "%s enter\n", __func__);
|
||||
|
||||
up(&esp_powerup_sem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void esp_sdio_dummy_remove(struct sdio_func *func)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static struct sdio_driver esp_sdio_dummy_driver = {
|
||||
.name = "eagle_sdio_dummy",
|
||||
.id_table = esp_sdio_devices,
|
||||
.probe = esp_sdio_dummy_probe,
|
||||
.remove = esp_sdio_dummy_remove,
|
||||
};
|
||||
|
||||
static int /*__init*/ esp_sdio_init(void)
|
||||
{
|
||||
#define ESP_WAIT_UP_TIME_MS 11000
|
||||
int err;
|
||||
u64 ver;
|
||||
int retry = 3;
|
||||
bool powerup = false;
|
||||
int edf_ret = 0;
|
||||
|
||||
esp_dbg(ESP_DBG_TRACE, "%s \n", __func__);
|
||||
|
||||
#ifdef DRIVER_VER
|
||||
ver = DRIVER_VER;
|
||||
esp_dbg(ESP_SHOW, "\n***** EAGLE DRIVER VER:%llx*****\n\n", ver);
|
||||
#endif
|
||||
edf_ret = esp_debugfs_init();
|
||||
|
||||
request_init_conf();
|
||||
|
||||
esp_wakelock_init();
|
||||
esp_wake_lock();
|
||||
|
||||
do {
|
||||
sema_init(&esp_powerup_sem, 0);
|
||||
|
||||
sif_platform_target_poweron();
|
||||
|
||||
sif_platform_rescan_card(1);
|
||||
|
||||
err = sdio_register_driver(&esp_sdio_dummy_driver);
|
||||
if (err) {
|
||||
esp_dbg(ESP_DBG_ERROR, "eagle sdio driver registration failed, error code: %d\n", err);
|
||||
goto _fail;
|
||||
}
|
||||
|
||||
if (down_timeout(&esp_powerup_sem,
|
||||
msecs_to_jiffies(ESP_WAIT_UP_TIME_MS)) == 0)
|
||||
{
|
||||
|
||||
powerup = true;
|
||||
msleep(200);
|
||||
break;
|
||||
}
|
||||
|
||||
esp_dbg(ESP_SHOW, "%s ------ RETRY ------ \n", __func__);
|
||||
|
||||
sif_record_retry_config();
|
||||
|
||||
sdio_unregister_driver(&esp_sdio_dummy_driver);
|
||||
|
||||
sif_platform_rescan_card(0);
|
||||
|
||||
sif_platform_target_poweroff();
|
||||
|
||||
} while (retry--);
|
||||
|
||||
if (!powerup) {
|
||||
esp_dbg(ESP_DBG_ERROR, "eagle sdio can not power up!\n");
|
||||
|
||||
err = -ENODEV;
|
||||
goto _fail;
|
||||
}
|
||||
|
||||
esp_dbg(ESP_SHOW, "%s power up OK\n", __func__);
|
||||
|
||||
sdio_unregister_driver(&esp_sdio_dummy_driver);
|
||||
|
||||
sif_sdio_state = ESP_SDIO_STATE_FIRST_INIT;
|
||||
sema_init(&esp_powerup_sem, 0);
|
||||
|
||||
sdio_register_driver(&esp_sdio_driver);
|
||||
|
||||
if ((down_timeout(&esp_powerup_sem,
|
||||
msecs_to_jiffies(ESP_WAIT_UP_TIME_MS)) == 0 ) && sif_get_ate_config() == 0) {
|
||||
if(sif_sdio_state == ESP_SDIO_STATE_FIRST_NORMAL_EXIT){
|
||||
sdio_unregister_driver(&esp_sdio_driver);
|
||||
|
||||
sif_platform_rescan_card(0);
|
||||
|
||||
msleep(100);
|
||||
|
||||
sif_platform_rescan_card(1);
|
||||
|
||||
sif_sdio_state = ESP_SDIO_STATE_SECOND_INIT;
|
||||
|
||||
sdio_register_driver(&esp_sdio_driver);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
esp_register_early_suspend();
|
||||
esp_wake_unlock();
|
||||
return err;
|
||||
|
||||
_fail:
|
||||
esp_wake_unlock();
|
||||
esp_wakelock_destroy();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void /*__exit*/ esp_sdio_exit(void)
|
||||
{
|
||||
esp_dbg(ESP_SHOW, "%s \n", __func__);
|
||||
|
||||
esp_debugfs_exit();
|
||||
|
||||
esp_unregister_early_suspend();
|
||||
|
||||
sdio_unregister_driver(&esp_sdio_driver);
|
||||
|
||||
sif_platform_rescan_card(0);
|
||||
|
||||
#ifndef FPGA_DEBUG
|
||||
sif_platform_target_poweroff();
|
||||
#endif /* !FPGA_DEBUG */
|
||||
|
||||
esp_wakelock_destroy();
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Espressif System");
|
||||
MODULE_DESCRIPTION("Driver for SDIO interconnected eagle low-power WLAN devices");
|
||||
MODULE_LICENSE("GPL");
|
||||
#endif /* ESP_USE_SDIO */
|
||||
115
drivers/net/wireless/esp8089/sdio_stub.c
Executable file
115
drivers/net/wireless/esp8089/sdio_stub.c
Executable file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Espressif System.
|
||||
*
|
||||
* sdio stub code for RK
|
||||
*/
|
||||
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
//#include <mach/iomux.h>
|
||||
#include <linux/amlogic/wifi_dt.h>
|
||||
|
||||
/* reset GPIO parameter defaults to GPIO 0 (ID_SD) on the Raspberry Pi */
|
||||
/* default reset port of OGA hw rev 1.1 : GPIO3_B1 (105) */
|
||||
/* default reset port of ODROID-C4 : GPIOX_18(494) */
|
||||
static int esp_reset_gpio = 494;
|
||||
module_param(esp_reset_gpio, int, 0);
|
||||
MODULE_PARM_DESC(esp_reset_gpio, "ESP8089 CH_PD reset GPIO number");
|
||||
|
||||
#define ESP8089_DRV_VERSION "1.9"
|
||||
|
||||
extern int rk29sdk_wifi_power(int on);
|
||||
extern int rk29sdk_wifi_set_carddetect(int val);
|
||||
int rockchip_wifi_init_module(void)
|
||||
{
|
||||
return esp_sdio_init();
|
||||
}
|
||||
|
||||
void rockchip_wifi_exit_module(void)
|
||||
{
|
||||
esp_sdio_exit();
|
||||
}
|
||||
void sif_platform_rescan_card(unsigned insert)
|
||||
{
|
||||
}
|
||||
|
||||
/* default enable port of ODROID-C4 : GPIOX_17(493) */
|
||||
static int esp_enable_gpio = 493;
|
||||
module_param(esp_enable_gpio, int, 0);
|
||||
MODULE_PARM_DESC(esp_enable_gpio, "ESP8089 CH_EN enable GPIO number");
|
||||
void sif_platform_reset_target(void)
|
||||
{
|
||||
/* set output high by default */
|
||||
printk("ESP8089 reset via GPIO %d\n", esp_reset_gpio);
|
||||
gpio_request(esp_reset_gpio,"esp_reset");
|
||||
gpio_direction_output(esp_reset_gpio, 0);
|
||||
msleep(200);
|
||||
gpio_direction_output(esp_reset_gpio, 1);
|
||||
gpio_free(esp_reset_gpio);
|
||||
}
|
||||
|
||||
void sif_platform_target_poweroff(void)
|
||||
{
|
||||
/* reset ESP before unload so that the esp can be probed on
|
||||
* warm reboot */
|
||||
sif_platform_reset_target();
|
||||
|
||||
gpio_request(esp_enable_gpio,"esp_enable");
|
||||
gpio_direction_output(esp_enable_gpio, 0);
|
||||
gpio_free(esp_enable_gpio);
|
||||
|
||||
sdio_notify(0);
|
||||
}
|
||||
|
||||
void sif_platform_target_poweron(void)
|
||||
{
|
||||
gpio_request(esp_enable_gpio,"esp_enable");
|
||||
gpio_direction_output(esp_enable_gpio, 0);
|
||||
|
||||
sif_platform_reset_target();
|
||||
|
||||
msleep(100);
|
||||
gpio_direction_output(esp_enable_gpio, 1);
|
||||
gpio_free(esp_enable_gpio);
|
||||
|
||||
sdio_notify(1);
|
||||
sdio_reinit();
|
||||
}
|
||||
|
||||
void sif_platform_target_speed(int high_speed)
|
||||
{
|
||||
}
|
||||
|
||||
void sif_platform_check_r1_ready(struct esp_pub *epub)
|
||||
{
|
||||
}
|
||||
|
||||
#ifdef ESP_ACK_INTERRUPT
|
||||
extern void sdmmc_ack_interrupt(struct mmc_host *mmc);
|
||||
|
||||
void sif_platform_ack_interrupt(struct esp_pub *epub)
|
||||
{
|
||||
struct esp_sdio_ctrl *sctrl = NULL;
|
||||
struct sdio_func *func = NULL;
|
||||
|
||||
if (epub == NULL) {
|
||||
ESSERT(epub != NULL);
|
||||
return;
|
||||
}
|
||||
sctrl = (struct esp_sdio_ctrl *)epub->sif;
|
||||
func = sctrl->func;
|
||||
if (func == NULL) {
|
||||
ESSERT(func != NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
sdmmc_ack_interrupt(func->card->host);
|
||||
}
|
||||
#endif //ESP_ACK_INTERRUPT
|
||||
EXPORT_SYMBOL(rockchip_wifi_init_module);
|
||||
EXPORT_SYMBOL(rockchip_wifi_exit_module);
|
||||
|
||||
late_initcall(esp_sdio_init);
|
||||
module_exit(esp_sdio_exit);
|
||||
477
drivers/net/wireless/esp8089/sip2_common.h
Executable file
477
drivers/net/wireless/esp8089/sip2_common.h
Executable file
@@ -0,0 +1,477 @@
|
||||
/*
|
||||
* Copyright (c) 2010 - 2014 Espressif System.
|
||||
*
|
||||
* Common definitions of Serial Interconnctor Protocol
|
||||
*
|
||||
* little endian
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef _SIP2_COMMON_H
|
||||
#define _SIP2_COMMON_H
|
||||
|
||||
#ifdef __ets__
|
||||
#include "utils.h"
|
||||
#endif /*__ets__*/
|
||||
|
||||
/* max 16 types */
|
||||
typedef enum {
|
||||
SIP_CTRL = 0,
|
||||
SIP_DATA,
|
||||
SIP_DATA_AMPDU
|
||||
} SIP_TYPE;
|
||||
|
||||
typedef enum {
|
||||
SIP_TX_CTRL_BUF = 0, /* from host */
|
||||
SIP_RX_CTRL_BUF, /* to host */
|
||||
SIP_TX_DATA_BUF, /* from host */
|
||||
SIP_RX_DATA_BUF /* to host */
|
||||
} SIP_BUF_TYPE;
|
||||
|
||||
enum sip_cmd_id {
|
||||
SIP_CMD_GET_VER = 0,
|
||||
SIP_CMD_WRITE_MEMORY,//1 ROM code
|
||||
SIP_CMD_READ_MEMORY,//2
|
||||
SIP_CMD_WRITE_REG,//3 ROM code
|
||||
SIP_CMD_READ_REG, //4
|
||||
SIP_CMD_BOOTUP,//5 ROM code
|
||||
SIP_CMD_COPYBACK,//6
|
||||
SIP_CMD_INIT, //7
|
||||
SIP_CMD_SCAN,//8
|
||||
SIP_CMD_SETKEY,//9
|
||||
SIP_CMD_CONFIG,//10
|
||||
SIP_CMD_BSS_INFO_UPDATE,//11
|
||||
SIP_CMD_LOOPBACK,//12 ROM code
|
||||
//do not add cmd before this line
|
||||
SIP_CMD_SET_WMM_PARAM,
|
||||
SIP_CMD_AMPDU_ACTION,
|
||||
SIP_CMD_HB_REQ, //15
|
||||
SIP_CMD_RESET_MAC, //16
|
||||
SIP_CMD_PRE_DOWN, //17
|
||||
SIP_CMD_SLEEP, /* for sleep testing */
|
||||
SIP_CMD_WAKEUP, /* for sleep testing */
|
||||
SIP_CMD_DEBUG, /* for general testing */
|
||||
SIP_CMD_GET_FW_VER, /* get fw rev. */
|
||||
SIP_CMD_SETVIF,
|
||||
SIP_CMD_SETSTA,
|
||||
SIP_CMD_PS,
|
||||
SIP_CMD_ATE,
|
||||
SIP_CMD_SUSPEND,
|
||||
SIP_CMD_RECALC_CREDIT,
|
||||
SIP_CMD_MAX,
|
||||
};
|
||||
|
||||
enum {
|
||||
SIP_EVT_TARGET_ON = 0, //
|
||||
SIP_EVT_BOOTUP,//1 in ROM code
|
||||
SIP_EVT_COPYBACK,//2
|
||||
SIP_EVT_SCAN_RESULT, //3
|
||||
SIP_EVT_TX_STATUS,//4
|
||||
SIP_EVT_CREDIT_RPT, //5, in ROM code
|
||||
SIP_EVT_ERROR,//6
|
||||
SIP_EVT_LOOPBACK,//7, in ROM code
|
||||
SIP_EVT_SNPRINTF_TO_HOST, //8 in ROM code
|
||||
//do not add evt before this line
|
||||
SIP_EVT_HB_ACK, //9
|
||||
SIP_EVT_RESET_MAC_ACK, //10
|
||||
SIP_EVT_WAKEUP,//11 /* for sleep testing */
|
||||
SIP_EVT_DEBUG,//12 /* for general testing */
|
||||
SIP_EVT_PRINT_TO_HOST, //13
|
||||
SIP_EVT_TRC_AMPDU, //14
|
||||
SIP_EVT_ROC, //15
|
||||
SIP_EVT_RESETTING,
|
||||
SIP_EVT_ATE,
|
||||
SIP_EVT_EP,
|
||||
SIP_EVT_INIT_EP,
|
||||
SIP_EVT_SLEEP,
|
||||
SIP_EVT_TXIDLE,
|
||||
SIP_EVT_NOISEFLOOR,
|
||||
SIP_EVT_MAX
|
||||
};
|
||||
|
||||
#define SIP_IFIDX_MASK 0xf0
|
||||
#define SIP_IFIDX_S 4
|
||||
#define SIP_TYPE_MASK 0x0f
|
||||
#define SIP_TYPE_S 0
|
||||
|
||||
#define SIP_HDR_GET_IFIDX(fc0) (((fc0) & SIP_IFIDX_MASK) >> SIP_IFIDX_S)
|
||||
#define SIP_HDR_SET_IFIDX(fc0, ifidx) ( (fc0) = ((fc0) & ~SIP_IFIDX_MASK) | ((ifidx) << SIP_IFIDX_S & SIP_IFIDX_MASK) )
|
||||
#define SIP_HDR_GET_TYPE(fc0) ((fc0) & SIP_TYPE_MASK )
|
||||
/* assume type field is cleared */
|
||||
#define SIP_HDR_SET_TYPE(fc0, type) ((fc0) = ((fc0) & ~ SIP_TYPE_MASK) | ((type) & SIP_TYPE_MASK))
|
||||
|
||||
/* sip 2.0, not hybrid header so far */
|
||||
#define SIP_HDR_IS_CTRL(hdr) (SIP_HDR_GET_TYPE((hdr)->fc[0]) == SIP_CTRL)
|
||||
#define SIP_HDR_IS_DATA(hdr) (SIP_HDR_GET_TYPE((hdr)->fc[0]) == SIP_DATA)
|
||||
#define SIP_HDR_IS_AMPDU(hdr) (SIP_HDR_GET_TYPE((hdr)->fc[0]) == SIP_DATA_AMPDU)
|
||||
|
||||
/* fc[1] flags, only for data pkt. Ctrl pkts use fc[1] as eventID */
|
||||
#define SIP_HDR_SET_FLAGS(hdr, flags) ((hdr)->fc[1] |= (flags))
|
||||
#define SIP_HDR_F_MORE_PKT 0x1
|
||||
#define SIP_HDR_F_NEED_CRDT_RPT 0x2
|
||||
#define SIP_HDR_F_SYNC 0x4
|
||||
#define SIP_HDR_F_SYNC_RESET 0x8
|
||||
#define SIP_HDR_F_PM_TURNING_ON 0x10
|
||||
#define SIP_HDR_F_PM_TURNING_OFF 0x20
|
||||
|
||||
#define SIP_HDR_NEED_CREDIT_UPDATE(hdr) ((hdr)->fc[1] & SIP_HDR_F_NEED_CRDT_RPT)
|
||||
#define SIP_HDR_IS_MORE_PKT(hdr) ((hdr)->fc[1] & SIP_HDR_F_MORE_PKT)
|
||||
#define SIP_HDR_IS_CRDT_RPT(hdr) ((hdr)->fc[1] & SIP_HDR_F_CRDT_RPT)
|
||||
#define SIP_HDR_IS_SYNC(hdr) ((hdr)->fc[1] & SIP_HDR_F_SYNC)
|
||||
#define SIP_HDR_IS_SYNC_RESET(hdr) ((hdr)->fc[1] & SIP_HDR_F_SYNC_RESET)
|
||||
#define SIP_HDR_IS_SYNC_PKT(hdr) (SIP_HDR_IS_SYNC(hdr) | SIP_HDR_IS_SYNC_RESET(hdr))
|
||||
#define SIP_HDR_SET_SYNC(hdr) SIP_HDR_SET_FLAGS((hdr), SIP_HDR_F_SYNC)
|
||||
#define SIP_HDR_SET_SYNC_RESET(hdr) SIP_HDR_SET_FLAGS((hdr), SIP_HDR_F_SYNC_RESET)
|
||||
#define SIP_HDR_SET_MORE_PKT(hdr) SIP_HDR_SET_FLAGS((hdr), SIP_HDR_F_MORE_PKT)
|
||||
#define SIP_HDR_SET_PM_TURNING_ON(hdr) SIP_HDR_SET_FLAGS((hdr), SIP_HDR_F_PM_TURNING_ON)
|
||||
#define SIP_HDR_IS_PM_TURNING_ON(hdr) ((hdr)->fc[1] & SIP_HDR_F_PM_TURNING_ON)
|
||||
#define SIP_HDR_SET_PM_TURNING_OFF(hdr) SIP_HDR_SET_FLAGS((hdr), SIP_HDR_F_PM_TURNING_OFF)
|
||||
#define SIP_HDR_IS_PM_TURNING_OFF(hdr) ((hdr)->fc[1] & SIP_HDR_F_PM_TURNING_OFF)
|
||||
|
||||
/*
|
||||
* fc[0]: first 4bit: ifidx; last 4bit: type
|
||||
* fc[1]: flags
|
||||
*
|
||||
* Don't touch the header definitons
|
||||
*/
|
||||
struct sip_hdr_min {
|
||||
u8 fc[2];
|
||||
__le16 len;
|
||||
} __packed;
|
||||
|
||||
/* not more than 4byte long */
|
||||
struct sip_tx_data_info {
|
||||
u8 tid;
|
||||
u8 ac;
|
||||
u8 p2p:1,
|
||||
enc_flag:7;
|
||||
u8 hw_kid;
|
||||
} __packed;
|
||||
|
||||
/* NB: this structure should be not more than 4byte !! */
|
||||
struct sip_tx_info {
|
||||
union {
|
||||
u32 cmdid;
|
||||
struct sip_tx_data_info dinfo;
|
||||
} u;
|
||||
} __packed;
|
||||
|
||||
struct sip_hdr {
|
||||
u8 fc[2]; //fc[0]: type and ifidx ; fc[1] is eventID if the first ctrl pkt in the chain. data pkt still can use fc[1] to set flag
|
||||
__le16 len;
|
||||
union {
|
||||
volatile u32 recycled_credits; /* last 12bits is credits, first 20 bits is actual length of the first pkt in the chain */
|
||||
struct sip_tx_info tx_info;
|
||||
} u;
|
||||
u32 seq;
|
||||
} __packed;
|
||||
|
||||
#define h_credits u.recycled_credits
|
||||
#define c_evtid fc[1]
|
||||
#define c_cmdid u.tx_info.u.cmdid
|
||||
#define d_ac u.tx_info.u.dinfo.ac
|
||||
#define d_tid u.tx_info.u.dinfo.tid
|
||||
#define d_p2p u.tx_info.u.dinfo.p2p
|
||||
#define d_enc_flag u.tx_info.u.dinfo.enc_flag
|
||||
#define d_hw_kid u.tx_info.u.dinfo.hw_kid
|
||||
|
||||
#define SIP_CREDITS_MASK 0xfff /* last 12 bits */
|
||||
|
||||
#ifdef HOST_RC
|
||||
|
||||
#define RC_CNT_MASK 0xf
|
||||
|
||||
struct sip_rc_status {
|
||||
u32 rc_map;
|
||||
union {
|
||||
u32 rc_cnt1:4,
|
||||
rc_cnt2:4,
|
||||
rc_cnt3:4,
|
||||
rc_cnt4:4,
|
||||
rc_cnt5:4;
|
||||
|
||||
u32 rc_cnt_store;
|
||||
};
|
||||
};
|
||||
|
||||
/* copy from mac80211.h */
|
||||
struct sip_tx_rc {
|
||||
struct ieee80211_tx_rate rates[IEEE80211_TX_MAX_RATES];
|
||||
s8 rts_cts_rate_idx;
|
||||
};
|
||||
#endif /* HOST_RC */
|
||||
|
||||
#define SIP_HDR_MIN_LEN 4
|
||||
#define SIP_HDR_LEN sizeof(struct sip_hdr)
|
||||
#define SIP_CTRL_HDR_LEN SIP_HDR_LEN /* same as sip_hdr in sip2 design */
|
||||
#define SIP_BOOT_BUF_SIZE 256
|
||||
#define SIP_CTRL_BUF_SZ 256 /* too much?? */
|
||||
#define SIP_CTRL_BUF_N 6
|
||||
#define SIP_CTRL_TXBUF_N 2
|
||||
#define SIP_CTRL_RXBUF_N 4
|
||||
|
||||
/* WAR for mblk */
|
||||
#define SIP_RX_ADDR_PREFIX_MASK 0xfc000000
|
||||
#define SIP_RX_ADDR_SHIFT 6 /* [31:5], shift 6 bits*/
|
||||
|
||||
struct sip_cmd_write_memory {
|
||||
u32 addr;
|
||||
u32 len;
|
||||
} __packed;
|
||||
|
||||
struct sip_cmd_read_memory {
|
||||
u32 addr;
|
||||
u32 len;
|
||||
} __packed;
|
||||
|
||||
struct sip_cmd_write_reg {
|
||||
u32 addr;
|
||||
u32 val;
|
||||
} __packed;
|
||||
|
||||
struct sip_cmd_bootup {
|
||||
u32 boot_addr;
|
||||
} __packed;
|
||||
|
||||
struct sip_cmd_loopback {
|
||||
u32 txlen; //host to target packet len, 0 means no txpacket
|
||||
u32 rxlen; //target to host packet len, 0 means no rxpacket
|
||||
u32 pack_id; //sequence of packet
|
||||
} __packed;
|
||||
|
||||
struct sip_evt_loopback {
|
||||
u32 txlen; //host to target packet len, 0 means no txpacket
|
||||
u32 rxlen; //target to host packet len, 0 means no rxpacket
|
||||
u32 pack_id; //sequence of packet
|
||||
} __packed;
|
||||
|
||||
struct sip_cmd_copyback {
|
||||
u32 addr;
|
||||
u32 len;
|
||||
} __packed;
|
||||
|
||||
struct sip_cmd_scan {
|
||||
// u8 ssid[32];
|
||||
u8 ssid_len;
|
||||
// u8 hw_channel[14];
|
||||
u8 n_channels;
|
||||
u8 ie_len;
|
||||
u8 aborted;
|
||||
} __packed; // ie[] append at the end
|
||||
|
||||
|
||||
#ifndef ETH_ALEN
|
||||
#define ETH_ALEN 6
|
||||
#endif /* ETH_ALEN */
|
||||
|
||||
struct sip_cmd_setkey {
|
||||
u8 bssid_no;
|
||||
u8 addr[ETH_ALEN];
|
||||
u8 alg;
|
||||
u8 keyidx;
|
||||
u8 hw_key_idx;
|
||||
u8 flags;
|
||||
u8 keylen;
|
||||
u8 key[32];
|
||||
} __packed;
|
||||
|
||||
struct sip_cmd_config {
|
||||
u16 center_freq;
|
||||
u16 duration;
|
||||
} __packed;
|
||||
|
||||
struct sip_cmd_bss_info_update {
|
||||
u8 bssid[ETH_ALEN];
|
||||
u16 isassoc;
|
||||
u32 beacon_int;
|
||||
u8 bssid_no;
|
||||
} __packed;
|
||||
|
||||
struct sip_evt_bootup {
|
||||
u16 tx_blksz;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
/* anything else ? */
|
||||
} __packed;
|
||||
|
||||
struct sip_cmd_setvif {
|
||||
u8 index;
|
||||
u8 mac[ETH_ALEN];
|
||||
u8 set;
|
||||
u8 op_mode;
|
||||
u8 is_p2p;
|
||||
} __packed;
|
||||
|
||||
enum esp_ieee80211_phytype{
|
||||
ESP_IEEE80211_T_CCK = 0,
|
||||
ESP_IEEE80211_T_OFDM = 1,
|
||||
ESP_IEEE80211_T_HT20_L = 2,
|
||||
ESP_IEEE80211_T_HT20_S = 3,
|
||||
};
|
||||
|
||||
struct sip_cmd_setsta {
|
||||
u8 ifidx;
|
||||
u8 index;
|
||||
u8 set;
|
||||
u8 phymode;
|
||||
u8 mac[ETH_ALEN];
|
||||
u16 aid;
|
||||
u8 ampdu_factor;
|
||||
u8 ampdu_density;
|
||||
u16 resv;
|
||||
} __packed;
|
||||
|
||||
struct sip_cmd_ps {
|
||||
u8 dtim_period;
|
||||
u8 max_sleep_period;
|
||||
u8 on;
|
||||
u8 resv;
|
||||
} __packed;
|
||||
|
||||
struct sip_cmd_suspend {
|
||||
u8 suspend;
|
||||
u8 resv[3];
|
||||
} __packed;
|
||||
|
||||
#define SIP_DUMP_RPBM_ERR BIT(0)
|
||||
#define SIP_RXABORT_FIXED BIT(1)
|
||||
#define SIP_SUPPORT_BGSCAN BIT(2)
|
||||
struct sip_evt_bootup2 {
|
||||
u16 tx_blksz;
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
u16 rx_blksz;
|
||||
u8 credit_to_reserve;
|
||||
u8 options;
|
||||
s16 noise_floor;
|
||||
u8 resv[2];
|
||||
/* anything else ? */
|
||||
} __packed;
|
||||
|
||||
typedef enum {
|
||||
TRC_TX_AMPDU_STOPPED = 1,
|
||||
TRC_TX_AMPDU_OPERATIONAL,
|
||||
TRC_TX_AMPDU_WAIT_STOP,
|
||||
TRC_TX_AMPDU_WAIT_OPERATIONAL,
|
||||
TRC_TX_AMPDU_START,
|
||||
} trc_ampdu_state_t;
|
||||
|
||||
struct sip_evt_trc_ampdu {
|
||||
u8 state;
|
||||
u8 tid;
|
||||
u8 addr[ETH_ALEN];
|
||||
} __packed;
|
||||
|
||||
struct sip_cmd_set_wmm_params {
|
||||
u8 aci;
|
||||
u8 aifs;
|
||||
u8 ecw_min;
|
||||
u8 ecw_max;
|
||||
u16 txop_us;
|
||||
} __packed;
|
||||
|
||||
#define SIP_AMPDU_RX_START 0
|
||||
#define SIP_AMPDU_RX_STOP 1
|
||||
#define SIP_AMPDU_TX_OPERATIONAL 2
|
||||
#define SIP_AMPDU_TX_STOP 3
|
||||
struct sip_cmd_ampdu_action {
|
||||
u8 action;
|
||||
u8 index;
|
||||
u8 tid;
|
||||
u8 win_size;
|
||||
u16 ssn;
|
||||
u8 addr[ETH_ALEN];
|
||||
} __packed;
|
||||
|
||||
#define SIP_TX_ST_OK 0
|
||||
#define SIP_TX_ST_NOEB 1
|
||||
#define SIP_TX_ST_ACKTO 2
|
||||
#define SIP_TX_ST_ENCERR 3
|
||||
|
||||
//NB: sip_tx_status must be 4 bytes aligned
|
||||
struct sip_tx_status {
|
||||
u32 sip_seq;
|
||||
#ifdef HOST_RC
|
||||
struct sip_rc_status rcstatus;
|
||||
#endif /* HOST_RC */
|
||||
u8 errno; /* success or failure code */
|
||||
u8 rate_index;
|
||||
char ack_signal;
|
||||
u8 pad;
|
||||
} __packed;
|
||||
|
||||
struct sip_evt_tx_report {
|
||||
u32 pkts;
|
||||
struct sip_tx_status status[0];
|
||||
} __packed;
|
||||
|
||||
struct sip_evt_tx_mblk {
|
||||
u32 mblk_map;
|
||||
} __packed;
|
||||
|
||||
struct sip_evt_scan_report {
|
||||
u16 scan_id;
|
||||
u16 aborted;
|
||||
} __packed;
|
||||
|
||||
struct sip_evt_roc {
|
||||
u16 state; //start:1, end :0
|
||||
u16 is_ok;
|
||||
} __packed;
|
||||
|
||||
struct sip_evt_txidle {
|
||||
u32 last_seq;
|
||||
} __packed;
|
||||
|
||||
struct sip_evt_noisefloor {
|
||||
s16 noise_floor;
|
||||
u16 pad;
|
||||
} __packed;
|
||||
/*
|
||||
* for mblk direct memory access, no need for sip_hdr. tx: first 2k for contrl msg,
|
||||
* rest of 14k for data. rx, same.
|
||||
*/
|
||||
#ifdef TEST_MODE
|
||||
|
||||
struct sip_cmd_sleep {
|
||||
u32 sleep_mode;
|
||||
u32 sleep_tm_ms;
|
||||
u32 wakeup_tm_ms; //zero: after receive bcn, then sleep, nozero: delay nozero ms to sleep
|
||||
u32 sleep_times; //zero: always sleep, nozero: after nozero number sleep/wakeup, then end up sleep
|
||||
} __packed;
|
||||
|
||||
struct sip_cmd_wakeup {
|
||||
u32 check_data; //0:copy to event
|
||||
} __packed;
|
||||
|
||||
struct sip_evt_wakeup {
|
||||
u32 check_data;
|
||||
} __packed;
|
||||
|
||||
//general debug command
|
||||
struct sip_cmd_debug {
|
||||
u32 cmd_type;
|
||||
u32 para_num;
|
||||
u32 para[10];
|
||||
} __packed;
|
||||
|
||||
struct sip_evt_debug {
|
||||
u16 len;
|
||||
u32 results[12];
|
||||
u16 pad;
|
||||
} __packed;
|
||||
|
||||
struct sip_cmd_ate {
|
||||
//u8 len;
|
||||
u8 cmdstr[0];
|
||||
} __packed;
|
||||
|
||||
#endif //ifdef TEST_MODE
|
||||
#endif /* _SIP_COMMON_H_ */
|
||||
271
drivers/net/wireless/esp8089/slc_host_register.h
Executable file
271
drivers/net/wireless/esp8089/slc_host_register.h
Executable file
@@ -0,0 +1,271 @@
|
||||
//Generated at 2012-10-23 20:11:08
|
||||
/*
|
||||
* Copyright (c) 2011 Espressif System
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef SLC_HOST_REGISTER_H_INCLUDED
|
||||
#define SLC_HOST_REGISTER_H_INCLUDED
|
||||
|
||||
/* #define REG_SLC_HOST_BASE 0x00000000 */
|
||||
/* skip the token1, since reading it will clean the credit */
|
||||
#define REG_SLC_HOST_BASE 0x00000000
|
||||
#define REG_SLC_BASE 0x00000000
|
||||
|
||||
|
||||
#define SLC_HOST_PF (REG_SLC_HOST_BASE + 0x0)
|
||||
#define SLC_HOST_TOKEN_RDATA (REG_SLC_HOST_BASE + 0x4)
|
||||
#define SLC_HOST_RX_PF_EOF 0x0000000F
|
||||
#define SLC_HOST_RX_PF_EOF_S 28
|
||||
#define SLC_HOST_TOKEN1 0x00000FFF
|
||||
#define SLC_HOST_TOKEN1_S 16
|
||||
#define SLC_HOST_RX_PF_VALID (BIT(15))
|
||||
#define SLC_HOST_TOKEN0 0x00000FFF
|
||||
#define SLC_HOST_TOKEN0_S 0
|
||||
|
||||
#define SLC_HOST_TOKEN0_MASK SLC_HOST_TOKEN0
|
||||
|
||||
#define SLC_HOST_INT_RAW (REG_SLC_HOST_BASE + 0x8)
|
||||
#define SLC_HOST_EXT_BIT3_INT_RAW (BIT(22))
|
||||
#define SLC_HOST_EXT_BIT2_INT_RAW (BIT(21))
|
||||
#define SLC_HOST_EXT_BIT1_INT_RAW (BIT(20))
|
||||
#define SLC_HOST_RXFIFO_NOT_EMPTY_INT_RAW (BIT(19))
|
||||
#define SLC_HOST_RX_PF_VALID_INT_RAW (BIT(18))
|
||||
#define SLC_HOST_TX_OVF_INT_RAW (BIT(17))
|
||||
#define SLC_HOST_RX_UDF_INT_RAW (BIT(16))
|
||||
#define SLC_HOST_TX_START_INT_RAW (BIT(15))
|
||||
#define SLC_HOST_RX_START_INT_RAW (BIT(14))
|
||||
#define SLC_HOST_RX_EOF_INT_RAW (BIT(13))
|
||||
#define SLC_HOST_RX_SOF_INT_RAW (BIT(12))
|
||||
#define SLC_HOST_TOKEN1_0TO1_INT_RAW (BIT(11))
|
||||
#define SLC_HOST_TOKEN0_0TO1_INT_RAW (BIT(10))
|
||||
#define SLC_HOST_TOKEN1_1TO0_INT_RAW (BIT(9))
|
||||
#define SLC_HOST_TOKEN0_1TO0_INT_RAW (BIT(8))
|
||||
#define SLC_HOST_TOHOST_BIT7_INT_RAW (BIT(7))
|
||||
#define SLC_HOST_TOHOST_BIT6_INT_RAW (BIT(6))
|
||||
#define SLC_HOST_TOHOST_BIT5_INT_RAW (BIT(5))
|
||||
#define SLC_HOST_TOHOST_BIT4_INT_RAW (BIT(4))
|
||||
#define SLC_HOST_TOHOST_BIT3_INT_RAW (BIT(3))
|
||||
#define SLC_HOST_TOHOST_BIT2_INT_RAW (BIT(2))
|
||||
#define SLC_HOST_TOHOST_BIT1_INT_RAW (BIT(1))
|
||||
#define SLC_HOST_TOHOST_BIT0_INT_RAW (BIT(0))
|
||||
|
||||
#define SLC_HOST_STATE_W0 (REG_SLC_HOST_BASE + 0xC)
|
||||
#define SLC_HOST_STATE3 0x000000FF
|
||||
#define SLC_HOST_STATE3_S 24
|
||||
#define SLC_HOST_STATE2 0x000000FF
|
||||
#define SLC_HOST_STATE2_S 16
|
||||
#define SLC_HOST_STATE1 0x000000FF
|
||||
#define SLC_HOST_STATE1_S 8
|
||||
#define SLC_HOST_STATE0 0x000000FF
|
||||
#define SLC_HOST_STATE0_S 0
|
||||
|
||||
#define SLC_HOST_STATE_W1 (REG_SLC_HOST_BASE + 0x10)
|
||||
#define SLC_HOST_STATE7 0x000000FF
|
||||
#define SLC_HOST_STATE7_S 24
|
||||
#define SLC_HOST_STATE6 0x000000FF
|
||||
#define SLC_HOST_STATE6_S 16
|
||||
#define SLC_HOST_STATE5 0x000000FF
|
||||
#define SLC_HOST_STATE5_S 8
|
||||
#define SLC_HOST_STATE4 0x000000FF
|
||||
#define SLC_HOST_STATE4_S 0
|
||||
|
||||
#define SLC_HOST_CONF_W0 (REG_SLC_HOST_BASE + 0x14)
|
||||
#define SLC_HOST_CONF3 0x000000FF
|
||||
#define SLC_HOST_CONF3_S 24
|
||||
#define SLC_HOST_CONF2 0x000000FF
|
||||
#define SLC_HOST_CONF2_S 16
|
||||
#define SLC_HOST_CONF1 0x000000FF
|
||||
#define SLC_HOST_CONF1_S 8
|
||||
#define SLC_HOST_CONF0 0x000000FF
|
||||
#define SLC_HOST_CONF0_S 0
|
||||
|
||||
#define SLC_HOST_CONF_W1 (REG_SLC_HOST_BASE + 0x18)
|
||||
#define SLC_HOST_CONF7 0x000000FF
|
||||
#define SLC_HOST_CONF7_S 24
|
||||
#define SLC_HOST_CONF6 0x000000FF
|
||||
#define SLC_HOST_CONF6_S 16
|
||||
#define SLC_HOST_CONF5 0x000000FF
|
||||
#define SLC_HOST_CONF5_S 8
|
||||
#define SLC_HOST_CONF4 0x000000FF
|
||||
#define SLC_HOST_CONF4_S 0
|
||||
|
||||
#define SLC_HOST_INT_ST (REG_SLC_HOST_BASE + 0x1C)
|
||||
#define SLC_HOST_RX_ST (BIT(23))
|
||||
#define SLC_HOST_EXT_BIT3_INT_ST (BIT(22))
|
||||
#define SLC_HOST_EXT_BIT2_INT_ST (BIT(21))
|
||||
#define SLC_HOST_EXT_BIT1_INT_ST (BIT(20))
|
||||
#define SLC_HOST_RXFIFO_NOT_EMPTY_INT_ST (BIT(19))
|
||||
#define SLC_HOST_RX_PF_VALID_INT_ST (BIT(18))
|
||||
#define SLC_HOST_TX_OVF_INT_ST (BIT(17))
|
||||
#define SLC_HOST_RX_UDF_INT_ST (BIT(16))
|
||||
#define SLC_HOST_TX_START_INT_ST (BIT(15))
|
||||
#define SLC_HOST_RX_START_INT_ST (BIT(14))
|
||||
#define SLC_HOST_RX_EOF_INT_ST (BIT(13))
|
||||
#define SLC_HOST_RX_SOF_INT_ST (BIT(12))
|
||||
#define SLC_HOST_TOKEN1_0TO1_INT_ST (BIT(11))
|
||||
#define SLC_HOST_TOKEN0_0TO1_INT_ST (BIT(10))
|
||||
#define SLC_HOST_TOKEN1_1TO0_INT_ST (BIT(9))
|
||||
#define SLC_HOST_TOKEN0_1TO0_INT_ST (BIT(8))
|
||||
#define SLC_HOST_TOHOST_BIT7_INT_ST (BIT(7))
|
||||
#define SLC_HOST_TOHOST_BIT6_INT_ST (BIT(6))
|
||||
#define SLC_HOST_TOHOST_BIT5_INT_ST (BIT(5))
|
||||
#define SLC_HOST_TOHOST_BIT4_INT_ST (BIT(4))
|
||||
#define SLC_HOST_TOHOST_BIT3_INT_ST (BIT(3))
|
||||
#define SLC_HOST_TOHOST_BIT2_INT_ST (BIT(2))
|
||||
#define SLC_HOST_TOHOST_BIT1_INT_ST (BIT(1))
|
||||
#define SLC_HOST_TOHOST_BIT0_INT_ST (BIT(0))
|
||||
|
||||
#define SLC_HOST_CONF_W2 (REG_SLC_HOST_BASE + 0x20)
|
||||
#define SLC_HOST_CONF11 0x000000FF
|
||||
#define SLC_HOST_CONF11_S 24
|
||||
#define SLC_HOST_CONF10 0x000000FF
|
||||
#define SLC_HOST_CONF10_S 16
|
||||
#define SLC_HOST_CONF9 0x000000FF
|
||||
#define SLC_HOST_CONF9_S 8
|
||||
#define SLC_HOST_CONF8 0x000000FF
|
||||
#define SLC_HOST_CONF8_S 0
|
||||
|
||||
#define SLC_HOST_CONF_W3 (REG_SLC_HOST_BASE + 0x24)
|
||||
#define SLC_HOST_CONF15 0x000000FF
|
||||
#define SLC_HOST_CONF15_S 24
|
||||
#define SLC_HOST_CONF14 0x000000FF
|
||||
#define SLC_HOST_CONF14_S 16
|
||||
#define SLC_HOST_CONF13 0x000000FF
|
||||
#define SLC_HOST_CONF13_S 8
|
||||
#define SLC_HOST_CONF12 0x000000FF
|
||||
#define SLC_HOST_CONF12_S 0
|
||||
|
||||
#define SLC_HOST_GEN_TXDONE_INT BIT(16)
|
||||
#define SLC_HOST_GEN_RXDONE_INT BIT(17)
|
||||
|
||||
#define SLC_HOST_CONF_W4 (REG_SLC_HOST_BASE + 0x28)
|
||||
#define SLC_HOST_CONF19 0x000000FF
|
||||
#define SLC_HOST_CONF19_S 24
|
||||
#define SLC_HOST_CONF18 0x000000FF
|
||||
#define SLC_HOST_CONF18_S 16
|
||||
#define SLC_HOST_CONF17 0x000000FF
|
||||
#define SLC_HOST_CONF17_S 8
|
||||
#define SLC_HOST_CONF16 0x000000FF
|
||||
#define SLC_HOST_CONF16_S 0
|
||||
|
||||
#define SLC_HOST_TOKEN_WDATA (REG_SLC_HOST_BASE + 0x2C)
|
||||
#define SLC_HOST_TOKEN1_WD 0x00000FFF
|
||||
#define SLC_HOST_TOKEN1_WD_S 16
|
||||
#define SLC_HOST_TOKEN0_WD 0x00000FFF
|
||||
#define SLC_HOST_TOKEN0_WD_S 0
|
||||
|
||||
#define SLC_HOST_INT_CLR (REG_SLC_HOST_BASE + 0x30)
|
||||
#define SLC_HOST_TOKEN1_WR (BIT(31))
|
||||
#define SLC_HOST_TOKEN0_WR (BIT(30))
|
||||
#define SLC_HOST_TOKEN1_DEC (BIT(29))
|
||||
#define SLC_HOST_TOKEN0_DEC (BIT(28))
|
||||
#define SLC_HOST_EXT_BIT3_INT_CLR (BIT(22))
|
||||
#define SLC_HOST_EXT_BIT2_INT_CLR (BIT(21))
|
||||
#define SLC_HOST_EXT_BIT1_INT_CLR (BIT(20))
|
||||
#define SLC_HOST_EXT_BIT0_INT_CLR (BIT(19))
|
||||
#define SLC_HOST_RX_PF_VALID_INT_CLR (BIT(18))
|
||||
#define SLC_HOST_TX_OVF_INT_CLR (BIT(17))
|
||||
#define SLC_HOST_RX_UDF_INT_CLR (BIT(16))
|
||||
#define SLC_HOST_TX_START_INT_CLR (BIT(15))
|
||||
#define SLC_HOST_RX_START_INT_CLR (BIT(14))
|
||||
#define SLC_HOST_RX_EOF_INT_CLR (BIT(13))
|
||||
#define SLC_HOST_RX_SOF_INT_CLR (BIT(12))
|
||||
#define SLC_HOST_TOKEN1_0TO1_INT_CLR (BIT(11))
|
||||
#define SLC_HOST_TOKEN0_0TO1_INT_CLR (BIT(10))
|
||||
#define SLC_HOST_TOKEN1_1TO0_INT_CLR (BIT(9))
|
||||
#define SLC_HOST_TOKEN0_1TO0_INT_CLR (BIT(8))
|
||||
#define SLC_HOST_TOHOST_BIT7_INT_CLR (BIT(7))
|
||||
#define SLC_HOST_TOHOST_BIT6_INT_CLR (BIT(6))
|
||||
#define SLC_HOST_TOHOST_BIT5_INT_CLR (BIT(5))
|
||||
#define SLC_HOST_TOHOST_BIT4_INT_CLR (BIT(4))
|
||||
#define SLC_HOST_TOHOST_BIT3_INT_CLR (BIT(3))
|
||||
#define SLC_HOST_TOHOST_BIT2_INT_CLR (BIT(2))
|
||||
#define SLC_HOST_TOHOST_BIT1_INT_CLR (BIT(1))
|
||||
#define SLC_HOST_TOHOST_BIT0_INT_CLR (BIT(0))
|
||||
|
||||
#define SLC_HOST_INT_ENA (REG_SLC_HOST_BASE + 0x34)
|
||||
#define SLC_HOST_EXT_BIT3_INT_ENA (BIT(22))
|
||||
#define SLC_HOST_EXT_BIT2_INT_ENA (BIT(21))
|
||||
#define SLC_HOST_EXT_BIT1_INT_ENA (BIT(20))
|
||||
#define SLC_HOST_EXT_BIT0_INT_ENA (BIT(19))
|
||||
#define SLC_HOST_RX_PF_VALID_INT_ENA (BIT(18))
|
||||
#define SLC_HOST_TX_OVF_INT_ENA (BIT(17))
|
||||
#define SLC_HOST_RX_UDF_INT_ENA (BIT(16))
|
||||
#define SLC_HOST_TX_START_INT_ENA (BIT(15))
|
||||
#define SLC_HOST_RX_START_INT_ENA (BIT(14))
|
||||
#define SLC_HOST_RX_EOF_INT_ENA (BIT(13))
|
||||
#define SLC_HOST_RX_SOF_INT_ENA (BIT(12))
|
||||
#define SLC_HOST_TOKEN1_0TO1_INT_ENA (BIT(11))
|
||||
#define SLC_HOST_TOKEN0_0TO1_INT_ENA (BIT(10))
|
||||
#define SLC_HOST_TOKEN1_1TO0_INT_ENA (BIT(9))
|
||||
#define SLC_HOST_TOKEN0_1TO0_INT_ENA (BIT(8))
|
||||
#define SLC_HOST_TOHOST_BIT7_INT_ENA (BIT(7))
|
||||
#define SLC_HOST_TOHOST_BIT6_INT_ENA (BIT(6))
|
||||
#define SLC_HOST_TOHOST_BIT5_INT_ENA (BIT(5))
|
||||
#define SLC_HOST_TOHOST_BIT4_INT_ENA (BIT(4))
|
||||
#define SLC_HOST_TOHOST_BIT3_INT_ENA (BIT(3))
|
||||
#define SLC_HOST_TOHOST_BIT2_INT_ENA (BIT(2))
|
||||
#define SLC_HOST_TOHOST_BIT1_INT_ENA (BIT(1))
|
||||
#define SLC_HOST_TOHOST_BIT0_INT_ENA (BIT(0))
|
||||
|
||||
#define SLC_HOST_CONF_W5 (REG_SLC_HOST_BASE + 0x3C)
|
||||
#define SLC_HOST_CONF23 0x000000FF
|
||||
#define SLC_HOST_CONF23_S 24
|
||||
#define SLC_HOST_CONF22 0x000000FF
|
||||
#define SLC_HOST_CONF22_S 16
|
||||
#define SLC_HOST_CONF21 0x000000FF
|
||||
#define SLC_HOST_CONF21_S 8
|
||||
#define SLC_HOST_CONF20 0x000000FF
|
||||
#define SLC_HOST_CONF20_S 0
|
||||
|
||||
#define SLC_HOST_WIN_CMD (REG_SLC_HOST_BASE + 0x40)
|
||||
|
||||
|
||||
#define SLC_HOST_DATE (REG_SLC_HOST_BASE + 0x78)
|
||||
#define SLC_HOST_ID (REG_SLC_HOST_BASE + 0x7C)
|
||||
|
||||
#define SLC_ADDR_WINDOW_CLEAR_MASK (~(0xf<<12))
|
||||
#define SLC_FROM_HOST_ADDR_WINDOW (0x1<<12)
|
||||
#define SLC_TO_HOST_ADDR_WINDOW (0x3<<12)
|
||||
|
||||
#define SLC_SET_FROM_HOST_ADDR_WINDOW(v) do { \
|
||||
(v) &= 0xffff; \
|
||||
(v) &= SLC_ADDR_WINDOW_CLEAR_MASK; \
|
||||
(v) |= SLC_FROM_HOST_ADDR_WINDOW; \
|
||||
} while (0);
|
||||
|
||||
#define SLC_SET_TO_HOST_ADDR_WINDOW(v) do { \
|
||||
(v) &= 0xffff; \
|
||||
(v) &= SLC_ADDR_WINDOW_CLEAR_MASK; \
|
||||
(v) |= SLC_TO_HOST_ADDR_WINDOW; \
|
||||
} while (0);
|
||||
|
||||
#define SLC_INT_ENA (REG_SLC_BASE + 0xC)
|
||||
#define SLC_RX_EOF_INT_ENA BIT(17)
|
||||
#define SLC_FRHOST_BIT2_INT_ENA BIT(2)
|
||||
|
||||
#define SLC_RX_LINK (REG_SLC_BASE + 0x24)
|
||||
#define SLC_RXLINK_START BIT(29)
|
||||
|
||||
#define SLC_BRIDGE_CONF (REG_SLC_BASE + 0x44)
|
||||
#define SLC_TX_PUSH_IDLE_NUM 0xFFFF
|
||||
#define SLC_TX_PUSH_IDLE_NUM_S 16
|
||||
#define SLC_HDA_MAP_128K BIT(13)
|
||||
#define SLC_TX_DUMMY_MODE BIT(12)
|
||||
#define SLC_FIFO_MAP_ENA 0x0000000F
|
||||
#define SLC_FIFO_MAP_ENA_S 8
|
||||
#define SLC_TXEOF_ENA 0x0000003F
|
||||
#define SLC_TXEOF_ENA_S
|
||||
|
||||
|
||||
#endif // SLC_HOST_REGISTER_H_INCLUDED
|
||||
2375
drivers/net/wireless/esp8089/spi_sif_esp.c
Executable file
2375
drivers/net/wireless/esp8089/spi_sif_esp.c
Executable file
File diff suppressed because it is too large
Load Diff
181
drivers/net/wireless/esp8089/spi_stub.c
Normal file
181
drivers/net/wireless/esp8089/spi_stub.c
Normal file
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Espressif System.
|
||||
*
|
||||
* sdio stub code for allwinner
|
||||
*/
|
||||
#include <asm/io.h>
|
||||
#include <mach/irqs.h>
|
||||
#include <mach/io.h>
|
||||
#include <mach/iomux.h>
|
||||
#include <mach/pmu.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/mach/irq.h>
|
||||
|
||||
#include "../drivers/spi/rk29_spim.h"
|
||||
#include "esp_sif.h"
|
||||
|
||||
//#define SPI_FREQ (20000000) // 1. 22.5Mhz 2. 45Mhz
|
||||
#define SPI_FREQ (30000000) // 1. 22.5Mhz 2. 45Mhz
|
||||
|
||||
//Below are for spi HZ 22.5M
|
||||
#if (SPI_FREQ == 30000000)
|
||||
|
||||
#define CMD_RESP_SIZE (10) //(50) //Common respon wait time
|
||||
#define DATA_RESP_SIZE_W (142+45) // (1024*13)// (1024*16) //(398+400) // (1024*10) //Only for Write bytes function, data write response. max:(361+109)
|
||||
#define DATA_RESP_SIZE_R (231+75) // (340+102) //(231+75)//(340+102) //Only for Read bytes function, data write response max:(340+102)
|
||||
|
||||
#define BLOCK_W_DATA_RESP_SIZE_EACH (10) //For each data write resp size, in block write
|
||||
#define BLOCK_W_DATA_RESP_SIZE_FINAL (152) // (142+52) //For final data write resp size, in block write ,max: 119
|
||||
|
||||
#define BLOCK_R_DATA_RESP_SIZE_1ST (265) // (231+75) //For each data read resp size, in block read ,max: 134
|
||||
#define BLOCK_R_DATA_RESP_SIZE_EACH (10) // (20) //For each data read resp size, in block read
|
||||
|
||||
#elif(SPI_FREQ == 20000000)
|
||||
|
||||
#define CMD_RESP_SIZE (10) //Common respon wait time
|
||||
#define DATA_RESP_SIZE_W (103+40) //Only for Write bytes function, data write response. max: 103
|
||||
#define DATA_RESP_SIZE_R (118+40) //Only for Read bytes function, data write response max: 118
|
||||
//w: oxFF : 218 clock. oxFE : 214 clock.
|
||||
|
||||
#define BLOCK_W_DATA_RESP_SIZE_EACH (20) //For each data write resp size, in block write
|
||||
#define BLOCK_W_DATA_RESP_SIZE_FINAL (112+40) //For final data write resp size, in block write ,max :112
|
||||
|
||||
#define BLOCK_R_DATA_RESP_SIZE_1ST (123+40) //For each data read resp size, in block read ,max: 123
|
||||
#define BLOCK_R_DATA_RESP_SIZE_EACH (20) //For each data read resp size, in block read
|
||||
|
||||
#endif
|
||||
|
||||
//0xE5 ~0xFF 30us totoal
|
||||
//
|
||||
|
||||
struct spi_device_id esp_spi_id[] = {
|
||||
{"esp_spi_0", 0},
|
||||
{"esp_spi_1", 1},
|
||||
{},
|
||||
};
|
||||
|
||||
|
||||
#ifdef REGISTER_SPI_BOARD_INFO
|
||||
static struct rk29xx_spi_chip spi_test_chip[] = {
|
||||
{
|
||||
//.poll_mode = 1,
|
||||
.enable_dma = 1,
|
||||
},
|
||||
{
|
||||
//.poll_mode = 1,
|
||||
.enable_dma = 1,
|
||||
},
|
||||
|
||||
};
|
||||
static struct spi_board_info esp_board_spi_devices[] = {
|
||||
{
|
||||
.modalias = "esp_spi_0",
|
||||
.bus_num = 0, //0 or 1
|
||||
.max_speed_hz = 18*1000*1000,
|
||||
.chip_select = 0,
|
||||
.mode = SPI_MODE_3,
|
||||
.controller_data = &spi_test_chip[0],
|
||||
},
|
||||
};
|
||||
|
||||
void sif_platform_register_board_info(void) {
|
||||
spi_register_board_info(esp_board_spi_devices, ARRAY_SIZE(esp_board_spi_devices));
|
||||
}
|
||||
#endif /*REGISTER_SPI_BOARD_INFO*/
|
||||
|
||||
|
||||
#define RK30_GPIO0_BASE RK2928_GPIO0_BASE
|
||||
#define GPIO_NO RK30_PIN0_PA0
|
||||
#define GPIO_BASE_ADDR ((unsigned char __iomem *) RK30_GPIO0_BASE)
|
||||
#define GPIO_INT_MASK_OFFSET GPIO_INTEN
|
||||
#define GPIO_INT_STAT_OFFSET GPIO_PORTS_EOI
|
||||
|
||||
int sif_platform_get_irq_no(void)
|
||||
{
|
||||
return gpio_to_irq(GPIO_NO);
|
||||
}
|
||||
|
||||
int sif_platform_is_irq_occur(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void sif_platform_irq_clear(void)
|
||||
{
|
||||
}
|
||||
|
||||
void sif_platform_irq_mask(int mask)
|
||||
{
|
||||
if (mask)
|
||||
disable_irq_nosync(sif_platform_get_irq_no());
|
||||
else
|
||||
enable_irq(sif_platform_get_irq_no());
|
||||
}
|
||||
|
||||
int sif_platform_irq_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
printk(KERN_ERR "%s enter\n", __func__);
|
||||
|
||||
if ( (ret = gpio_request(GPIO_NO, "esp_spi_int")) != 0) {
|
||||
printk(KERN_ERR "request gpio error\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
gpio_direction_input(GPIO_NO);
|
||||
|
||||
sif_platform_irq_clear();
|
||||
sif_platform_irq_mask(1);
|
||||
|
||||
udelay(1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void sif_platform_irq_deinit(void)
|
||||
{
|
||||
gpio_free(GPIO_NO);
|
||||
}
|
||||
|
||||
|
||||
void sif_platform_reset_target(void)
|
||||
{
|
||||
gpio_direction_output(RK30_PIN1_PB3, GPIO_LOW);
|
||||
mdelay(200);
|
||||
gpio_direction_output(RK30_PIN1_PB3, GPIO_HIGH);
|
||||
mdelay(200);
|
||||
}
|
||||
|
||||
void sif_platform_target_poweroff(void)
|
||||
{
|
||||
gpio_direction_output(RK30_PIN1_PB3, GPIO_LOW);
|
||||
|
||||
}
|
||||
|
||||
void sif_platform_target_poweron(void)
|
||||
{
|
||||
mdelay(200);
|
||||
gpio_direction_output(RK30_PIN1_PB3, GPIO_LOW);
|
||||
mdelay(200);
|
||||
gpio_direction_output(RK30_PIN1_PB3, GPIO_HIGH);
|
||||
mdelay(200);
|
||||
}
|
||||
|
||||
void sif_platform_target_speed(int high_speed)
|
||||
{
|
||||
}
|
||||
|
||||
#ifdef ESP_ACK_INTERRUPT
|
||||
void sif_platform_ack_interrupt(struct esp_pub *epub)
|
||||
{
|
||||
sif_platform_irq_clear();
|
||||
}
|
||||
#endif //ESP_ACK_INTERRUPT
|
||||
|
||||
|
||||
module_init(esp_spi_init);
|
||||
module_exit(esp_spi_exit);
|
||||
|
||||
1431
drivers/net/wireless/esp8089/testmode.c
Executable file
1431
drivers/net/wireless/esp8089/testmode.c
Executable file
File diff suppressed because it is too large
Load Diff
77
drivers/net/wireless/esp8089/testmode.h
Executable file
77
drivers/net/wireless/esp8089/testmode.h
Executable file
@@ -0,0 +1,77 @@
|
||||
|
||||
#ifndef __TEST_MODE
|
||||
#define __TEST_MODE
|
||||
|
||||
enum {
|
||||
TEST_CMD_UNSPEC,
|
||||
TEST_CMD_ECHO,
|
||||
TEST_CMD_ASK,
|
||||
TEST_CMD_SLEEP,
|
||||
TEST_CMD_WAKEUP,
|
||||
TEST_CMD_LOOPBACK,
|
||||
TEST_CMD_TX,
|
||||
TEST_CMD_RX,
|
||||
TEST_CMD_DEBUG,
|
||||
TEST_CMD_SDIO_WR,
|
||||
TEST_CMD_SDIO_RD,
|
||||
TEST_CMD_ATE,
|
||||
TEST_CMD_SDIOTEST,
|
||||
TEST_CMD_SDIOSPEED,
|
||||
__TEST_CMD_MAX,
|
||||
};
|
||||
#define TEST_CMD_MAX (__TEST_CMD_MAX - 1)
|
||||
|
||||
enum {
|
||||
TEST_ATTR_UNSPEC,
|
||||
TEST_ATTR_CMD_NAME,
|
||||
TEST_ATTR_CMD_TYPE,
|
||||
TEST_ATTR_PARA_NUM,
|
||||
TEST_ATTR_PARA0,
|
||||
TEST_ATTR_PARA1,
|
||||
TEST_ATTR_PARA2,
|
||||
TEST_ATTR_PARA3,
|
||||
TEST_ATTR_PARA4,
|
||||
TEST_ATTR_PARA5,
|
||||
TEST_ATTR_PARA6,
|
||||
TEST_ATTR_PARA7,
|
||||
TEST_ATTR_STR,
|
||||
__TEST_ATTR_MAX,
|
||||
};
|
||||
#define TEST_ATTR_MAX (__TEST_ATTR_MAX - 1)
|
||||
#define TEST_ATTR_PARA(i) (TEST_ATTR_PARA0+(i))
|
||||
|
||||
enum {
|
||||
RD_REG = 0,
|
||||
WR_REG,
|
||||
SET_SENSE,
|
||||
SET_TX_RATE,
|
||||
SET_TX_FREQ,
|
||||
TKIP_MIC_ERROR,
|
||||
RIFS_CTRL,
|
||||
BACKOFF,
|
||||
SET_RXSENSE,
|
||||
CONFIGURE_TRC,
|
||||
RDPER,
|
||||
RDRSSI,
|
||||
DBGTRC,
|
||||
WRMEM,
|
||||
RDMEM
|
||||
};
|
||||
|
||||
u32 get_loopback_num(void);
|
||||
u32 get_loopback_id(void);
|
||||
void inc_loopback_id(void);
|
||||
|
||||
void esp_test_ate_done_cb(char *ep);
|
||||
|
||||
struct sdiotest_param {
|
||||
atomic_t start;
|
||||
u32 mode; //1: read 2: write 3: read&write
|
||||
u32 addr;
|
||||
u32 idle_period; //in msec
|
||||
struct task_struct *thread;
|
||||
};
|
||||
|
||||
#endif //__TEST_MODE
|
||||
|
||||
|
||||
Reference in New Issue
Block a user