mirror of
https://github.com/revyos/thead-kernel.git
synced 2026-06-21 17:22:24 +02:00
Compare commits
97 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
62225503f5 | ||
|
|
dddd938847 | ||
|
|
49c39d9e97 | ||
|
|
918e660a58 | ||
|
|
b8c5d35460 | ||
|
|
afcdc418d4 | ||
|
|
d6f09caa32 | ||
|
|
727e6f3be6 | ||
|
|
2f78e6b748 | ||
|
|
cfe4413691 | ||
|
|
373e8161c5 | ||
|
|
9ba56a64a8 | ||
|
|
ad542ee013 | ||
|
|
e44f708a9e | ||
|
|
ccbbd8ae8f | ||
|
|
e286235a75 | ||
|
|
e084b32587 | ||
|
|
880ab177a1 | ||
|
|
c32beb855f | ||
|
|
8304fb3b0e | ||
|
|
51464f6592 | ||
|
|
f87b29df53 | ||
|
|
c71d194901 | ||
|
|
dc96c0fe68 | ||
|
|
5ffd7f5029 | ||
|
|
0f89c7db16 | ||
|
|
4a4a708db1 | ||
|
|
255c988024 | ||
|
|
af2602ac87 | ||
|
|
b6d74c3560 | ||
|
|
8f3347a598 | ||
|
|
9aa4002cc9 | ||
|
|
e025348004 | ||
|
|
58f804da14 | ||
|
|
277f5bc2bc | ||
|
|
2dc08a7dac | ||
|
|
05735e9ff4 | ||
|
|
d81a2398a8 | ||
|
|
e133903e4d | ||
|
|
8b4bca072c | ||
|
|
026ae08e53 | ||
|
|
95a545985b | ||
|
|
f722795a38 | ||
|
|
06bd593cfd | ||
|
|
556f057aca | ||
|
|
186355454e | ||
|
|
b25b9b6b16 | ||
|
|
35a32afaf8 | ||
|
|
3e042d29a3 | ||
|
|
c32ad7b836 | ||
|
|
99a459c9f7 | ||
|
|
c10fdb081d | ||
|
|
e3b22dbe54 | ||
|
|
b9526ccc12 | ||
|
|
f05fed4b3a | ||
|
|
3e8db613d4 | ||
|
|
e04af8ab30 | ||
|
|
a29e54cb02 | ||
|
|
fe82c45483 | ||
|
|
c64537c234 | ||
|
|
e0b5c2d836 | ||
|
|
65d28e339c | ||
|
|
383394d925 | ||
|
|
76d072714b | ||
|
|
f107c010f0 | ||
|
|
21488b4bba | ||
|
|
4090089096 | ||
|
|
48d0bea232 | ||
|
|
0f0b0abd92 | ||
|
|
2864ff8827 | ||
|
|
3b1e9db0d7 | ||
|
|
d7048c221b | ||
|
|
d92a0f15a5 | ||
|
|
e4706a16f3 | ||
|
|
34157258d7 | ||
|
|
825f6a577e | ||
|
|
f0fba63d97 | ||
|
|
790c65208f | ||
|
|
4f4ed3f042 | ||
|
|
4d4f6ba338 | ||
|
|
40ef3b0976 | ||
|
|
921113dc1d | ||
|
|
296d3dc80c | ||
|
|
d592c8d305 | ||
|
|
8d34c4a386 | ||
|
|
2360026a43 | ||
|
|
dd0b44d681 | ||
|
|
3366ec3f14 | ||
|
|
c2bb75e485 | ||
|
|
a854067698 | ||
|
|
580ea36ab7 | ||
|
|
2fac2fed77 | ||
|
|
ac080f0f32 | ||
|
|
22994ee8fd | ||
|
|
dd5c99c459 | ||
|
|
798c6e25dc | ||
|
|
ed4a257bd1 |
88
.github/workflows/kernel.yml
vendored
88
.github/workflows/kernel.yml
vendored
@@ -8,25 +8,29 @@ on:
|
||||
- cron: "0 2 * * *"
|
||||
|
||||
env:
|
||||
xuetie_toolchain: https://occ-oss-prod.oss-cn-hangzhou.aliyuncs.com/resource//1663142514282
|
||||
toolchain_file_name: Xuantie-900-gcc-linux-5.10.4-glibc-x86_64-V2.6.1-20220906.tar.gz
|
||||
xuantie_toolchain: https://occ-oss-prod.oss-cn-hangzhou.aliyuncs.com/resource//1698113812618
|
||||
toolchain_file_name: Xuantie-900-gcc-linux-5.10.4-glibc-x86_64-V2.8.0-20231018.tar.gz
|
||||
mainline_toolchain: https://github.com/riscv-collab/riscv-gnu-toolchain/releases/download/2023.10.18
|
||||
mainline_toolchain_file_name: riscv64-glibc-ubuntu-22.04-gcc-nightly-2023.10.18-nightly.tar.gz
|
||||
wget_alias: 'wget --retry-connrefused --waitretry=1 --read-timeout=20 --timeout=15 -t 0'
|
||||
ARCH: riscv
|
||||
board: lpi4a
|
||||
KBUILD_BUILD_USER: builder
|
||||
KBUILD_BUILD_HOST: revyos-riscv-builder
|
||||
KDEB_COMPRESS: xz
|
||||
KDEB_CHANGELOG_DIST: unstable
|
||||
|
||||
jobs:
|
||||
kernel:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- name: thead-gcc
|
||||
toolchain_tripe: riscv64-unknown-linux-gnu-
|
||||
- name: gcc-12
|
||||
toolchain_tripe: riscv64-linux-gnu-
|
||||
name: [thead-gcc, gcc-13]
|
||||
board: [lpi4a, ahead]
|
||||
|
||||
runs-on: ubuntu-22.04
|
||||
env:
|
||||
CROSS_COMPILE: ${{ matrix.toolchain_tripe }}
|
||||
CROSS_COMPILE: riscv64-unknown-linux-gnu-
|
||||
|
||||
steps:
|
||||
- name: Install software
|
||||
@@ -36,68 +40,50 @@ jobs:
|
||||
libncurses-dev gawk flex bison openssl libssl-dev tree \
|
||||
dkms libelf-dev libudev-dev libpci-dev libiberty-dev autoconf device-tree-compiler \
|
||||
devscripts
|
||||
sudo update-alternatives --install \
|
||||
/usr/bin/riscv64-linux-gnu-gcc riscv64-gcc /usr/bin/riscv64-linux-gnu-gcc-12 10
|
||||
sudo update-alternatives --install \
|
||||
/usr/bin/riscv64-linux-gnu-g++ riscv64-g++ /usr/bin/riscv64-linux-gnu-g++-12 10
|
||||
|
||||
- name: Checkout kernel
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: 'kernel'
|
||||
|
||||
- name: Configure toolchains
|
||||
run: |
|
||||
mkdir rootfs && mkdir rootfs/boot
|
||||
if [ x"${{ matrix.name }}" = x"thead-gcc" ]; then
|
||||
wget ${xuetie_toolchain}/${toolchain_file_name}
|
||||
tar -xvf ${toolchain_file_name} -C /opt
|
||||
fi
|
||||
|
||||
- name: Compile Kernel && Install
|
||||
run: |
|
||||
export PATH="/opt/Xuantie-900-gcc-linux-5.10.4-glibc-x86_64-V2.6.1/bin:$PATH"
|
||||
mkdir -p rootfs
|
||||
if [[ ${{ matrix.name }} = "thead-gcc" ]]; then
|
||||
${wget_alias} ${xuantie_toolchain}/${toolchain_file_name}
|
||||
tar -xvf ${toolchain_file_name} -C /opt
|
||||
export PATH="/opt/Xuantie-900-gcc-linux-5.10.4-glibc-x86_64-V2.8.0/bin:$PATH"
|
||||
else
|
||||
${wget_alias} ${mainline_toolchain}/${mainline_toolchain_file_name}
|
||||
tar -xvf ${mainline_toolchain_file_name} -C /opt
|
||||
export PATH="/opt/riscv/bin:$PATH"
|
||||
fi
|
||||
${CROSS_COMPILE}gcc -v
|
||||
|
||||
pushd kernel
|
||||
make revyos_defconfig
|
||||
export KDEB_PKGVERSION="$(date "+%Y.%m.%d.%H.%M")+$(git rev-parse --short HEAD)"
|
||||
if [ x"${{ matrix.name }}" = x"gcc-12" ]; then
|
||||
echo "CONFIG_THEAD_ISA=n" >> .config
|
||||
elif [ x"${{ matrix.name }}" = x"thead-gcc" ]; then
|
||||
echo "CONFIG_THEAD_ISA=y" >> .config
|
||||
if [ x"${{ matrix.board }}" = x"lpi4a" ]; then
|
||||
make revyos_defconfig
|
||||
elif [ x"${{ matrix.board }}" = x"ahead" ]; then
|
||||
make revyos_beaglev_defconfig
|
||||
fi
|
||||
make -j$(nproc) bindeb-pkg LOCALVERSION="-${board}"
|
||||
make -j$(nproc) dtbs
|
||||
# if [ x"$(cat .config | grep CONFIG_MODULES=y)" = x"CONFIG_MODULES=y" ]; then
|
||||
# sudo make INSTALL_MOD_PATH=${GITHUB_WORKSPACE}/rootfs/ modules_install -j$(nproc)
|
||||
# fi
|
||||
# sudo make INSTALL_PATH=${GITHUB_WORKSPACE}/rootfs/boot install -j$(nproc)
|
||||
export KDEB_PKGVERSION="$(date "+%Y.%m.%d.%H.%M")+$(git rev-parse --short HEAD)"
|
||||
sed -i '/CONFIG_LOCALVERSION_AUTO/d' .config && echo "CONFIG_LOCALVERSION_AUTO=n" >> .config
|
||||
cat .config | grep "CONFIG_THEAD_ISA"
|
||||
make -j$(nproc) bindeb-pkg LOCALVERSION="-${{ matrix.board }}"
|
||||
|
||||
# Copy deb
|
||||
sudo dcmd cp -v ../*.changes ${GITHUB_WORKSPACE}/rootfs/
|
||||
|
||||
# build perf & install
|
||||
# make LDFLAGS=-static NO_LIBELF=1 NO_JVMTI=1 VF=1 -C tools/perf/
|
||||
# sudo mkdir -p ${GITHUB_WORKSPACE}/rootfs/sbin/
|
||||
# sudo cp -v tools/perf/perf ${GITHUB_WORKSPACE}/rootfs/sbin/perf-thead
|
||||
|
||||
# Install Kernel
|
||||
# sudo cp -v arch/riscv/boot/Image ${GITHUB_WORKSPACE}/rootfs/boot/
|
||||
|
||||
# record commit-id
|
||||
git rev-parse HEAD > kernel-commitid
|
||||
sudo cp -v kernel-commitid ${GITHUB_WORKSPACE}/rootfs/boot/
|
||||
git rev-parse HEAD > ${{ matrix.board }}-kernel-commitid
|
||||
sudo cp -v ${{ matrix.board }}-kernel-commitid ${GITHUB_WORKSPACE}/rootfs/
|
||||
|
||||
# Install DTB
|
||||
sudo cp -v arch/riscv/boot/dts/thead/{light-lpi4a.dtb,light-lpi4a-16gb.dtb} ${GITHUB_WORKSPACE}/rootfs/boot/
|
||||
ls -al ${GITHUB_WORKSPACE}/rootfs/
|
||||
popd
|
||||
|
||||
- name: compress
|
||||
run: tar -zcvf thead-kernel-${{ matrix.name }}.tar.gz rootfs
|
||||
|
||||
- name: 'Upload Artifact'
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: thead-kernel-${{ matrix.name }}.tar.gz
|
||||
path: thead-kernel-${{ matrix.name }}.tar.gz
|
||||
name: thead-kernel-${{ matrix.name }}
|
||||
path: rootfs/*
|
||||
retention-days: 30
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -18,6 +18,7 @@
|
||||
*.c.[012]*.*
|
||||
*.dt.yaml
|
||||
*.dtb
|
||||
*.dtbo
|
||||
*.dtb.S
|
||||
*.dwo
|
||||
*.elf
|
||||
|
||||
@@ -18,6 +18,7 @@ config RISCV
|
||||
select ARCH_HAS_DEBUG_VM_PGTABLE
|
||||
select ARCH_HAS_DEBUG_VIRTUAL if MMU
|
||||
select ARCH_HAS_DEBUG_WX
|
||||
select ARCH_HAS_FAST_MULTIPLIER
|
||||
select ARCH_HAS_GCOV_PROFILE_ALL
|
||||
select ARCH_HAS_GIGANTIC_PAGE
|
||||
select ARCH_HAS_KCOV
|
||||
@@ -34,6 +35,7 @@ config RISCV
|
||||
select ARCH_KEEP_MEMBLOCK
|
||||
select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX
|
||||
select ARCH_OPTIONAL_KERNEL_RWX_DEFAULT
|
||||
select ARCH_USE_CMPXCHG_LOCKREF
|
||||
select ARCH_USE_QUEUED_SPINLOCKS
|
||||
select ARCH_USE_QUEUED_RWLOCKS
|
||||
select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT if MMU
|
||||
@@ -403,7 +405,9 @@ config VECTOR
|
||||
|
||||
config THEAD_ISA
|
||||
bool "T-HEAD extension ISA in AFLAGS with -march=_xtheadc"
|
||||
default n
|
||||
default y
|
||||
help
|
||||
Say N here if you want to disable xtheadc in the kernel.
|
||||
|
||||
endmenu
|
||||
|
||||
|
||||
@@ -50,10 +50,15 @@ endif
|
||||
# ISA string setting
|
||||
riscv-march-$(CONFIG_ARCH_RV32I) := rv32ima
|
||||
riscv-march-$(CONFIG_ARCH_RV64I) := rv64ima
|
||||
riscv-march-$(CONFIG_FPU) := $(riscv-march-y)fd
|
||||
riscv-march-$(CONFIG_FPU) := $(riscv-march-y)fd
|
||||
riscv-march-$(CONFIG_RISCV_ISA_C) := $(riscv-march-y)c
|
||||
riscv-march-$(CONFIG_VECTOR) := $(riscv-march-y)v0p7
|
||||
riscv-march-$(CONFIG_THEAD_ISA) := $(riscv-march-y)_xtheadc
|
||||
|
||||
# Fix mainline build
|
||||
toolchain-have-v0p7 := $(call cc-option-yn, -march=$(riscv-march-y)v0p7)
|
||||
riscv-march-$(toolchain-have-v0p7) := $(riscv-march-y)v0p7
|
||||
|
||||
toolchain-have-xtheadc := $(call cc-option-yn, -march=$(riscv-march-y)_xtheadc)
|
||||
riscv-march-$(toolchain-have-xtheadc) := $(riscv-march-y)_xtheadc
|
||||
|
||||
# Newer binutils versions default to ISA spec version 20191213 which moves some
|
||||
# instructions from the I extension to the Zicsr and Zifencei extensions.
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
ifeq ($(CONFIG_OF_OVERLAY),y)
|
||||
DTC_FLAGS += -@
|
||||
endif
|
||||
|
||||
subdir-y += sifive
|
||||
subdir-y += kendryte
|
||||
subdir-y += thead
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
ifeq ($(CONFIG_OF_OVERLAY),y)
|
||||
DTC_FLAGS += -@
|
||||
endif
|
||||
|
||||
dtb-$(CONFIG_SOC_THEAD) += ice.dtb
|
||||
dtb-$(CONFIG_SOC_THEAD) += light-fm-emu.dtb light_mpw.dtb
|
||||
dtb-$(CONFIG_SOC_THEAD) += light-fm-emu-npu-fce.dtb
|
||||
@@ -29,7 +34,7 @@ dtb-$(CONFIG_SOC_THEAD) += light-a-val-full.dtb
|
||||
dtb-$(CONFIG_SOC_THEAD) += light-ant-ref.dtb
|
||||
dtb-$(CONFIG_SOC_THEAD) += light-ant-discrete.dtb
|
||||
dtb-$(CONFIG_SOC_THEAD) += light-beagle.dtb
|
||||
dtb-$(CONFIG_SOC_THEAD) += light-lpi4a.dtb light-lpi4a-ddr2G.dtb light-lpi4a-16gb.dtb
|
||||
dtb-$(CONFIG_SOC_THEAD) += light-lpi4a.dtb light-lpi4a-ddr2G.dtb light-lpi4a-16gb.dtb light-lpi4a-dsi0-hdmi.dtb
|
||||
dtb-$(CONFIG_SOC_THEAD) += light-lpi4a-cluster.dtb light-lpi4a-cluster-16gb.dtb
|
||||
dtb-$(CONFIG_SOC_THEAD) += light-a-ref.dtb light-a-ref-dsi0.dtb light-a-ref-dsi0-hdmi.dtb
|
||||
dtb-$(CONFIG_SOC_THEAD) += light-b-ref.dtb
|
||||
@@ -42,3 +47,9 @@ dtb-$(CONFIG_SOC_THEAD) += fire-emu.dtb fire-emu-crash.dtb
|
||||
dtb-$(CONFIG_SOC_THEAD) += fire-emu-soc-base.dtb fire-emu-soc-c910x4.dtb fire-emu-gpu-dpu-dsi0.dtb fire-emu-vi-dsp-vo.dtb fire-emu-vi-vp-vo.dtb
|
||||
dtb-$(CONFIG_SOC_THEAD) += fire-emu-soc-base-sec.dtb
|
||||
dtb-$(CONFIG_SOC_THEAD) += light-lpi4a-laptop.dtb
|
||||
dtb-$(CONFIG_SOC_THEAD) += light-milkv-meles.dtb light-milkv-meles-4g.dtb
|
||||
|
||||
targets += dtbs dtbs_install
|
||||
targets += $(dtb-y)
|
||||
|
||||
subdir-y := overlays
|
||||
|
||||
1490
arch/riscv/boot/dts/thead/light-beagle-bone-buses.dtsi
Normal file
1490
arch/riscv/boot/dts/thead/light-beagle-bone-buses.dtsi
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,8 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2021 Alibaba Group Holding Limited.
|
||||
* Copyright (C) 2022 BeagleBoard.org - https://beagleboard.org/
|
||||
* Copyright (C) 2022 Deepak Khatri <lorforlinux@beagleboard.org>
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
@@ -10,13 +12,8 @@
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include "light-vi-devices.dtsi"
|
||||
/ {
|
||||
model = "T-HEAD Light val board";
|
||||
compatible = "thead,light-val", "thead,light";
|
||||
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
reg = <0x0 0x200000 0x0 0x7fe00000>;
|
||||
};
|
||||
model = "BeagleBoard.org BeagleV-Ahead";
|
||||
compatible = "beagle,light", "thead,light-val", "thead,light";
|
||||
|
||||
chosen {
|
||||
bootargs = "console=ttyS0,115200 crashkernel=256M-:128M earlycon clk_ignore_unused sram=0xffe0000000,0x180000";
|
||||
@@ -25,11 +22,42 @@
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
status = "disabled";
|
||||
led0 {
|
||||
label = "SYS_STATUS";
|
||||
gpios = <&gpio1_porta 15 0>; /* GPIO_ACTIVE_HIGH: 0 */
|
||||
default-state = "off";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&led_pins_default>;
|
||||
|
||||
led-0 {
|
||||
label = "beaglebone:green:usr0";
|
||||
gpios = <&ao_gpio4_porta 8 GPIO_ACTIVE_HIGH>;
|
||||
linux,default-trigger = "heartbeat";
|
||||
//function = LED_FUNCTION_HEARTBEAT;
|
||||
};
|
||||
|
||||
led-1 {
|
||||
label = "beaglebone:green:usr1";
|
||||
gpios = <&ao_gpio4_porta 9 GPIO_ACTIVE_HIGH>;
|
||||
linux,default-trigger = "mmc0";
|
||||
//function = LED_FUNCTION_DISK_ACTIVITY;
|
||||
};
|
||||
|
||||
led-2 {
|
||||
label = "beaglebone:green:usr2";
|
||||
gpios = <&ao_gpio4_porta 10 GPIO_ACTIVE_HIGH>;
|
||||
linux,default-trigger = "cpu";
|
||||
//function = LED_FUNCTION_CPU;
|
||||
};
|
||||
|
||||
led-3 {
|
||||
label = "beaglebone:green:usr3";
|
||||
gpios = <&ao_gpio4_porta 11 GPIO_ACTIVE_HIGH>;
|
||||
linux,default-trigger = "mmc1";
|
||||
//function = LED_FUNCTION_DISK_ACTIVITY;
|
||||
};
|
||||
|
||||
led-4 {
|
||||
label = "beaglebone:green:usr4";
|
||||
gpios = <&ao_gpio4_porta 12 GPIO_ACTIVE_HIGH>;
|
||||
linux,default-trigger = "netdev";
|
||||
//function = LED_FUNCTION_WLAN;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -194,10 +222,9 @@
|
||||
};
|
||||
|
||||
dummy_codec: dummy_codec {
|
||||
#sound-dai-cells = <0>;
|
||||
compatible = "thead,light-dummy-pcm";
|
||||
#sound-dai-cells = <1>;
|
||||
compatible = "linux,bt-sco";
|
||||
status = "okay";
|
||||
sound-name-prefix = "DUMMY";
|
||||
};
|
||||
|
||||
reg_vref_1v8: regulator-adc-verf {
|
||||
@@ -205,56 +232,9 @@
|
||||
regulator-name = "vref-1v8";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
reg_tp_pwr_en: regulator-pwr-en {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "PWR_EN";
|
||||
regulator-min-microvolt = <2800000>;
|
||||
regulator-max-microvolt = <2800000>;
|
||||
gpio = <&gpio1_porta 12 1>;
|
||||
enable-active-high;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
wcn_wifi: wireless-wlan {
|
||||
compatible = "wlan-platdata";
|
||||
clock-names = "clk_wifi";
|
||||
ref-clock-frequency = <24000000>;
|
||||
keep_wifi_power_on;
|
||||
pinctrl-names = "default";
|
||||
wifi_chip_type = "rtl8723ds";
|
||||
WIFI,poweren_gpio = <&gpio2_porta 29 0>;
|
||||
WIFI,reset_n = <&gpio2_porta 22 0>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
wcn_bt: wireless-bluetooth {
|
||||
compatible = "bluetooth-platdata";
|
||||
pinctrl-names = "default", "rts_gpio";
|
||||
BT,power_gpio = <&gpio2_porta 29 0>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
gpio-keys {
|
||||
compatible = "gpio-keys";
|
||||
pinctrl-0 = <&pinctrl_volume>;
|
||||
pinctrl-names = "default";
|
||||
key-volumedown {
|
||||
label = "Volume Down Key";
|
||||
linux,code = <KEY_VOLUMEDOWN>;
|
||||
debounce-interval = <1>;
|
||||
gpios = <&gpio1_porta 19 0x1>;
|
||||
};
|
||||
key-volumeup {
|
||||
label = "Volume Up Key";
|
||||
linux,code = <KEY_VOLUMEUP>;
|
||||
debounce-interval = <1>;
|
||||
gpios = <&gpio2_porta 25 0x1>;
|
||||
};
|
||||
};
|
||||
|
||||
aon: aon {
|
||||
compatible = "thead,light-aon";
|
||||
mbox-names = "aon";
|
||||
@@ -286,119 +266,6 @@
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
soc_vdd_3v3_en_reg: soc_vdd_3v3_en {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "soc_vdd_3v3_en";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
gpio = <&gpio0_porta 30 1>;
|
||||
enable-active-high;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
soc_lcd0_bias_en_reg: soc_lcd0_bias_en {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "soc_lcd0_bias_en";
|
||||
regulator-min-microvolt = <5700000>;
|
||||
regulator-max-microvolt = <5700000>;
|
||||
gpio = <&gpio1_porta 10 1>;
|
||||
enable-active-high;
|
||||
};
|
||||
|
||||
soc_vdd18_lcd0_en_reg: soc_lcd0_en {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "soc_lcd0_en";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
gpio = <&gpio1_porta 9 1>;
|
||||
enable-active-high;
|
||||
};
|
||||
|
||||
soc_vdd5v_se_en_reg: soc_vdd5v_se_en {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "soc_vdd5v_se_en";
|
||||
regulator-min-microvolt = <5000000>;
|
||||
regulator-max-microvolt = <5000000>;
|
||||
gpio = <&gpio2_porta 14 1>;
|
||||
enable-active-high;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
soc_wcn33_en_reg: soc_wcn33_en {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "soc_wcn33_en";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
gpio = <&gpio2_porta 29 1>;
|
||||
enable-active-high;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
soc_vbus_en_reg: soc_vbus_en {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "soc_vbus_en";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
gpio = <&gpio2_porta 28 1>;
|
||||
enable-active-high;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
|
||||
soc_avdd28_rgb_reg: soc_avdd28_rgb {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "soc_avdd28_rgb";
|
||||
regulator-min-microvolt = <2800000>;
|
||||
regulator-max-microvolt = <2800000>;
|
||||
gpio = <&gpio1_porta 15 1>;
|
||||
enable-active-high;
|
||||
};
|
||||
|
||||
soc_dovdd18_rgb_reg: soc_dovdd18_rgb {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "soc_dovdd18_rgb";
|
||||
regulator-min-microvolt = <2800000>;
|
||||
regulator-max-microvolt = <2800000>;
|
||||
gpio = <&gpio1_porta 13 1>;
|
||||
enable-active-high;
|
||||
};
|
||||
|
||||
soc_dvdd12_rgb_reg: soc_dvdd12_rgb {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "soc_dvdd12_rgb";
|
||||
regulator-min-microvolt = <2800000>;
|
||||
regulator-max-microvolt = <2800000>;
|
||||
gpio = <&gpio1_porta 14 1>;
|
||||
enable-active-high;
|
||||
};
|
||||
|
||||
soc_avdd25_ir_reg: soc_avdd25_ir {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "soc_avdd25_ir";
|
||||
regulator-min-microvolt = <2500000>;
|
||||
regulator-max-microvolt = <2500000>;
|
||||
gpio = <&gpio0_porta 28 1>;
|
||||
enable-active-high;
|
||||
};
|
||||
|
||||
soc_dovdd18_ir_reg: soc_dovdd18_ir {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "soc_dovdd18_ir";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
gpio = <&gpio1_porta 13 1>;
|
||||
enable-active-high;
|
||||
};
|
||||
|
||||
soc_dvdd12_ir_reg: soc_dvdd12_ir {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "soc_dvdd12_ir";
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <1200000>;
|
||||
gpio = <&gpio0_porta 29 1>;
|
||||
enable-active-high;
|
||||
};
|
||||
|
||||
aon_reg_dialog: light-dialog-reg {
|
||||
compatible = "thead,light-dialog-pmic-ant";
|
||||
status = "okay";
|
||||
@@ -620,10 +487,11 @@
|
||||
w25q,fast-read;
|
||||
};
|
||||
|
||||
spidev@1 {
|
||||
compatible = "spidev";
|
||||
channel@1 {
|
||||
compatible = "rohm,dh2228fv";
|
||||
//symlink = "bone/spi/0.1";
|
||||
#address-cells = <0x1>;
|
||||
#size-cells = <0x1>;
|
||||
#size-cells = <0x0>;
|
||||
reg = <0x1>;
|
||||
spi-max-frequency = <50000000>;
|
||||
};
|
||||
@@ -659,10 +527,11 @@
|
||||
compatible = "snps,dw-apb-ssi";
|
||||
num-cs = <1>;
|
||||
cs-gpios = <&gpio0_porta 1 0>;
|
||||
status = "okay";
|
||||
status = "disabled";
|
||||
|
||||
spidev@0 {
|
||||
compatible = "spidev";
|
||||
channel@0 {
|
||||
compatible = "rohm,dh2228fv";
|
||||
//symlink = "bone/spi/1.1";
|
||||
#address-cells = <0x1>;
|
||||
#size-cells = <0x1>;
|
||||
reg = <0x0>;
|
||||
@@ -740,7 +609,7 @@
|
||||
};
|
||||
|
||||
&padctrl0_apsys { /* right-pinctrl */
|
||||
light-evb-padctrl0 {
|
||||
light_padctrl0: light-evb-padctrl0 {
|
||||
/*
|
||||
* Pin Configuration Node:
|
||||
* Format: <pin_id mux_node config>
|
||||
@@ -789,12 +658,20 @@
|
||||
thead,pins = <
|
||||
FM_GPIO3_2 0x1 0x208 /* pwm0 */
|
||||
>;
|
||||
};
|
||||
};
|
||||
|
||||
pinctrl_bt: btgrp {
|
||||
thead,pins = <
|
||||
FM_SDIO1_WPRTN 0x3 0x72
|
||||
FM_SDIO1_DETN 0x3 0x72
|
||||
FM_GPIO2_30 0x0 0x72
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&padctrl1_apsys { /* left-pinctrl */
|
||||
light-evb-padctrl1 {
|
||||
light_padctrl1: light-evb-padctrl1 {
|
||||
/*
|
||||
* Pin Configuration Node:
|
||||
* Format: <pin_id mux_node config>
|
||||
@@ -833,18 +710,24 @@
|
||||
FM_QSPI1_D2_WP 0x1 0x238
|
||||
FM_QSPI1_D3_HOLD 0x1 0x238
|
||||
>;
|
||||
};
|
||||
|
||||
pinctrl_volume: volume_grp {
|
||||
thead,pins = <
|
||||
FM_CLK_OUT_2 0x3 0x208
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
PIN , 0x0, 0x1, 0x2, 0x3, 0x4, 0x5
|
||||
AUDIO_PA8, AUDIO_PA8, NULL, NULL, GPIO4_8, NULL, NULL
|
||||
AUDIO_PA9, AUDIO_PA9, NULL, NULL, GPIO4_9, NULL, NULL
|
||||
AUDIO_PA10, AUDIO_PA10, NULL, NULL, GPIO4_10, NULL, NULL
|
||||
AUDIO_PA11, AUDIO_PA11, NULL, NULL, GPIO4_11, NULL, NULL
|
||||
AUDIO_PA12, AUDIO_PA12, NULL, NULL, GPIO4_12, NULL, NULL
|
||||
*/
|
||||
|
||||
#define FM_AUDIO_PA8_AUDIO_PA8 0x00
|
||||
#define FM_AUDIO_PA8_GPIO 0x03
|
||||
|
||||
&padctrl_aosys {
|
||||
light-aon-padctrl {
|
||||
light_padctrl: light-aon-padctrl {
|
||||
/*
|
||||
* Pin Configuration Node:
|
||||
* Format: <pin_id mux_node config>
|
||||
@@ -862,12 +745,26 @@
|
||||
>;
|
||||
};
|
||||
|
||||
led_pins_default: leds0_grp {
|
||||
thead,pins = <
|
||||
FM_AUDIO_PA8 0x3 0x72
|
||||
FM_AUDIO_PA9 0x3 0x72
|
||||
FM_AUDIO_PA10 0x3 0x72
|
||||
FM_AUDIO_PA11 0x3 0x72
|
||||
FM_AUDIO_PA12 0x3 0x72
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&i2c0 {
|
||||
clock-frequency = <400000>;
|
||||
status = "okay";
|
||||
|
||||
eeprom@50 {
|
||||
compatible = "atmel,24c32";
|
||||
reg = <0x50>;
|
||||
};
|
||||
};
|
||||
|
||||
&i2c1 {
|
||||
@@ -953,85 +850,6 @@
|
||||
memory-region = <&dsp1_mem>;
|
||||
};
|
||||
|
||||
&vvcam_flash_led0{
|
||||
flash_led_name = "aw36413_aw36515";
|
||||
floodlight_i2c_bus = /bits/ 8 <2>;
|
||||
floodlight_en_pin = <&gpio1_porta 26 0>;
|
||||
projection_i2c_bus = /bits/ 8 <1>;
|
||||
flash_led_touch_pin = <&gpio1_porta 27 0>; //flash led touch pin
|
||||
io-channels = <&adc 2>;
|
||||
io-channel-names = "projection_adc";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&vvcam_sensor0 {
|
||||
sensor_name = "SC2310";
|
||||
sensor_regulators = "DOVDD18_RGB", "DVDD12_RGB", "AVDD28_RGB";
|
||||
sensor_regulator_timing_us = <70 50 20>;
|
||||
sensor_pdn = <&gpio1_porta 21 0>; //powerdown pin / shutdown pin
|
||||
sensor_rst = <&gpio1_porta 16 0>;
|
||||
sensor_pdn_delay_us = <4000>; //powerdown pin / shutdown pin actived till I2C ready
|
||||
DOVDD18_RGB-supply = <&soc_dovdd18_rgb_reg>;
|
||||
DVDD12_RGB-supply = <&soc_dvdd12_rgb_reg>;
|
||||
AVDD28_RGB-supply = <&soc_avdd28_rgb_reg>;
|
||||
i2c_reg_width = /bits/ 8 <2>;
|
||||
i2c_data_width = /bits/ 8 <1>;
|
||||
i2c_addr = /bits/ 8 <0x30>;
|
||||
i2c_bus = /bits/ 8 <3>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&vvcam_sensor1 {
|
||||
sensor_name = "SC132GS";
|
||||
sensor_regulators = "DOVDD18_IR", "DVDD12_IR", "AVDD25_IR";
|
||||
sensor_regulator_timing_us = <70 1000 2000>;
|
||||
i2c_addr = /bits/ 8 <0x31>;
|
||||
sensor_pdn = <&gpio1_porta 28 0>; //powerdown pin / shutdown pin
|
||||
sensor_rst = <&gpio1_porta 24 0>;
|
||||
sensor_pdn_delay_us = <2000>; //powerdown pin / shutdown pin actived till I2C ready
|
||||
DOVDD18_IR-supply = <&soc_dovdd18_ir_reg>;
|
||||
DVDD12_IR-supply = <&soc_dvdd12_ir_reg>;
|
||||
AVDD25_IR-supply = <&soc_avdd25_ir_reg>;
|
||||
i2c_reg_width = /bits/ 8 <2>;
|
||||
i2c_data_width = /bits/ 8 <1>;
|
||||
i2c_bus = /bits/ 8 <2>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&vvcam_sensor2 {
|
||||
sensor_name = "GC5035";
|
||||
sensor_regulators = "DOVDD18_SCAN", "DVDD12_SCAN", "AVDD28_SCAN";
|
||||
sensor_regulator_timing_us = <100 50 0>;
|
||||
sensor_pdn = <&gpio1_porta 30 0>; //powerdown pin / shutdown pin
|
||||
sensor_rst = <&gpio1_porta 29 0>;
|
||||
sensor_pdn_delay_us = <1000>; //powerdown pin / shutdown pin actived till I2C ready
|
||||
DOVDD18_SCAN-supply = <&soc_dovdd18_scan_reg>;
|
||||
DVDD12_SCAN-supply = <&soc_dvdd12_scan_reg>;
|
||||
AVDD28_SCAN-supply = <&soc_avdd28_scan_en_reg>;
|
||||
i2c_addr = /bits/ 8 <0x37>;
|
||||
i2c_bus = /bits/ 8 <4>;
|
||||
i2c_reg_width = /bits/ 8 <1>;
|
||||
i2c_data_width = /bits/ 8 <1>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&vvcam_sensor3 {
|
||||
sensor_name = "GC02M1B";
|
||||
sensor_regulators = "DOVDD18_SCAN", "DVDD12_SCAN", "AVDD28_SCAN";
|
||||
sensor_regulator_timing_us = <100 50 0>;
|
||||
sensor_pdn = <&gpio1_porta 30 0>; //powerdown pin / shutdown pin
|
||||
sensor_rst = <&gpio1_porta 29 0>;
|
||||
sensor_pdn_delay_us = <1000>; //powerdown pin / shutdown pin actived till I2C ready
|
||||
DOVDD18_SCAN-supply = <&soc_dovdd18_scan_reg>;
|
||||
DVDD12_SCAN-supply = <&soc_dvdd12_scan_reg>;
|
||||
AVDD28_SCAN-supply = <&soc_avdd28_scan_en_reg>;
|
||||
i2c_addr = /bits/ 8 <0x37>;
|
||||
i2c_bus = /bits/ 8 <4>;
|
||||
i2c_reg_width = /bits/ 8 <1>;
|
||||
i2c_data_width = /bits/ 8 <1>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&video0{
|
||||
vi_mem_pool_region = <2>; // vi_mem: framebuffer, region[2]
|
||||
channel0 {
|
||||
@@ -2179,21 +1997,6 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&dpu_enc0 {
|
||||
status = "okay";
|
||||
|
||||
ports {
|
||||
/* output */
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
|
||||
enc0_out: endpoint {
|
||||
remote-endpoint = <&dsi0_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&dpu_enc1 {
|
||||
ports {
|
||||
/delete-node/ port@0;
|
||||
@@ -2204,46 +2007,6 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&dsi0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&dhost_0 {
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
|
||||
dsi0_in: endpoint {
|
||||
remote-endpoint = <&enc0_out>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
|
||||
dsi0_out: endpoint {
|
||||
remote-endpoint = <&panel0_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
panel0@0 {
|
||||
compatible = "i2c_dsi,ili9881d";
|
||||
reg = <0>;
|
||||
mcu_auto_reset_enable = <0>;
|
||||
tp_point_rotate = <0>;
|
||||
|
||||
port {
|
||||
panel0_in: endpoint {
|
||||
remote-endpoint = <&dsi0_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&disp1_out {
|
||||
remote-endpoint = <&hdmi_tx_in>;
|
||||
};
|
||||
@@ -2261,11 +2024,6 @@
|
||||
|
||||
&lightsound {
|
||||
status = "okay";
|
||||
simple-audio-card,widgets = "Speaker", "Speaker";
|
||||
simple-audio-card,routing =
|
||||
"Speaker", "AW87519 VO",
|
||||
"AW87519 IN", "ES8156 ROUT";
|
||||
simple-audio-card,aux-devs = <&audio_aw87519_pa>;
|
||||
simple-audio-card,dai-link@0 { /* I2S - AUDIO SYS CODEC 8156*/
|
||||
reg = <0>;
|
||||
format = "i2s";
|
||||
@@ -2293,13 +2051,13 @@
|
||||
sound-dai = <&light_i2s 1>;
|
||||
};
|
||||
codec {
|
||||
sound-dai = <&dummy_codec>;
|
||||
sound-dai = <&dummy_codec 2>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&light_i2s {
|
||||
status = "okay";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&i2s0 {
|
||||
@@ -2321,12 +2079,14 @@
|
||||
300000 650000
|
||||
800000 700000
|
||||
1500000 800000
|
||||
1848000 1000000
|
||||
>;
|
||||
light,dvddm-operating-points = <
|
||||
/* kHz uV */
|
||||
300000 800000
|
||||
800000 800000
|
||||
1500000 800000
|
||||
1848000 1000000
|
||||
>;
|
||||
};
|
||||
c910_1: cpu@1 {
|
||||
@@ -2335,12 +2095,14 @@
|
||||
300000 650000
|
||||
800000 700000
|
||||
1500000 800000
|
||||
1848000 1000000
|
||||
>;
|
||||
light,dvddm-operating-points = <
|
||||
/* kHz uV */
|
||||
300000 800000
|
||||
800000 800000
|
||||
1500000 800000
|
||||
1848000 1000000
|
||||
>;
|
||||
};
|
||||
c910_2: cpu@2 {
|
||||
@@ -2350,12 +2112,14 @@
|
||||
300000 650000
|
||||
800000 700000
|
||||
1500000 800000
|
||||
1848000 1000000
|
||||
>;
|
||||
light,dvddm-operating-points = <
|
||||
/* kHz uV */
|
||||
300000 800000
|
||||
800000 800000
|
||||
1500000 800000
|
||||
1848000 1000000
|
||||
>;
|
||||
};
|
||||
c910_3: cpu@3 {
|
||||
@@ -2365,12 +2129,14 @@
|
||||
300000 650000
|
||||
800000 700000
|
||||
1500000 800000
|
||||
1848000 1000000
|
||||
>;
|
||||
light,dvddm-operating-points = <
|
||||
/* kHz uV */
|
||||
300000 800000
|
||||
800000 800000
|
||||
1500000 800000
|
||||
1848000 1000000
|
||||
>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -7,6 +7,27 @@
|
||||
|
||||
#include "light-beagle-ref.dts"
|
||||
|
||||
/ {
|
||||
bcmdhd_wlan {
|
||||
compatible = "android,bcmdhd_wlan";
|
||||
|
||||
gpio_wl_reg_on = <&gpio2_porta 31 1>;
|
||||
gpio_wl_host_wake = <&gpio2_porta 25 1>;
|
||||
};
|
||||
};
|
||||
|
||||
&pwm {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&qspi0 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&qspi1 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&vvcam_sensor4 { // beagle board J5 CSI0 connector
|
||||
sensor_name = "IMX219";
|
||||
sensor_pdn = <&gpio2_porta 23 0>; //powerdown pin / shutdown pin
|
||||
@@ -703,3 +724,5 @@ video12: tuningtool
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
#include "light-beagle-bone-buses.dtsi"
|
||||
|
||||
@@ -24,3 +24,7 @@
|
||||
®_usb_hub_vdd1v2 {
|
||||
/delete-property/ gpio;
|
||||
};
|
||||
|
||||
®_usb_hub_vcc5v {
|
||||
/delete-property/ gpio;
|
||||
};
|
||||
|
||||
@@ -24,3 +24,7 @@
|
||||
®_usb_hub_vdd1v2 {
|
||||
/delete-property/ gpio;
|
||||
};
|
||||
|
||||
®_usb_hub_vcc5v {
|
||||
/delete-property/ gpio;
|
||||
};
|
||||
|
||||
131
arch/riscv/boot/dts/thead/light-lpi4a-dsi0-hdmi.dts
Normal file
131
arch/riscv/boot/dts/thead/light-lpi4a-dsi0-hdmi.dts
Normal file
@@ -0,0 +1,131 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2022 Alibaba Group Holding Limited.
|
||||
*/
|
||||
|
||||
#include "light-lpi4a-ref.dts"
|
||||
|
||||
/ {
|
||||
model = "T-HEAD Light Lichee Pi 4A configuration for 8GB DDR board";
|
||||
compatible = "thead,light-val", "thead,light-lpi4a", "thead,light";
|
||||
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
reg = <0x0 0x00000000 0x2 0x00000000>;
|
||||
};
|
||||
};
|
||||
|
||||
&cmamem {
|
||||
alloc-ranges = <0x1 0xe4000000 0 0x14000000>; // [0x1E400_0000 ~ 0x1F800_0000]
|
||||
};
|
||||
|
||||
&pwm {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&qspi0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&qspi1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&i2c3 {
|
||||
touch@14 {
|
||||
#gpio-cells = <2>;
|
||||
compatible = "goodix,gt9271";
|
||||
reg = <0x14>;
|
||||
interrupt-parent = <&ao_gpio_porta>;
|
||||
interrupts = <3 0>;
|
||||
irq-gpios = <&ao_gpio_porta 3 0>;
|
||||
reset-gpios = <&pcal6408ahk_d 0 0>;
|
||||
AVDD28-supply = <®_tp_pwr_en>;
|
||||
touchscreen-size-x = <800>;
|
||||
touchscreen-size-y = <1280>;
|
||||
tp-size = <9271>;
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
|
||||
&dpu_enc0 {
|
||||
status = "okay";
|
||||
|
||||
ports {
|
||||
/* output */
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
|
||||
enc0_out: endpoint {
|
||||
remote-endpoint = <&dsi0_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&dpu_enc1 {
|
||||
ports {
|
||||
/delete-node/ port@0;
|
||||
};
|
||||
};
|
||||
|
||||
&dpu {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&dsi0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&dhost_0 {
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
|
||||
dsi0_in: endpoint {
|
||||
remote-endpoint = <&enc0_out>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
|
||||
dsi0_out: endpoint {
|
||||
remote-endpoint = <&panel0_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
panel0@0 {
|
||||
compatible = "chongzhou,cz101b4001", "jadard,jd9365da-h3";
|
||||
reg = <0>;
|
||||
backlight = <&lcd0_backlight>;
|
||||
reset-gpio = <&pcal6408ahk_d 7 0>; /* active low */
|
||||
hsvcc-supply = <&soc_vdd18_lcd0_en_reg>;
|
||||
vspn3v3-supply = <&soc_vdd33_lcd0_en_reg>;
|
||||
|
||||
port {
|
||||
panel0_in: endpoint {
|
||||
remote-endpoint = <&dsi0_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&disp1_out {
|
||||
remote-endpoint = <&hdmi_tx_in>;
|
||||
};
|
||||
|
||||
&hdmi_tx {
|
||||
status = "okay";
|
||||
|
||||
port@0 {
|
||||
/* input */
|
||||
hdmi_tx_in: endpoint {
|
||||
remote-endpoint = <&disp1_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
16
arch/riscv/boot/dts/thead/light-milkv-meles-4g.dts
Normal file
16
arch/riscv/boot/dts/thead/light-milkv-meles-4g.dts
Normal file
@@ -0,0 +1,16 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2022 Alibaba Group Holding Limited.
|
||||
*/
|
||||
|
||||
#include "light-milkv-meles.dts"
|
||||
|
||||
/ {
|
||||
model = "Milk-V Meles 4G";
|
||||
compatible = "milkv,meles", "thead,light";
|
||||
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
reg = <0x0 0x200000 0x0 0xffe00000>;
|
||||
};
|
||||
};
|
||||
885
arch/riscv/boot/dts/thead/light-milkv-meles.dts
Normal file
885
arch/riscv/boot/dts/thead/light-milkv-meles.dts
Normal file
@@ -0,0 +1,885 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2021-2022 Alibaba Group Holding Limited.
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
#include "light.dtsi"
|
||||
#include <dt-bindings/input/linux-event-codes.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
/ {
|
||||
model = "Milk-V Meles";
|
||||
compatible = "milkv,meles", "thead,light";
|
||||
|
||||
aliases {
|
||||
mmc0 = &emmc;
|
||||
mmc1 = &sdhci0;
|
||||
mmc2 = &sdhci1;
|
||||
};
|
||||
|
||||
chosen {
|
||||
bootargs = "console=ttyS0,115200 crashkernel=256M-:128M earlycon clk_ignore_unused sram=0xffe0000000,0x180000";
|
||||
stdout-path = "serial0:115200n8";
|
||||
};
|
||||
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
reg = <0x0 0x200000 0x1 0xffe00000>;
|
||||
};
|
||||
|
||||
display_subsystem: display-subsystem {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
|
||||
led0 {
|
||||
label = "SYS_STATUS";
|
||||
gpios = <&gpio1_porta 15 0>; /* GPIO_ACTIVE_HIGH: 0 */
|
||||
default-state = "off";
|
||||
};
|
||||
|
||||
led1 {
|
||||
label = "USER_LED";
|
||||
gpios = <&gpio1_porta 16 0>; /* GPIO_ACTIVE_HIGH: 0 */
|
||||
linux,default-trigger = "heartbeat";
|
||||
default-state = "on";
|
||||
};
|
||||
};
|
||||
|
||||
light_iopmp: iopmp {
|
||||
compatible = "thead,light-iopmp";
|
||||
|
||||
/* config#1: multiple valid regions */
|
||||
iopmp_emmc: IOPMP_EMMC {
|
||||
regions = <0x000000 0x100000>,
|
||||
<0x100000 0x200000>;
|
||||
attr = <0xFFFFFFFF>;
|
||||
dummy_slave= <0x800000>;
|
||||
};
|
||||
|
||||
/* config#2: iopmp bypass */
|
||||
iopmp_sdio0: IOPMP_SDIO0 {
|
||||
bypass_en;
|
||||
};
|
||||
|
||||
/* config#3: iopmp default region set */
|
||||
iopmp_sdio1: IOPMP_SDIO1 {
|
||||
attr = <0xFFFFFFFF>;
|
||||
is_default_region;
|
||||
};
|
||||
|
||||
iopmp_usb0: IOPMP_USB0 {
|
||||
attr = <0xFFFFFFFF>;
|
||||
is_default_region;
|
||||
};
|
||||
|
||||
iopmp_ao: IOPMP_AO {
|
||||
is_default_region;
|
||||
};
|
||||
|
||||
iopmp_aud: IOPMP_AUD {
|
||||
is_default_region;
|
||||
};
|
||||
|
||||
iopmp_chip_dbg: IOPMP_CHIP_DBG {
|
||||
is_default_region;
|
||||
};
|
||||
|
||||
iopmp_eip120i: IOPMP_EIP120I {
|
||||
is_default_region;
|
||||
};
|
||||
|
||||
iopmp_eip120ii: IOPMP_EIP120II {
|
||||
is_default_region;
|
||||
};
|
||||
|
||||
iopmp_eip120iii: IOPMP_EIP120III {
|
||||
is_default_region;
|
||||
};
|
||||
|
||||
iopmp_isp0: IOPMP_ISP0 {
|
||||
is_default_region;
|
||||
};
|
||||
|
||||
iopmp_isp1: IOPMP_ISP1 {
|
||||
is_default_region;
|
||||
};
|
||||
|
||||
iopmp_dw200: IOPMP_DW200 {
|
||||
is_default_region;
|
||||
};
|
||||
|
||||
iopmp_vipre: IOPMP_VIPRE {
|
||||
is_default_region;
|
||||
};
|
||||
|
||||
iopmp_venc: IOPMP_VENC {
|
||||
is_default_region;
|
||||
};
|
||||
|
||||
iopmp_vdec: IOPMP_VDEC {
|
||||
is_default_region;
|
||||
};
|
||||
|
||||
iopmp_g2d: IOPMP_G2D {
|
||||
is_default_region;
|
||||
};
|
||||
|
||||
iopmp_fce: IOPMP_FCE {
|
||||
is_default_region;
|
||||
};
|
||||
|
||||
iopmp_npu: IOPMP_NPU {
|
||||
is_default_region;
|
||||
};
|
||||
|
||||
iopmp0_dpu: IOPMP0_DPU {
|
||||
bypass_en;
|
||||
};
|
||||
|
||||
iopmp1_dpu: IOPMP1_DPU {
|
||||
bypass_en;
|
||||
};
|
||||
|
||||
iopmp_gpu: IOPMP_GPU {
|
||||
is_default_region;
|
||||
};
|
||||
|
||||
iopmp_gmac1: IOPMP_GMAC1 {
|
||||
is_default_region;
|
||||
};
|
||||
|
||||
iopmp_gmac2: IOPMP_GMAC2 {
|
||||
is_default_region;
|
||||
};
|
||||
|
||||
iopmp_dmac: IOPMP_DMAC {
|
||||
is_default_region;
|
||||
};
|
||||
|
||||
iopmp_tee_dmac: IOPMP_TEE_DMAC {
|
||||
is_default_region;
|
||||
};
|
||||
|
||||
iopmp_dsp0: IOPMP_DSP0 {
|
||||
is_default_region;
|
||||
};
|
||||
|
||||
iopmp_dsp1: IOPMP_DSP1 {
|
||||
is_default_region;
|
||||
};
|
||||
};
|
||||
|
||||
mbox_910t_client1: mbox_910t_client1 {
|
||||
compatible = "thead,light-mbox-client";
|
||||
mbox-names = "902";
|
||||
mboxes = <&mbox_910t 1 0>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
mbox_910t_client2: mbox_910t_client2 {
|
||||
compatible = "thead,light-mbox-client";
|
||||
mbox-names = "906";
|
||||
mboxes = <&mbox_910t 2 0>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
lightsound: lightsound@1 {
|
||||
status = "okay";
|
||||
compatible = "simple-audio-card";
|
||||
simple-audio-card,name = "Light-Sound-Card";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
/* I2S - AUDIO SYS CODEC 8156*/
|
||||
simple-audio-card,dai-link@0 {
|
||||
reg = <0>;
|
||||
format = "i2s";
|
||||
cpu {
|
||||
sound-dai = <&i2s1 0>;
|
||||
};
|
||||
codec {
|
||||
sound-dai = <&es8156_audio_codec>;
|
||||
};
|
||||
};
|
||||
|
||||
/* I2S - HDMI */
|
||||
simple-audio-card,dai-link@1 {
|
||||
reg = <1>;
|
||||
format = "i2s";
|
||||
cpu {
|
||||
sound-dai = <&light_i2s 1>;
|
||||
};
|
||||
codec {
|
||||
sound-dai = <&dummy_codec>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
wifi_pwrseq: wifi-pwrseq {
|
||||
status = "okay";
|
||||
compatible = "mmc-pwrseq-simple";
|
||||
reset-gpios = <&gpio0_porta 20 1>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_wireless_power>;
|
||||
};
|
||||
|
||||
dummy_codec: dummy_codec {
|
||||
#sound-dai-cells = <0>;
|
||||
compatible = "thead,light-dummy-pcm";
|
||||
status = "okay";
|
||||
sound-name-prefix = "DUMMY";
|
||||
};
|
||||
|
||||
vdd_5v: regulator-vdd-5v {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vdd_5v";
|
||||
regulator-min-microvolt = <5000000>;
|
||||
regulator-max-microvolt = <5000000>;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
vdd_1v8: regulator-vdd-1v8 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vdd_1v8";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
vin-supply = <&vdd_5v>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
reg_vref_1v8: regulator-adc-verf {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vref-1v8";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
vcc_usb_en: regulator-usb-en {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vcc_usb_en";
|
||||
gpio = <&gpio2_porta 30 1>; /* GPIO_ACTIVE_LOW: 1 */
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
aon {
|
||||
compatible = "thead,light-aon";
|
||||
mbox-names = "aon";
|
||||
mboxes = <&mbox_910t 1 0>;
|
||||
status = "okay";
|
||||
|
||||
pd: light-aon-pd {
|
||||
compatible = "thead,light-aon-pd";
|
||||
#power-domain-cells = <1>;
|
||||
};
|
||||
|
||||
aon_reg_dialog: light-dialog-reg {
|
||||
compatible = "thead,light-dialog-pmic-ant";
|
||||
status = "okay";
|
||||
|
||||
dvdd_cpu_reg: appcpu_dvdd {
|
||||
regulator-name = "appcpu_dvdd";
|
||||
regulator-min-microvolt = <300000>;
|
||||
regulator-max-microvolt = <1570000>;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
dvddm_cpu_reg: appcpu_dvddm {
|
||||
regulator-name = "appcpu_dvddm";
|
||||
regulator-min-microvolt = <300000>;
|
||||
regulator-max-microvolt = <1570000>;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
soc_dvdd18_aon_reg: soc_dvdd18_aon {
|
||||
regulator-name = "soc_dvdd18_aon";
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
soc_avdd33_usb3_reg: soc_avdd33_usb3 {
|
||||
regulator-name = "soc_avdd33_usb3";
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
soc_dvdd08_aon_reg: soc_dvdd08_aon {
|
||||
regulator-name = "soc_dvdd08_aon";
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
soc_dvdd08_ddr_reg: soc_dvdd08_ddr {
|
||||
regulator-name = "soc_dvdd08_ddr";
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
soc_vdd_ddr_1v8_reg: soc_vdd_ddr_1v8 {
|
||||
regulator-name = "soc_vdd_ddr_1v8";
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
soc_vdd_ddr_1v1_reg: soc_vdd_ddr_1v1 {
|
||||
regulator-name = "soc_vdd_ddr_1v1";
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
soc_vdd_ddr_0v6_reg: soc_vdd_ddr_0v6 {
|
||||
regulator-name = "soc_vdd_ddr_0v6";
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
soc_dvdd18_ap_reg: soc_dvdd18_ap {
|
||||
regulator-name = "soc_dvdd18_ap";
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
soc_avdd08_mipi_hdmi_reg: soc_avdd08_mipi_hdmi {
|
||||
regulator-name = "soc_avdd08_mipi_hdmi";
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
soc_avdd18_mipi_hdmi_reg: soc_avdd18_mipi_hdmi {
|
||||
regulator-name = "soc_avdd18_mipi_hdmi";
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
soc_vdd33_emmc_reg: soc_vdd33_emmc {
|
||||
regulator-name = "soc_vdd33_emmc";
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
soc_vdd18_emmc_reg: soc_vdd18_emmc {
|
||||
regulator-name = "soc_vdd18_emmc";
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
soc_dovdd18_scan_reg: soc_dovdd18_scan {
|
||||
regulator-name = "soc_dovdd18_scan";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
soc_dvdd12_scan_reg: soc_dvdd12_scan {
|
||||
regulator-name = "soc_dvdd12_scan";
|
||||
regulator-min-microvolt = <900000>;
|
||||
regulator-max-microvolt = <3600000>;
|
||||
};
|
||||
|
||||
soc_avdd28_scan_en_reg: soc_avdd28_scan_en {
|
||||
regulator-name = "soc_avdd28_scan_en";
|
||||
regulator-min-microvolt = <900000>;
|
||||
regulator-max-microvolt = <3600000>;
|
||||
};
|
||||
};
|
||||
|
||||
c910_cpufreq {
|
||||
compatible = "thead,light-mpw-cpufreq";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
test: light-aon-test {
|
||||
compatible = "thead,light-aon-test";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&cmamem {
|
||||
alloc-ranges = <0 0xe4000000 0 0x14000000>; // [0xE400_0000 ~ 0xF800_0000]
|
||||
};
|
||||
|
||||
&resmem {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
ranges;
|
||||
|
||||
tee_mem: memory@1a000000 {
|
||||
reg = <0x0 0x1a000000 0 0x4000000>;
|
||||
no-map;
|
||||
};
|
||||
dsp0_mem: memory@20000000 { /**0x2000_0000~0x2040_0000 4M**/
|
||||
reg = <0x0 0x20000000 0x0 0x00280000 /* DSP FW code&data section 2.5M*/
|
||||
0x0 0x20280000 0x0 0x00001000 /* DSP communication area 4K*/
|
||||
0x0 0x20281000 0x0 0x00007000 /* Panic/log page 28K */
|
||||
0x0 0x20288000 0x0 0x00178000>; /* DSP shared memory 1.5M-32K*/
|
||||
no-map;
|
||||
};
|
||||
dsp1_mem: memory@20400000 { /**0x2040_0000~0x2080_0000 4M**/
|
||||
reg = <0x0 0x20400000 0x0 0x00280000 /* DSP FW code&data section */
|
||||
0x0 0x20680000 0x0 0x00001000 /* DSP communication area */
|
||||
0x0 0x20681000 0x0 0x00007000 /* Panic/log page*/
|
||||
0x0 0x20688000 0x0 0x00178000>; /* DSP shared memory */
|
||||
no-map;
|
||||
};
|
||||
vi_mem: framebuffer@0f800000 {
|
||||
reg = <0x0 0x0F800000 0x0 0x05400000 /* vi_mem_pool_region[0] 84 MB (default) */
|
||||
0x0 0x14C00000 0x0 0x01D00000 /* vi_mem_pool_region[1] 29 MB */
|
||||
0x0 0x16900000 0x0 0x03200000>; /* vi_mem_pool_region[2] 50 MB */
|
||||
no-map;
|
||||
};
|
||||
facelib_mem: memory@22000000 {
|
||||
reg = <0x0 0x22000000 0x0 0x10000000>;
|
||||
no-map;
|
||||
};
|
||||
};
|
||||
|
||||
&adc {
|
||||
vref-supply = <®_vref_1v8>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&i2c0 {
|
||||
clock-frequency = <400000>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&i2c1 {
|
||||
clock-frequency = <400000>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&audio_i2c0 {
|
||||
clock-frequency = <100000>;
|
||||
status = "okay";
|
||||
|
||||
es8156_audio_codec: es8156@9 {
|
||||
#sound-dai-cells = <0>;
|
||||
compatible = "everest,es8156";
|
||||
reg = <0x09>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_audio_i2s1_mclk>;
|
||||
};
|
||||
};
|
||||
|
||||
&uart0 {
|
||||
clock-frequency = <100000000>;
|
||||
};
|
||||
|
||||
&gmac0 {
|
||||
phy-mode = "rgmii-id";
|
||||
rx-clk-delay = <0x00>; /* for RGMII */
|
||||
tx-clk-delay = <0x00>; /* for RGMII */
|
||||
phy-handle = <&phy_88E1111_0>;
|
||||
status = "okay";
|
||||
|
||||
mdio0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "snps,dwmac-mdio";
|
||||
|
||||
phy_88E1111_0: ethernet-phy@0 {
|
||||
reg = <0x1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&gmac1 {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&emmc {
|
||||
max-frequency = <198000000>;
|
||||
non-removable;
|
||||
mmc-hs400-1_8v;
|
||||
io_fixed_1v8;
|
||||
is_emmc;
|
||||
no-sdio;
|
||||
no-sd;
|
||||
pull_up;
|
||||
bus-width = <8>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&sdhci0 {
|
||||
max-frequency = <198000000>;
|
||||
bus-width = <4>;
|
||||
pull_up;
|
||||
wprtn_ignore;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&sdhci1 {
|
||||
status = "okay";
|
||||
max-frequency = <198000000>;
|
||||
bus-width = <4>;
|
||||
pull_up;
|
||||
no-sd;
|
||||
no-mmc;
|
||||
non-removable;
|
||||
io_fixed_1v8;
|
||||
post-power-on-delay-ms = <50>;
|
||||
wprtn_ignore;
|
||||
cap-sd-highspeed;
|
||||
keep-power-in-suspend;
|
||||
mmc-pwrseq = <&wifi_pwrseq>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
brcmf: wifi@1 {
|
||||
compatible = "brcm,bcm4329-fmac";
|
||||
reg = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
&padctrl0_apsys { /* right-pinctrl */
|
||||
light-evb-padctrl0 {
|
||||
/*
|
||||
* Pin Configuration Node:
|
||||
* Format: <pin_id mux_node config>
|
||||
*/
|
||||
pinctrl_uart0: uart0grp {
|
||||
thead,pins = <
|
||||
FM_UART0_TXD 0x0 0x72
|
||||
FM_UART0_RXD 0x0 0x72
|
||||
>;
|
||||
};
|
||||
|
||||
pinctrl_spi0: spi0grp {
|
||||
thead,pins = <
|
||||
FM_SPI_CSN 0x3 0x20a
|
||||
FM_SPI_SCLK 0x0 0x20a
|
||||
FM_SPI_MISO 0x0 0x23a
|
||||
FM_SPI_MOSI 0x0 0x23a
|
||||
>;
|
||||
};
|
||||
|
||||
pinctrl_qspi0: qspi0grp {
|
||||
thead,pins = <
|
||||
FM_QSPI0_SCLK 0x0 0x20f
|
||||
FM_QSPI0_CSN0 0x3 0x20f
|
||||
FM_QSPI0_D0_MOSI 0x0 0x23f
|
||||
FM_QSPI0_D1_MISO 0x0 0x23f
|
||||
>;
|
||||
};
|
||||
|
||||
pinctrl_pwm: pwmgrp {
|
||||
thead,pins = <
|
||||
FM_QSPI0_D2_WP 0x1 0x208 /* pwm5 */
|
||||
FM_QSPI0_CSN1 0x1 0x208 /* pwm2 */
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&padctrl1_apsys { /* left-pinctrl */
|
||||
light-evb-padctrl1 {
|
||||
/*
|
||||
* Pin Configuration Node:
|
||||
* Format: <pin_id mux_node config>
|
||||
*/
|
||||
pinctrl_uart3: uart3grp {
|
||||
thead,pins = <
|
||||
FM_UART3_TXD 0x0 0x72
|
||||
FM_UART3_RXD 0x0 0x72
|
||||
>;
|
||||
};
|
||||
|
||||
pinctrl_uart4: uart4grp {
|
||||
thead,pins = <
|
||||
FM_UART4_TXD 0x0 0x72
|
||||
FM_UART4_RXD 0x0 0x72
|
||||
FM_UART4_CTSN 0x0 0x72
|
||||
FM_UART4_RTSN 0x0 0x72
|
||||
>;
|
||||
};
|
||||
|
||||
pinctrl_qspi1: qspi1grp {
|
||||
thead,pins = <
|
||||
FM_QSPI1_SCLK 0x0 0x20a
|
||||
FM_QSPI1_CSN0 0x3 0x20a
|
||||
FM_QSPI1_D0_MOSI 0x0 0x23a
|
||||
FM_QSPI1_D1_MISO 0x0 0x23a
|
||||
FM_QSPI1_D2_WP 0x0 0x23a
|
||||
FM_QSPI1_D3_HOLD 0x0 0x23a
|
||||
>;
|
||||
};
|
||||
|
||||
pinctrl_iso7816: iso7816grp {
|
||||
thead,pins = <
|
||||
FM_QSPI1_SCLK 0x1 0x208
|
||||
FM_QSPI1_D0_MOSI 0x1 0x238
|
||||
FM_QSPI1_D1_MISO 0x1 0x238
|
||||
FM_QSPI1_D2_WP 0x1 0x238
|
||||
FM_QSPI1_D3_HOLD 0x1 0x238
|
||||
>;
|
||||
};
|
||||
|
||||
pinctrl_wireless_power: wireless-power-group {
|
||||
thead,pins = <
|
||||
FM_GPIO0_20 0x0 0x23a
|
||||
>;
|
||||
};
|
||||
|
||||
pinctrl_wireless_host_wake: wireless-host-wake-group {
|
||||
thead,pins = <
|
||||
FM_GPIO0_21 0x0 0x21a
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&padctrl_aosys {
|
||||
light-aon-padctrl {
|
||||
/*
|
||||
* Pin Configuration Node:
|
||||
* Format: <pin_id mux_node config>
|
||||
*/
|
||||
|
||||
pinctrl_audiopa1: audiopa1_grp {
|
||||
thead,pins = <
|
||||
FM_AUDIO_PA1 0x3 0x72
|
||||
>;
|
||||
};
|
||||
|
||||
pinctrl_audiopa2: audiopa2_grp {
|
||||
thead,pins = <
|
||||
FM_AUDIO_PA2 0x0 0x72
|
||||
>;
|
||||
};
|
||||
|
||||
pinctrl_volume: volume_grp {
|
||||
thead,pins = <
|
||||
FM_CPU_JTG_TDI 0x3 0x208
|
||||
FM_CPU_JTG_TDO 0x3 0x208
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&padctrl_audiosys {
|
||||
status = "okay";
|
||||
|
||||
light-audio-padctrl {
|
||||
/*
|
||||
* Pin Configuration Node:
|
||||
* Format: <pin_id mux_node config>
|
||||
*/
|
||||
|
||||
pinctrl_audio_i2s1_mclk: audio_i2s1_mclk_grp {
|
||||
thead,pins = <
|
||||
FM_AUDIO_IO_PA13 0x0 0x20a
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&xtensa_dsp {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&xtensa_dsp0 {
|
||||
status = "okay";
|
||||
memory-region = <&dsp0_mem>;
|
||||
};
|
||||
|
||||
&xtensa_dsp1{
|
||||
status = "okay";
|
||||
memory-region = <&dsp1_mem>;
|
||||
};
|
||||
|
||||
&trng {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&eip_28 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&vdec {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&venc {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&isp_venc_shake {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&vidmem {
|
||||
status = "okay";
|
||||
memory-region = <&vi_mem>;
|
||||
};
|
||||
|
||||
&gpu {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&npu {
|
||||
vha_clk_rate = <1000000000>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&fce {
|
||||
memory-region = <&facelib_mem>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&cpus {
|
||||
c910_0: cpu@0 {
|
||||
operating-points = <
|
||||
/* kHz uV */
|
||||
300000 650000
|
||||
800000 700000
|
||||
1500000 800000
|
||||
1848000 1000000
|
||||
>;
|
||||
light,dvddm-operating-points = <
|
||||
/* kHz uV */
|
||||
300000 800000
|
||||
800000 800000
|
||||
1500000 800000
|
||||
1848000 1000000
|
||||
>;
|
||||
};
|
||||
|
||||
c910_1: cpu@1 {
|
||||
operating-points = <
|
||||
/* kHz uV */
|
||||
300000 650000
|
||||
800000 700000
|
||||
1500000 800000
|
||||
1848000 1000000
|
||||
>;
|
||||
light,dvddm-operating-points = <
|
||||
/* kHz uV */
|
||||
300000 800000
|
||||
800000 800000
|
||||
1500000 800000
|
||||
1848000 1000000
|
||||
>;
|
||||
};
|
||||
|
||||
c910_2: cpu@2 {
|
||||
operating-points = <
|
||||
/* kHz uV */
|
||||
300000 650000
|
||||
800000 700000
|
||||
1500000 800000
|
||||
1848000 1000000
|
||||
>;
|
||||
light,dvddm-operating-points = <
|
||||
/* kHz uV */
|
||||
300000 800000
|
||||
800000 800000
|
||||
1500000 800000
|
||||
1848000 1000000
|
||||
>;
|
||||
};
|
||||
|
||||
c910_3: cpu@3 {
|
||||
operating-points = <
|
||||
/* kHz uV */
|
||||
300000 650000
|
||||
800000 700000
|
||||
1500000 800000
|
||||
1848000 1000000
|
||||
>;
|
||||
light,dvddm-operating-points = <
|
||||
/* kHz uV */
|
||||
300000 800000
|
||||
800000 800000
|
||||
1500000 800000
|
||||
1848000 1000000
|
||||
>;
|
||||
};
|
||||
};
|
||||
|
||||
&dpu {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
/* DP1 --- HDMI0 */
|
||||
&dpu_enc1 {
|
||||
status = "disabled";
|
||||
ports {
|
||||
/delete-node/ port@0;
|
||||
};
|
||||
};
|
||||
|
||||
&disp1_out {
|
||||
remote-endpoint = <&hdmi_tx_in>;
|
||||
};
|
||||
|
||||
&hdmi_tx {
|
||||
status = "okay";
|
||||
|
||||
port@0 {
|
||||
/* input */
|
||||
hdmi_tx_in: endpoint {
|
||||
remote-endpoint = <&disp1_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&light_i2s {
|
||||
status = "okay";
|
||||
/delete-property/ pinctrl-names;
|
||||
/delete-property/ pinctrl-0;
|
||||
};
|
||||
|
||||
&i2s0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&i2s1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&qspi0 {
|
||||
status = "okay";
|
||||
num-cs = <1>;
|
||||
cs-gpios = <&gpio2_porta 3 0>; // GPIO_ACTIVE_HIGH: 0
|
||||
|
||||
spi_flash: spi-flash@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "jedec,spi-nor";
|
||||
reg = <0x0>;
|
||||
spi-max-frequency = <50000000>;
|
||||
spi-tx-bus-width = <1>;
|
||||
spi-rx-bus-width = <1>;
|
||||
status = "okay";
|
||||
|
||||
partitions {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
loader@0 {
|
||||
label = "loader";
|
||||
reg = <0x0 0x800000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&qspi1 {
|
||||
status = "disabled";
|
||||
};
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <dt-bindings/pinctrl/light-fm-aon-pinctrl.h>
|
||||
#include <dt-bindings/pinctrl/light-fm-audio-pinctrl.h>
|
||||
#include <dt-bindings/pinctrl/light-fm-pinctrl-def.h>
|
||||
#include <dt-bindings/pinctrl/light.h>
|
||||
#include <dt-bindings/clock/light-fm-ap-clock.h>
|
||||
#include <dt-bindings/clock/light-vpsys.h>
|
||||
#include <dt-bindings/clock/light-vosys.h>
|
||||
@@ -379,7 +380,7 @@
|
||||
};
|
||||
};
|
||||
|
||||
soc {
|
||||
soc: soc {
|
||||
compatible = "simple-bus";
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
@@ -1046,7 +1047,7 @@
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
g2d: gc620@ffecc80000 {
|
||||
/* g2d: gc620@ffecc80000 {
|
||||
compatible = "thead,c910-gc620";
|
||||
reg = <0xff 0xecc80000 0x0 0x40000>;
|
||||
interrupt-parent = <&intc>;
|
||||
@@ -1057,6 +1058,19 @@
|
||||
<&vpsys_clk_gate LIGHT_VPSYS_G2D_CCLK>;
|
||||
clock-names = "pclk", "aclk", "cclk";
|
||||
status = "okay";
|
||||
};*/
|
||||
|
||||
g2d: gpu@13040000 {
|
||||
compatible = "vivante,gc";
|
||||
reg = <0xff 0xecc80000 0x0 0x40000>;
|
||||
|
||||
clocks = <&vpsys_clk_gate LIGHT_VPSYS_G2D_PCLK>,
|
||||
<&vpsys_clk_gate LIGHT_VPSYS_G2D_ACLK>,
|
||||
<&vpsys_clk_gate LIGHT_VPSYS_G2D_CCLK>;
|
||||
clock-names = "bus", "core", "shader";
|
||||
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <101>;
|
||||
};
|
||||
|
||||
dsi0: dw-mipi-dsi0@ffef500000 {
|
||||
|
||||
71
arch/riscv/boot/dts/thead/overlays/BBORG_LOAD-00A2.dts
Normal file
71
arch/riscv/boot/dts/thead/overlays/BBORG_LOAD-00A2.dts
Normal file
@@ -0,0 +1,71 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2020 - 2022 Deepak Khatri <lorforlinux@beagleboard.org>
|
||||
* See Cape Interface Spec page for more info on Bone Buses
|
||||
* https://docs.beagleboard.org/0.0/boards/capes/cape-interface-spec.html#beaglebone-cape-interface-spec
|
||||
*
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
/plugin/;
|
||||
|
||||
/*
|
||||
* Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
|
||||
*/
|
||||
&{/chosen} {
|
||||
overlays {
|
||||
BBORG_LOAD-00A2 = __TIMESTAMP__;
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* Easy load control through sysfs (/sys/class/leds/) using gpio-leds driver
|
||||
*/
|
||||
|
||||
&bone_led_P9_42 {
|
||||
status = "okay";
|
||||
label = "load-sink1";
|
||||
default-state = "keep";
|
||||
};
|
||||
|
||||
&bone_led_P9_41 {
|
||||
status = "okay";
|
||||
label = "load-sink2";
|
||||
default-state = "keep";
|
||||
};
|
||||
|
||||
&bone_led_P9_30 {
|
||||
status = "okay";
|
||||
label = "load-sink3";
|
||||
default-state = "keep";
|
||||
};
|
||||
|
||||
&bone_led_P9_27 {
|
||||
status = "okay";
|
||||
label = "load-sink4";
|
||||
default-state = "keep";
|
||||
};
|
||||
|
||||
&bone_led_P8_12 {
|
||||
status = "okay";
|
||||
label = "load-sink5";
|
||||
default-state = "keep";
|
||||
};
|
||||
|
||||
&bone_led_P8_11 {
|
||||
status = "okay";
|
||||
label = "load-sink6";
|
||||
default-state = "keep";
|
||||
};
|
||||
|
||||
&bone_led_P8_15 {
|
||||
status = "okay";
|
||||
label = "load-sink7";
|
||||
default-state = "keep";
|
||||
};
|
||||
|
||||
&bone_led_P8_17 {
|
||||
status = "okay";
|
||||
label = "load-sink8";
|
||||
default-state = "keep";
|
||||
};
|
||||
58
arch/riscv/boot/dts/thead/overlays/BBORG_RELAY-00A2.dts
Normal file
58
arch/riscv/boot/dts/thead/overlays/BBORG_RELAY-00A2.dts
Normal file
@@ -0,0 +1,58 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2015 Robert Nelson <robertcnelson@gmail.com>
|
||||
* Copyright (C) 2019 Amilcar Lucas <amilcar.lucas@iav.de>
|
||||
* Copyright (C) 2020 - 2023 Deepak Khatri <lorforlinux@beagleboard.org>
|
||||
*
|
||||
* See Cape Interface Spec page for more info on Bone Buses
|
||||
* https://docs.beagleboard.org/0.0/boards/capes/cape-interface-spec.html#beaglebone-cape-interface-spec
|
||||
*
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
/plugin/;
|
||||
|
||||
/*
|
||||
* Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
|
||||
*/
|
||||
&{/chosen} {
|
||||
overlays {
|
||||
BBORG_RELAY-00A2.kernel = __TIMESTAMP__;
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* Easy load control through sysfs (/sys/class/leds/) using gpio-leds driver
|
||||
*/
|
||||
|
||||
// relay1
|
||||
&bone_led_P9_41 {
|
||||
status = "okay";
|
||||
// access: sys/class/leds/relay1
|
||||
label = "relay1";
|
||||
default-state = "keep";
|
||||
};
|
||||
|
||||
// relay2
|
||||
&bone_led_P9_42 {
|
||||
status = "okay";
|
||||
// access: sys/class/leds/relay2
|
||||
label = "relay2";
|
||||
default-state = "keep";
|
||||
};
|
||||
|
||||
// realy3
|
||||
&bone_led_P9_30 {
|
||||
status = "okay";
|
||||
// access: sys/class/leds/relay3
|
||||
label = "relay3";
|
||||
default-state = "keep";
|
||||
};
|
||||
|
||||
// realy4
|
||||
&bone_led_P9_27 {
|
||||
status = "okay";
|
||||
// access: sys/class/leds/relay4
|
||||
label = "relay4";
|
||||
default-state = "keep";
|
||||
};
|
||||
32
arch/riscv/boot/dts/thead/overlays/BONE-LED_P8_03.dts
Normal file
32
arch/riscv/boot/dts/thead/overlays/BONE-LED_P8_03.dts
Normal file
@@ -0,0 +1,32 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2020 - 2022 Deepak Khatri <lorforlinux@beagleboard.org>
|
||||
*
|
||||
* See Cape Interface Spec page for more info on Bone Buses
|
||||
* https://docs.beagleboard.org/0.0/boards/capes/cape-interface-spec.html#beaglebone-cape-interface-spec
|
||||
*
|
||||
* Virtual cape for LED on P8_03
|
||||
* Supports BBB, BBBWL, BBAI, and BBAI-64
|
||||
*
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
/plugin/;
|
||||
|
||||
&{/chosen} {
|
||||
overlays {
|
||||
BONE-LED_P8_03 = __TIMESTAMP__;
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* Easy LED control through sysfs (/sys/class/leds/) using gpio-leds driver
|
||||
*/
|
||||
|
||||
&bone_led_P8_03 {
|
||||
status = "okay";
|
||||
// access: sys/class/leds/led_P8_03
|
||||
label = "led_P8_03";
|
||||
linux,default-trigger = "heartbeat";
|
||||
default-state = "on";
|
||||
};
|
||||
32
arch/riscv/boot/dts/thead/overlays/BONE-LED_P9_11.dts
Normal file
32
arch/riscv/boot/dts/thead/overlays/BONE-LED_P9_11.dts
Normal file
@@ -0,0 +1,32 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2020 - 2022 Deepak Khatri <lorforlinux@beagleboard.org>
|
||||
*
|
||||
* See Cape Interface Spec page for more info on Bone Buses
|
||||
* https://docs.beagleboard.org/0.0/boards/capes/cape-interface-spec.html#beaglebone-cape-interface-spec
|
||||
*
|
||||
* Virtual cape for LED on P9_11
|
||||
* Supports BBB, BBBWL, BBAI, and BBAI-64
|
||||
*
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
/plugin/;
|
||||
|
||||
&{/chosen} {
|
||||
overlays {
|
||||
BONE-LED_P9_11 = __TIMESTAMP__;
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* Easy LED control through sysfs (/sys/class/leds/) using gpio-leds driver
|
||||
*/
|
||||
|
||||
&bone_led_P9_11 {
|
||||
status = "okay";
|
||||
// access: sys/class/leds/led_P9_11
|
||||
label = "led_P9_11";
|
||||
linux,default-trigger = "heartbeat";
|
||||
default-state = "on";
|
||||
};
|
||||
30
arch/riscv/boot/dts/thead/overlays/BVA-MIKROBUS-0.dts
Normal file
30
arch/riscv/boot/dts/thead/overlays/BVA-MIKROBUS-0.dts
Normal file
@@ -0,0 +1,30 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2023 BeagleBoard.org - https://beagleboard.org/
|
||||
* Copyright (C) 2023 Deepak Khatri <lorforlinux@beagleboard.org>
|
||||
*
|
||||
* See Cape Interface Spec page for more info on Bone Buses
|
||||
* https://docs.beagleboard.org/0.0/boards/capes/cape-interface-spec.html
|
||||
*
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
/plugin/;
|
||||
|
||||
/*
|
||||
* Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
|
||||
*/
|
||||
|
||||
&{/chosen} {
|
||||
overlays {
|
||||
BBORG_LOAD-00A2 = __TIMESTAMP__;
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* Enable mikroBus port
|
||||
*/
|
||||
|
||||
&bone_mikrobus0 {
|
||||
status = "okay";
|
||||
};
|
||||
14
arch/riscv/boot/dts/thead/overlays/Makefile
Normal file
14
arch/riscv/boot/dts/thead/overlays/Makefile
Normal file
@@ -0,0 +1,14 @@
|
||||
# Overlays for the CONFIG_SOC_THEAD platform
|
||||
|
||||
dtbo-$(CONFIG_SOC_THEAD) += \
|
||||
BBORG_LOAD-00A2.dtbo \
|
||||
BBORG_RELAY-00A2.dtbo \
|
||||
BONE-LED_P8_03.dtbo \
|
||||
BONE-LED_P9_11.dtbo \
|
||||
BVA-MIKROBUS-0.dtbo
|
||||
|
||||
targets += dtbs dtbs_install
|
||||
targets += $(dtbo-y)
|
||||
|
||||
always-y := $(dtbo-y)
|
||||
clean-files := *.dtbo
|
||||
6068
arch/riscv/configs/beaglev_defconfig
Normal file
6068
arch/riscv/configs/beaglev_defconfig
Normal file
File diff suppressed because it is too large
Load Diff
1104
arch/riscv/configs/revyos_beaglev_defconfig
Normal file
1104
arch/riscv/configs/revyos_beaglev_defconfig
Normal file
File diff suppressed because it is too large
Load Diff
@@ -73,32 +73,44 @@ CONFIG_IP_PNP_BOOTP=y
|
||||
CONFIG_IP_PNP_RARP=y
|
||||
CONFIG_NET_IPVTI=y
|
||||
CONFIG_INET_ESP=y
|
||||
CONFIG_TCP_CONG_ADVANCED=y
|
||||
CONFIG_TCP_CONG_BBR=m
|
||||
CONFIG_NETFILTER=y
|
||||
CONFIG_BRIDGE_NETFILTER=y
|
||||
CONFIG_NF_CONNTRACK=y
|
||||
CONFIG_NF_CONNTRACK_FTP=y
|
||||
CONFIG_NF_CONNTRACK_TFTP=y
|
||||
CONFIG_NF_NAT=y
|
||||
CONFIG_NETFILTER_XT_CONNMARK=y
|
||||
CONFIG_NETFILTER_XT_NAT=y
|
||||
CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
|
||||
CONFIG_NETFILTER_XT_TARGET_REDIRECT=y
|
||||
CONFIG_NETFILTER_XT_TARGET_MASQUERADE=y
|
||||
CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y
|
||||
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
|
||||
CONFIG_NETFILTER_XT_MATCH_IPVS=y
|
||||
CONFIG_NETFILTER_XT_MATCH_MARK=y
|
||||
CONFIG_TCP_CONG_ADVANCED=y
|
||||
CONFIG_TCP_CONG_CUBIC=y
|
||||
CONFIG_TCP_CONG_WESTWOOD=m
|
||||
CONFIG_TCP_CONG_BBR=m
|
||||
CONFIG_IP_VS=y
|
||||
CONFIG_IP_VS_PROTO_TCP=y
|
||||
CONFIG_IP_VS_PROTO_UDP=y
|
||||
CONFIG_IP_VS_RR=y
|
||||
CONFIG_IP_VS_NFCT=y
|
||||
CONFIG_NF_LOG_ARP=m
|
||||
CONFIG_NF_LOG_IPV4=m
|
||||
CONFIG_IP_NF_IPTABLES=y
|
||||
CONFIG_IP_NF_FILTER=y
|
||||
CONFIG_IP_NF_NAT=y
|
||||
CONFIG_IP_NF_TARGET_MASQUERADE=y
|
||||
CONFIG_IP_NF_TARGET_REDIRECT=y
|
||||
CONFIG_IP6_NF_IPTABLES=y
|
||||
CONFIG_IP6_NF_NAT=y
|
||||
CONFIG_IP_NF_TARGET_REJECT=m
|
||||
CONFIG_IP_NF_NAT=m
|
||||
CONFIG_IP_NF_TARGET_MASQUERADE=m
|
||||
CONFIG_IP_NF_TARGET_REDIRECT=m
|
||||
CONFIG_IP_NF_MANGLE=m
|
||||
CONFIG_NF_LOG_IPV6=m
|
||||
CONFIG_IP6_NF_IPTABLES=m
|
||||
CONFIG_IP6_NF_MATCH_IPV6HEADER=m
|
||||
CONFIG_IP6_NF_FILTER=m
|
||||
CONFIG_IP6_NF_TARGET_REJECT=m
|
||||
CONFIG_IP6_NF_MANGLE=m
|
||||
CONFIG_IP6_NF_NAT=m
|
||||
CONFIG_BRIDGE=y
|
||||
CONFIG_BRIDGE_VLAN_FILTERING=y
|
||||
CONFIG_VLAN_8021Q=y
|
||||
@@ -160,12 +172,17 @@ CONFIG_USB_USBNET=m
|
||||
# CONFIG_USB_NET_AX88179_178A is not set
|
||||
# CONFIG_USB_NET_NET1080 is not set
|
||||
CONFIG_RTL8723DS=y
|
||||
CONFIG_AIC_WLAN_SUPPORT=y
|
||||
CONFIG_AIC_FW_PATH="/lib/firmware/aic8800"
|
||||
CONFIG_AIC8800_WLAN_SUPPORT=m
|
||||
CONFIG_AIC8800_BTLPM_SUPPORT=m
|
||||
CONFIG_INPUT_MOUSEDEV=y
|
||||
CONFIG_INPUT_EVDEV=y
|
||||
CONFIG_KEYBOARD_GPIO=y
|
||||
# CONFIG_INPUT_MOUSE is not set
|
||||
CONFIG_INPUT_TOUCHSCREEN=y
|
||||
CONFIG_TOUCHSCREEN_GOODIX=y
|
||||
CONFIG_TOUCHSCREEN_GT9XX=y
|
||||
CONFIG_INPUT_MISC=y
|
||||
CONFIG_INPUT_UINPUT=y
|
||||
CONFIG_SERIAL_8250=y
|
||||
@@ -258,6 +275,7 @@ CONFIG_DRM_PANEL_SIMPLE=y
|
||||
CONFIG_DRM_PANEL_ILITEK_ILI9881C=y
|
||||
CONFIG_DRM_PANEL_ILI9881D=y
|
||||
CONFIG_DRM_PANEL_HX8394=y
|
||||
CONFIG_DRM_PANEL_JADARD_JD9365DA_H3=y
|
||||
CONFIG_DRM_VERISILICON=y
|
||||
CONFIG_DRM_POWERVR_ROGUE=m
|
||||
CONFIG_BACKLIGHT_CLASS_DEVICE=y
|
||||
@@ -383,8 +401,8 @@ CONFIG_HWSPINLOCK_LIGHT_TEST=m
|
||||
CONFIG_MAILBOX=y
|
||||
CONFIG_RPMSG=y
|
||||
CONFIG_RPMSG_CHAR=y
|
||||
CONFIG_RPMSG_VIRTIO=y
|
||||
CONFIG_RPMSG_THEAD_LIGHT=y
|
||||
CONFIG_RPMSG_VIRTIO=y
|
||||
CONFIG_EXTCON=y
|
||||
CONFIG_IIO=y
|
||||
CONFIG_IIO_SW_DEVICE=y
|
||||
@@ -394,7 +412,8 @@ CONFIG_NVMEM_THEAD_LIGHT_EFUSE=y
|
||||
CONFIG_TEE=y
|
||||
CONFIG_OPTEE=y
|
||||
CONFIG_OPTEE_BENCHMARK=y
|
||||
CONFIG_LIGHT_GPU_VIV=m
|
||||
# CONFIG_LIGHT_GPU_VIV is not set
|
||||
CONFIG_DRM_ETNAVIV=m
|
||||
# CONFIG_LIGHT_NET is not set
|
||||
CONFIG_EXT4_FS=y
|
||||
CONFIG_EXT4_FS_POSIX_ACL=y
|
||||
|
||||
@@ -396,4 +396,22 @@ static inline ulong __xchg16_relaxed(ulong new, void *ptr)
|
||||
cmpxchg_relaxed((ptr), (o), (n)); \
|
||||
})
|
||||
|
||||
#define cmpxchg64_relaxed(ptr, o, n) \
|
||||
({ \
|
||||
BUILD_BUG_ON(sizeof(*(ptr)) != 8); \
|
||||
cmpxchg_relaxed((ptr), (o), (n)); \
|
||||
})
|
||||
|
||||
#define cmpxchg64_acquire(ptr, o, n) \
|
||||
({ \
|
||||
BUILD_BUG_ON(sizeof(*(ptr)) != 8); \
|
||||
cmpxchg_acquire((ptr), (o), (n)); \
|
||||
})
|
||||
|
||||
#define cmpxchg64_release(ptr, o, n) \
|
||||
({ \
|
||||
BUILD_BUG_ON(sizeof(*(ptr)) != 8); \
|
||||
cmpxchg_release((ptr), (o), (n)); \
|
||||
})
|
||||
|
||||
#endif /* _ASM_RISCV_CMPXCHG_H */
|
||||
|
||||
@@ -115,14 +115,6 @@ config BT_HCIUART_H4
|
||||
|
||||
Say Y here to compile support for HCI UART (H4) protocol.
|
||||
|
||||
config BT_HCIUART_RTL3WIRE
|
||||
bool "Realtek Three-wire UART (H5) protocol support"
|
||||
depends on BT_HCIUART
|
||||
help
|
||||
Realtek Three-wire UART (H5) transport layer makes it possible
|
||||
to use Realtek Bluetooth controller with Three-wire UART.
|
||||
Say Y here to compile support for Realtek Three-wire UART.
|
||||
|
||||
config BT_HCIUART_NOKIA
|
||||
tristate "UART Nokia H4+ protocol support"
|
||||
depends on BT_HCIUART
|
||||
|
||||
@@ -45,6 +45,4 @@ hci_uart-$(CONFIG_BT_HCIUART_BCM) += hci_bcm.o
|
||||
hci_uart-$(CONFIG_BT_HCIUART_QCA) += hci_qca.o
|
||||
hci_uart-$(CONFIG_BT_HCIUART_AG6XX) += hci_ag6xx.o
|
||||
hci_uart-$(CONFIG_BT_HCIUART_MRVL) += hci_mrvl.o
|
||||
hci_uart-y += rtk_coex.o
|
||||
hci_uart-$(CONFIG_BT_HCIUART_RTL3WIRE) += hci_rtk_h5.o
|
||||
hci_uart-objs := $(hci_uart-y)
|
||||
|
||||
@@ -654,7 +654,6 @@ static const struct h4_recv_pkt bcm_recv_pkts[] = {
|
||||
{ H4_RECV_ACL, .recv = hci_recv_frame },
|
||||
{ H4_RECV_SCO, .recv = hci_recv_frame },
|
||||
{ H4_RECV_EVENT, .recv = hci_recv_frame },
|
||||
{ H4_RECV_ISO, .recv = hci_recv_frame },
|
||||
{ BCM_RECV_LM_DIAG, .recv = hci_recv_diag },
|
||||
{ BCM_RECV_NULL, .recv = hci_recv_diag },
|
||||
{ BCM_RECV_TYPE49, .recv = hci_recv_diag },
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
*
|
||||
* Bluetooth HCI UART driver
|
||||
@@ -5,25 +6,10 @@
|
||||
* Copyright (C) 2000-2001 Qualcomm Incorporated
|
||||
* Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
|
||||
* Copyright (C) 2004-2005 Marcel Holtmann <marcel@holtmann.org>
|
||||
*
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
@@ -31,6 +17,7 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/poll.h>
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/errno.h>
|
||||
@@ -38,32 +25,18 @@
|
||||
#include <linux/signal.h>
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
#include <net/bluetooth/hci_core.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#include "hci_uart.h"
|
||||
|
||||
#ifdef BTCOEX
|
||||
#include "rtk_coex.h"
|
||||
#endif
|
||||
|
||||
//#define VERSION "1.2"
|
||||
|
||||
struct h4_struct {
|
||||
unsigned long rx_state;
|
||||
unsigned long rx_count;
|
||||
struct sk_buff *rx_skb;
|
||||
struct sk_buff_head txq;
|
||||
};
|
||||
|
||||
/* H4 receiver States */
|
||||
#define H4_W4_PACKET_TYPE 0
|
||||
#define H4_W4_EVENT_HDR 1
|
||||
#define H4_W4_ACL_HDR 2
|
||||
#define H4_W4_SCO_HDR 3
|
||||
#define H4_W4_DATA 4
|
||||
|
||||
/* Initialize protocol */
|
||||
static int h4_open(struct hci_uart *hu)
|
||||
{
|
||||
@@ -71,7 +44,7 @@ static int h4_open(struct hci_uart *hu)
|
||||
|
||||
BT_DBG("hu %p", hu);
|
||||
|
||||
h4 = kzalloc(sizeof(*h4), GFP_ATOMIC);
|
||||
h4 = kzalloc(sizeof(*h4), GFP_KERNEL);
|
||||
if (!h4)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -98,8 +71,6 @@ static int h4_close(struct hci_uart *hu)
|
||||
{
|
||||
struct h4_struct *h4 = hu->priv;
|
||||
|
||||
hu->priv = NULL;
|
||||
|
||||
BT_DBG("hu %p", hu);
|
||||
|
||||
skb_queue_purge(&h4->txq);
|
||||
@@ -112,7 +83,7 @@ static int h4_close(struct hci_uart *hu)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Enqueue frame for transmittion (padding, crc, etc) */
|
||||
/* Enqueue frame for transmission (padding, crc, etc) */
|
||||
static int h4_enqueue(struct hci_uart *hu, struct sk_buff *skb)
|
||||
{
|
||||
struct h4_struct *h4 = hu->priv;
|
||||
@@ -120,174 +91,34 @@ static int h4_enqueue(struct hci_uart *hu, struct sk_buff *skb)
|
||||
BT_DBG("hu %p skb %p", hu, skb);
|
||||
|
||||
/* Prepend skb with frame type */
|
||||
memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
|
||||
memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1);
|
||||
skb_queue_tail(&h4->txq, skb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if HCI_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
|
||||
static inline int h4_check_data_len(struct h4_struct *h4, int len)
|
||||
#else
|
||||
static inline int h4_check_data_len(struct hci_dev *hdev, struct h4_struct *h4, int len)
|
||||
#endif
|
||||
{
|
||||
register int room = skb_tailroom(h4->rx_skb);
|
||||
|
||||
BT_DBG("len %d room %d", len, room);
|
||||
|
||||
if (!len) {
|
||||
#if HCI_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
|
||||
hci_recv_frame(h4->rx_skb);
|
||||
#else
|
||||
hci_recv_frame(hdev, h4->rx_skb);
|
||||
#endif
|
||||
} else if (len > room) {
|
||||
BT_ERR("Data length is too large");
|
||||
kfree_skb(h4->rx_skb);
|
||||
} else {
|
||||
h4->rx_state = H4_W4_DATA;
|
||||
h4->rx_count = len;
|
||||
return len;
|
||||
}
|
||||
|
||||
h4->rx_state = H4_W4_PACKET_TYPE;
|
||||
h4->rx_skb = NULL;
|
||||
h4->rx_count = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
static const struct h4_recv_pkt h4_recv_pkts[] = {
|
||||
{ H4_RECV_ACL, .recv = hci_recv_frame },
|
||||
{ H4_RECV_SCO, .recv = hci_recv_frame },
|
||||
{ H4_RECV_EVENT, .recv = hci_recv_frame },
|
||||
{ H4_RECV_ISO, .recv = hci_recv_frame },
|
||||
};
|
||||
|
||||
/* Recv data */
|
||||
static int h4_recv(struct hci_uart *hu, void *data, int count)
|
||||
static int h4_recv(struct hci_uart *hu, const void *data, int count)
|
||||
{
|
||||
struct h4_struct *h4 = hu->priv;
|
||||
register char *ptr;
|
||||
struct hci_event_hdr *eh;
|
||||
struct hci_acl_hdr *ah;
|
||||
struct hci_sco_hdr *sh;
|
||||
register int len, type, dlen;
|
||||
|
||||
BT_DBG("hu %p count %d rx_state %ld rx_count %ld",
|
||||
hu, count, h4->rx_state, h4->rx_count);
|
||||
if (!test_bit(HCI_UART_REGISTERED, &hu->flags))
|
||||
return -EUNATCH;
|
||||
|
||||
ptr = data;
|
||||
while (count) {
|
||||
if (h4->rx_count) {
|
||||
len = min_t(unsigned int, h4->rx_count, count);
|
||||
memcpy(skb_put(h4->rx_skb, len), ptr, len);
|
||||
h4->rx_count -= len; count -= len; ptr += len;
|
||||
|
||||
if (h4->rx_count)
|
||||
continue;
|
||||
|
||||
switch (h4->rx_state) {
|
||||
case H4_W4_DATA:
|
||||
BT_DBG("Complete data");
|
||||
#ifdef BTCOEX
|
||||
if(bt_cb(h4->rx_skb)->pkt_type == HCI_EVENT_PKT)
|
||||
rtk_btcoex_parse_event(
|
||||
h4->rx_skb->data,
|
||||
h4->rx_skb->len);
|
||||
|
||||
if(bt_cb(h4->rx_skb)->pkt_type == HCI_ACLDATA_PKT)
|
||||
rtk_btcoex_parse_l2cap_data_rx(
|
||||
h4->rx_skb->data,
|
||||
h4->rx_skb->len);
|
||||
#endif
|
||||
|
||||
#if HCI_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
|
||||
hci_recv_frame(h4->rx_skb);
|
||||
#else
|
||||
hci_recv_frame(hu->hdev, h4->rx_skb);
|
||||
#endif
|
||||
|
||||
h4->rx_state = H4_W4_PACKET_TYPE;
|
||||
h4->rx_skb = NULL;
|
||||
continue;
|
||||
|
||||
case H4_W4_EVENT_HDR:
|
||||
eh = hci_event_hdr(h4->rx_skb);
|
||||
|
||||
BT_DBG("Event header: evt 0x%2.2x plen %d", eh->evt, eh->plen);
|
||||
|
||||
#if HCI_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
|
||||
h4_check_data_len(h4, eh->plen);
|
||||
#else
|
||||
h4_check_data_len(hu->hdev, h4, eh->plen);
|
||||
#endif
|
||||
continue;
|
||||
|
||||
case H4_W4_ACL_HDR:
|
||||
ah = hci_acl_hdr(h4->rx_skb);
|
||||
dlen = __le16_to_cpu(ah->dlen);
|
||||
|
||||
BT_DBG("ACL header: dlen %d", dlen);
|
||||
|
||||
#if HCI_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
|
||||
h4_check_data_len(h4, dlen);
|
||||
#else
|
||||
h4_check_data_len(hu->hdev, h4, dlen);
|
||||
#endif
|
||||
continue;
|
||||
|
||||
case H4_W4_SCO_HDR:
|
||||
sh = hci_sco_hdr(h4->rx_skb);
|
||||
|
||||
BT_DBG("SCO header: dlen %d", sh->dlen);
|
||||
|
||||
#if HCI_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
|
||||
h4_check_data_len(h4, sh->dlen);
|
||||
#else
|
||||
h4_check_data_len(hu->hdev, h4, sh->dlen);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* H4_W4_PACKET_TYPE */
|
||||
switch (*ptr) {
|
||||
case HCI_EVENT_PKT:
|
||||
BT_DBG("Event packet");
|
||||
h4->rx_state = H4_W4_EVENT_HDR;
|
||||
h4->rx_count = HCI_EVENT_HDR_SIZE;
|
||||
type = HCI_EVENT_PKT;
|
||||
break;
|
||||
|
||||
case HCI_ACLDATA_PKT:
|
||||
BT_DBG("ACL packet");
|
||||
h4->rx_state = H4_W4_ACL_HDR;
|
||||
h4->rx_count = HCI_ACL_HDR_SIZE;
|
||||
type = HCI_ACLDATA_PKT;
|
||||
break;
|
||||
|
||||
case HCI_SCODATA_PKT:
|
||||
BT_DBG("SCO packet");
|
||||
h4->rx_state = H4_W4_SCO_HDR;
|
||||
h4->rx_count = HCI_SCO_HDR_SIZE;
|
||||
type = HCI_SCODATA_PKT;
|
||||
break;
|
||||
|
||||
default:
|
||||
BT_ERR("Unknown HCI packet type %2.2x", (__u8)*ptr);
|
||||
hu->hdev->stat.err_rx++;
|
||||
ptr++; count--;
|
||||
continue;
|
||||
};
|
||||
|
||||
ptr++; count--;
|
||||
|
||||
/* Allocate packet */
|
||||
h4->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
|
||||
if (!h4->rx_skb) {
|
||||
BT_ERR("Can't allocate mem for new packet");
|
||||
h4->rx_state = H4_W4_PACKET_TYPE;
|
||||
h4->rx_count = 0;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
h4->rx_skb->dev = (void *) hu->hdev;
|
||||
bt_cb(h4->rx_skb)->pkt_type = type;
|
||||
h4->rx_skb = h4_recv_buf(hu->hdev, h4->rx_skb, data, count,
|
||||
h4_recv_pkts, ARRAY_SIZE(h4_recv_pkts));
|
||||
if (IS_ERR(h4->rx_skb)) {
|
||||
int err = PTR_ERR(h4->rx_skb);
|
||||
bt_dev_err(hu->hdev, "Frame reassembly failed (%d)", err);
|
||||
h4->rx_skb = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
return count;
|
||||
@@ -299,8 +130,9 @@ static struct sk_buff *h4_dequeue(struct hci_uart *hu)
|
||||
return skb_dequeue(&h4->txq);
|
||||
}
|
||||
|
||||
static struct hci_uart_proto h4p = {
|
||||
static const struct hci_uart_proto h4p = {
|
||||
.id = HCI_UART_H4,
|
||||
.name = "H4",
|
||||
.open = h4_open,
|
||||
.close = h4_close,
|
||||
.recv = h4_recv,
|
||||
@@ -311,17 +143,132 @@ static struct hci_uart_proto h4p = {
|
||||
|
||||
int __init h4_init(void)
|
||||
{
|
||||
int err = hci_uart_register_proto(&h4p);
|
||||
|
||||
if (!err)
|
||||
BT_INFO("HCI H4 protocol initialized");
|
||||
else
|
||||
BT_ERR("HCI H4 protocol registration failed");
|
||||
|
||||
return err;
|
||||
return hci_uart_register_proto(&h4p);
|
||||
}
|
||||
|
||||
int __exit h4_deinit(void)
|
||||
{
|
||||
return hci_uart_unregister_proto(&h4p);
|
||||
}
|
||||
|
||||
struct sk_buff *h4_recv_buf(struct hci_dev *hdev, struct sk_buff *skb,
|
||||
const unsigned char *buffer, int count,
|
||||
const struct h4_recv_pkt *pkts, int pkts_count)
|
||||
{
|
||||
struct hci_uart *hu = hci_get_drvdata(hdev);
|
||||
u8 alignment = hu->alignment ? hu->alignment : 1;
|
||||
|
||||
/* Check for error from previous call */
|
||||
if (IS_ERR(skb))
|
||||
skb = NULL;
|
||||
|
||||
while (count) {
|
||||
int i, len;
|
||||
|
||||
/* remove padding bytes from buffer */
|
||||
for (; hu->padding && count > 0; hu->padding--) {
|
||||
count--;
|
||||
buffer++;
|
||||
}
|
||||
if (!count)
|
||||
break;
|
||||
|
||||
if (!skb) {
|
||||
for (i = 0; i < pkts_count; i++) {
|
||||
if (buffer[0] != (&pkts[i])->type)
|
||||
continue;
|
||||
|
||||
skb = bt_skb_alloc((&pkts[i])->maxlen,
|
||||
GFP_ATOMIC);
|
||||
if (!skb)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
hci_skb_pkt_type(skb) = (&pkts[i])->type;
|
||||
hci_skb_expect(skb) = (&pkts[i])->hlen;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check for invalid packet type */
|
||||
if (!skb)
|
||||
return ERR_PTR(-EILSEQ);
|
||||
|
||||
count -= 1;
|
||||
buffer += 1;
|
||||
}
|
||||
|
||||
len = min_t(uint, hci_skb_expect(skb) - skb->len, count);
|
||||
skb_put_data(skb, buffer, len);
|
||||
|
||||
count -= len;
|
||||
buffer += len;
|
||||
|
||||
/* Check for partial packet */
|
||||
if (skb->len < hci_skb_expect(skb))
|
||||
continue;
|
||||
|
||||
for (i = 0; i < pkts_count; i++) {
|
||||
if (hci_skb_pkt_type(skb) == (&pkts[i])->type)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i >= pkts_count) {
|
||||
kfree_skb(skb);
|
||||
return ERR_PTR(-EILSEQ);
|
||||
}
|
||||
|
||||
if (skb->len == (&pkts[i])->hlen) {
|
||||
u16 dlen;
|
||||
|
||||
switch ((&pkts[i])->lsize) {
|
||||
case 0:
|
||||
/* No variable data length */
|
||||
dlen = 0;
|
||||
break;
|
||||
case 1:
|
||||
/* Single octet variable length */
|
||||
dlen = skb->data[(&pkts[i])->loff];
|
||||
hci_skb_expect(skb) += dlen;
|
||||
|
||||
if (skb_tailroom(skb) < dlen) {
|
||||
kfree_skb(skb);
|
||||
return ERR_PTR(-EMSGSIZE);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
/* Double octet variable length */
|
||||
dlen = get_unaligned_le16(skb->data +
|
||||
(&pkts[i])->loff);
|
||||
hci_skb_expect(skb) += dlen;
|
||||
|
||||
if (skb_tailroom(skb) < dlen) {
|
||||
kfree_skb(skb);
|
||||
return ERR_PTR(-EMSGSIZE);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* Unsupported variable length */
|
||||
kfree_skb(skb);
|
||||
return ERR_PTR(-EILSEQ);
|
||||
}
|
||||
|
||||
if (!dlen) {
|
||||
hu->padding = (skb->len - 1) % alignment;
|
||||
hu->padding = (alignment - hu->padding) % alignment;
|
||||
|
||||
/* No more data, complete frame */
|
||||
(&pkts[i])->recv(hdev, skb);
|
||||
skb = NULL;
|
||||
}
|
||||
} else {
|
||||
hu->padding = (skb->len - 1) % alignment;
|
||||
hu->padding = (alignment - hu->padding) % alignment;
|
||||
|
||||
/* Complete frame */
|
||||
(&pkts[i])->recv(hdev, skb);
|
||||
skb = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return skb;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(h4_recv_buf);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,908 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Bluetooth HCI UART driver
|
||||
*
|
||||
* Copyright (C) 2011-2014 wifi_fae<wifi_fae@realtek.com.tw>
|
||||
*
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/fcntl.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/bitrev.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
#include <net/bluetooth/hci_core.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#include "hci_uart.h"
|
||||
|
||||
#ifdef BTCOEX
|
||||
#include "rtk_coex.h"
|
||||
#endif
|
||||
|
||||
//#define VERSION "1.0"
|
||||
|
||||
static int txcrc = 1;
|
||||
//static int hciextn = 1;
|
||||
|
||||
#define H5_TXWINSIZE 4
|
||||
#define H5_ACK_PKT 0x00
|
||||
#define H5_LE_PKT 0x0F
|
||||
#define H5_VDRSPEC_PKT 0x0E
|
||||
|
||||
struct h5_struct {
|
||||
struct sk_buff_head unack; /* Unack'ed packets queue */
|
||||
struct sk_buff_head rel; /* Reliable packets queue */
|
||||
struct sk_buff_head unrel; /* Unreliable packets queue */
|
||||
|
||||
unsigned long rx_count;
|
||||
struct sk_buff *rx_skb;
|
||||
struct delayed_work retrans_work;
|
||||
struct hci_uart *hu; /* Parent HCI UART */
|
||||
|
||||
enum {
|
||||
H5_W4_PKT_DELIMITER,
|
||||
H5_W4_PKT_START,
|
||||
H5_W4_HDR,
|
||||
H5_W4_DATA,
|
||||
H5_W4_CRC
|
||||
} rx_state;
|
||||
|
||||
enum {
|
||||
H5_ESCSTATE_NOESC,
|
||||
H5_ESCSTATE_ESC
|
||||
} rx_esc_state;
|
||||
|
||||
u16 message_crc;
|
||||
u8 use_crc;
|
||||
u8 rxack; /* Last packet sent by us that the peer ack'ed */
|
||||
|
||||
u8 rxseq_txack; /* rxseq == txack. */
|
||||
u8 txack_req; /* Do we need to send ack's to the peer? */
|
||||
/* Reliable packet sequence number - used to assign seq to each rel pkt. */
|
||||
u8 msgq_txseq;
|
||||
|
||||
/* The spin lock protects seq, ack and ack req */
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
/* ---- H5 CRC calculation ---- */
|
||||
|
||||
/* Table for calculating CRC for polynomial 0x1021, LSB processed first,
|
||||
initial value 0xffff, bits shifted in reverse order. */
|
||||
|
||||
static const u16 crc_table[] = {
|
||||
0x0000, 0x1081, 0x2102, 0x3183,
|
||||
0x4204, 0x5285, 0x6306, 0x7387,
|
||||
0x8408, 0x9489, 0xa50a, 0xb58b,
|
||||
0xc60c, 0xd68d, 0xe70e, 0xf78f
|
||||
};
|
||||
|
||||
/* Initialise the crc calculator */
|
||||
#define H5_CRC_INIT(x) x = 0xffff
|
||||
|
||||
/*
|
||||
Update crc with next data byte
|
||||
|
||||
Implementation note
|
||||
The data byte is treated as two nibbles. The crc is generated
|
||||
in reverse, i.e., bits are fed into the register from the top.
|
||||
*/
|
||||
static void h5_crc_update(u16 * crc, u8 d)
|
||||
{
|
||||
u16 reg = *crc;
|
||||
|
||||
reg = (reg >> 4) ^ crc_table[(reg ^ d) & 0x000f];
|
||||
reg = (reg >> 4) ^ crc_table[(reg ^ (d >> 4)) & 0x000f];
|
||||
|
||||
*crc = reg;
|
||||
}
|
||||
|
||||
/* ---- H5 core ---- */
|
||||
|
||||
static void h5_slip_msgdelim(struct sk_buff *skb)
|
||||
{
|
||||
const char pkt_delim = 0xc0;
|
||||
|
||||
memcpy(skb_put(skb, 1), &pkt_delim, 1);
|
||||
}
|
||||
|
||||
static void h5_slip_one_byte(struct sk_buff *skb, u8 c)
|
||||
{
|
||||
const char esc_c0[2] = { 0xdb, 0xdc };
|
||||
const char esc_db[2] = { 0xdb, 0xdd };
|
||||
const char esc_11[2] = { 0xdb, 0xde };
|
||||
const char esc_13[2] = { 0xdb, 0xdf };
|
||||
|
||||
switch (c) {
|
||||
case 0xc0:
|
||||
memcpy(skb_put(skb, 2), &esc_c0, 2);
|
||||
break;
|
||||
case 0xdb:
|
||||
memcpy(skb_put(skb, 2), &esc_db, 2);
|
||||
break;
|
||||
case 0x11:
|
||||
memcpy(skb_put(skb, 2), &esc_11, 2);
|
||||
break;
|
||||
case 0x13:
|
||||
memcpy(skb_put(skb, 2), &esc_13, 2);
|
||||
break;
|
||||
default:
|
||||
memcpy(skb_put(skb, 1), &c, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static int h5_enqueue(struct hci_uart *hu, struct sk_buff *skb)
|
||||
{
|
||||
struct h5_struct *h5 = hu->priv;
|
||||
|
||||
if (skb->len > 0xFFF) { //Pkt length must be less than 4095 bytes
|
||||
BT_ERR("Packet too long");
|
||||
kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (bt_cb(skb)->pkt_type) {
|
||||
case HCI_ACLDATA_PKT:
|
||||
case HCI_COMMAND_PKT:
|
||||
skb_queue_tail(&h5->rel, skb);
|
||||
break;
|
||||
|
||||
case HCI_SCODATA_PKT:
|
||||
skb_queue_tail(&h5->unrel, skb);
|
||||
break;
|
||||
case H5_LE_PKT:
|
||||
case H5_ACK_PKT:
|
||||
case H5_VDRSPEC_PKT:
|
||||
skb_queue_tail(&h5->unrel, skb); /* 3-wire LinkEstablishment */
|
||||
break;
|
||||
|
||||
default:
|
||||
BT_ERR("Unknown packet type");
|
||||
kfree_skb(skb);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct sk_buff *h5_prepare_pkt(struct h5_struct *h5, u8 * data,
|
||||
int len, int pkt_type)
|
||||
{
|
||||
struct sk_buff *nskb;
|
||||
u8 hdr[4], chan;
|
||||
u16 H5_CRC_INIT(h5_txmsg_crc);
|
||||
int rel, i;
|
||||
u8 tmp;
|
||||
unsigned long flags;
|
||||
|
||||
switch (pkt_type) {
|
||||
case HCI_ACLDATA_PKT:
|
||||
chan = 2; /* 3-wire ACL channel */
|
||||
rel = 1; /* reliable channel */
|
||||
break;
|
||||
case HCI_COMMAND_PKT:
|
||||
chan = 1; /* 3-wire cmd channel */
|
||||
rel = 1; /* reliable channel */
|
||||
break;
|
||||
case HCI_EVENT_PKT:
|
||||
chan = 4; /* 3-wire cmd channel */
|
||||
rel = 1; /* reliable channel */
|
||||
break;
|
||||
case HCI_SCODATA_PKT:
|
||||
chan = 3; /* 3-wire SCO channel */
|
||||
rel = 0; /* unreliable channel */
|
||||
break;
|
||||
case H5_LE_PKT:
|
||||
chan = 15; /* 3-wire LinkEstablishment channel */
|
||||
rel = 0; /* unreliable channel */
|
||||
break;
|
||||
case H5_ACK_PKT:
|
||||
chan = 0; /* 3-wire ACK channel */
|
||||
rel = 0; /* unreliable channel */
|
||||
break;
|
||||
case H5_VDRSPEC_PKT:
|
||||
chan = 14; /* 3-wire Vendor Specific channel */
|
||||
rel = 0; /* unreliable channel */
|
||||
break;
|
||||
default:
|
||||
BT_ERR("Unknown packet type");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Max len of packet: (original len +4(h5 hdr) +2(crc))*2
|
||||
(because bytes 0xc0 and 0xdb are escaped, worst case is
|
||||
when the packet is all made of 0xc0 and 0xdb :) )
|
||||
+ 2 (0xc0 delimiters at start and end). */
|
||||
|
||||
nskb = alloc_skb((len + 6) * 2 + 2, GFP_ATOMIC);
|
||||
if (!nskb)
|
||||
return NULL;
|
||||
|
||||
bt_cb(nskb)->pkt_type = pkt_type;
|
||||
|
||||
h5_slip_msgdelim(nskb);
|
||||
|
||||
spin_lock_irqsave(&h5->lock, flags);
|
||||
tmp = h5->rxseq_txack;
|
||||
hdr[0] = h5->rxseq_txack << 3;
|
||||
h5->txack_req = 0;
|
||||
spin_unlock_irqrestore(&h5->lock, flags);
|
||||
BT_DBG("We request packet no %u to card", tmp);
|
||||
|
||||
if (rel) {
|
||||
spin_lock_irqsave(&h5->lock, flags);
|
||||
tmp = h5->msgq_txseq;
|
||||
hdr[0] |= 0x80 + h5->msgq_txseq;
|
||||
h5->msgq_txseq = (h5->msgq_txseq + 1) & 0x07;
|
||||
spin_unlock_irqrestore(&h5->lock, flags);
|
||||
BT_DBG("Sending packet with seqno %u", tmp);
|
||||
}
|
||||
|
||||
if (h5->use_crc)
|
||||
hdr[0] |= 0x40;
|
||||
|
||||
hdr[1] = ((len << 4) & 0xff) | chan;
|
||||
hdr[2] = len >> 4;
|
||||
hdr[3] = ~(hdr[0] + hdr[1] + hdr[2]);
|
||||
|
||||
/* Put H5 header */
|
||||
for (i = 0; i < 4; i++) {
|
||||
h5_slip_one_byte(nskb, hdr[i]);
|
||||
|
||||
if (h5->use_crc)
|
||||
h5_crc_update(&h5_txmsg_crc, hdr[i]);
|
||||
}
|
||||
|
||||
/* Put payload */
|
||||
for (i = 0; i < len; i++) {
|
||||
h5_slip_one_byte(nskb, data[i]);
|
||||
|
||||
if (h5->use_crc)
|
||||
h5_crc_update(&h5_txmsg_crc, data[i]);
|
||||
}
|
||||
|
||||
/* Put CRC */
|
||||
if (h5->use_crc) {
|
||||
h5_txmsg_crc = bitrev16(h5_txmsg_crc);
|
||||
h5_slip_one_byte(nskb, (u8) ((h5_txmsg_crc >> 8) & 0x00ff));
|
||||
h5_slip_one_byte(nskb, (u8) (h5_txmsg_crc & 0x00ff));
|
||||
}
|
||||
|
||||
h5_slip_msgdelim(nskb);
|
||||
return nskb;
|
||||
}
|
||||
|
||||
/* This is a rewrite of pkt_avail in AH5 */
|
||||
static struct sk_buff *h5_dequeue(struct hci_uart *hu)
|
||||
{
|
||||
struct h5_struct *h5 = hu->priv;
|
||||
unsigned long flags;
|
||||
struct sk_buff *skb;
|
||||
|
||||
/* First of all, check for unreliable messages in the queue,
|
||||
since they have priority */
|
||||
|
||||
if ((skb = skb_dequeue(&h5->unrel)) != NULL) {
|
||||
struct sk_buff *nskb =
|
||||
h5_prepare_pkt(h5, skb->data, skb->len,
|
||||
bt_cb(skb)->pkt_type);
|
||||
if (nskb) {
|
||||
kfree_skb(skb);
|
||||
return nskb;
|
||||
} else {
|
||||
skb_queue_head(&h5->unrel, skb);
|
||||
BT_ERR
|
||||
("Could not dequeue pkt because alloc_skb failed");
|
||||
}
|
||||
}
|
||||
|
||||
/* Now, try to send a reliable pkt. We can only send a
|
||||
reliable packet if the number of packets sent but not yet ack'ed
|
||||
is < than the winsize */
|
||||
|
||||
spin_lock_irqsave_nested(&h5->unack.lock, flags, SINGLE_DEPTH_NESTING);
|
||||
|
||||
if (h5->unack.qlen < H5_TXWINSIZE
|
||||
&& (skb = skb_dequeue(&h5->rel)) != NULL) {
|
||||
struct sk_buff *nskb =
|
||||
h5_prepare_pkt(h5, skb->data, skb->len,
|
||||
bt_cb(skb)->pkt_type);
|
||||
if (nskb) {
|
||||
__skb_queue_tail(&h5->unack, skb);
|
||||
schedule_delayed_work(&h5->retrans_work, HZ / 4);
|
||||
spin_unlock_irqrestore(&h5->unack.lock, flags);
|
||||
return nskb;
|
||||
} else {
|
||||
skb_queue_head(&h5->rel, skb);
|
||||
BT_ERR
|
||||
("Could not dequeue pkt because alloc_skb failed");
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&h5->unack.lock, flags);
|
||||
|
||||
/* We could not send a reliable packet, either because there are
|
||||
none or because there are too many unack'ed pkts. Did we receive
|
||||
any packets we have not acknowledged yet ? */
|
||||
|
||||
if (h5->txack_req) {
|
||||
/* if so, craft an empty ACK pkt and send it on H5 unreliable
|
||||
channel 0 */
|
||||
struct sk_buff *nskb = h5_prepare_pkt(h5, NULL, 0, H5_ACK_PKT);
|
||||
return nskb;
|
||||
}
|
||||
|
||||
/* We have nothing to send */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int h5_flush(struct hci_uart *hu)
|
||||
{
|
||||
BT_DBG("hu %p", hu);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Remove ack'ed packets */
|
||||
static void h5_pkt_cull(struct h5_struct *h5)
|
||||
{
|
||||
struct sk_buff *skb, *tmp;
|
||||
unsigned long flags;
|
||||
int i, pkts_to_be_removed;
|
||||
u8 seqno;
|
||||
|
||||
spin_lock_irqsave(&h5->unack.lock, flags);
|
||||
|
||||
pkts_to_be_removed = skb_queue_len(&h5->unack);
|
||||
seqno = h5->msgq_txseq;
|
||||
|
||||
while (pkts_to_be_removed) {
|
||||
if (h5->rxack == seqno)
|
||||
break;
|
||||
pkts_to_be_removed--;
|
||||
seqno = (seqno - 1) & 0x07;
|
||||
}
|
||||
|
||||
if (h5->rxack != seqno)
|
||||
BT_ERR("Peer acked invalid packet");
|
||||
|
||||
BT_DBG("Removing %u pkts out of %u, up to seqno %u",
|
||||
pkts_to_be_removed, skb_queue_len(&h5->unack),
|
||||
(seqno - 1) & 0x07);
|
||||
|
||||
i = 0;
|
||||
skb_queue_walk_safe(&h5->unack, skb, tmp) {
|
||||
if (i >= pkts_to_be_removed)
|
||||
break;
|
||||
i++;
|
||||
|
||||
__skb_unlink(skb, &h5->unack);
|
||||
kfree_skb(skb);
|
||||
}
|
||||
|
||||
if (skb_queue_empty(&h5->unack))
|
||||
cancel_delayed_work(&h5->retrans_work);
|
||||
|
||||
spin_unlock_irqrestore(&h5->unack.lock, flags);
|
||||
|
||||
if (i != pkts_to_be_removed)
|
||||
BT_ERR("Removed only %u out of %u pkts", i, pkts_to_be_removed);
|
||||
}
|
||||
|
||||
/* Handle H5 link-establishment packets. When we
|
||||
detect a "sync" packet, symptom that the BT module has reset,
|
||||
we do nothing :) (yet) */
|
||||
#if 0
|
||||
static void h5_handle_le_pkt(struct hci_uart *hu)
|
||||
{
|
||||
struct h5_struct *h5 = hu->priv;
|
||||
u8 conf_pkt[2] = { 0x03, 0xfc };
|
||||
u8 conf_rsp_pkt[3] = { 0x04, 0x7b, 0x00 };
|
||||
u8 sync_pkt[2] = { 0x01, 0x7e };
|
||||
u8 sync_rsp_pkt[2] = { 0x02, 0x7d };
|
||||
|
||||
u8 wakeup_pkt[2] = { 0x05, 0xfa };
|
||||
u8 woken_pkt[2] = { 0x06, 0xf9 };
|
||||
u8 sleep_pkt[2] = { 0x07, 0x78 };
|
||||
|
||||
/* spot "conf" pkts and reply with a "conf rsp" pkt */
|
||||
if (h5->rx_skb->data[1] >> 4 == 2 && h5->rx_skb->data[2] == 0 &&
|
||||
!memcmp(&h5->rx_skb->data[4], conf_pkt, 2)) {
|
||||
struct sk_buff *nskb = alloc_skb(3, GFP_ATOMIC);
|
||||
|
||||
BT_DBG("Found a LE conf pkt");
|
||||
if (!nskb)
|
||||
return;
|
||||
|
||||
conf_rsp_pkt[2] |= txcrc << 0x4; //crc check enable, version no = 0. needed to be as avariable.
|
||||
memcpy(skb_put(nskb, 3), conf_rsp_pkt, 3);
|
||||
bt_cb(nskb)->pkt_type = H5_LE_PKT;
|
||||
|
||||
skb_queue_head(&h5->unrel, nskb);
|
||||
hci_uart_tx_wakeup(hu);
|
||||
}
|
||||
/* spot "conf resp" pkts */
|
||||
else if (h5->rx_skb->data[1] >> 4 == 2 && h5->rx_skb->data[2] == 0 &&
|
||||
!memcmp(&h5->rx_skb->data[4], conf_rsp_pkt, 2)) {
|
||||
BT_DBG("Found a LE conf resp pkt, device go into active state");
|
||||
txcrc = (h5->rx_skb->data[6] >> 0x4) & 0x1;
|
||||
}
|
||||
|
||||
/* Spot "sync" pkts. If we find one...disaster! */
|
||||
else if (h5->rx_skb->data[1] >> 4 == 2 && h5->rx_skb->data[2] == 0 &&
|
||||
!memcmp(&h5->rx_skb->data[4], sync_pkt, 2)) {
|
||||
BT_ERR("Found a LE sync pkt, card has reset");
|
||||
//DO Something here
|
||||
}
|
||||
/* Spot "sync resp" pkts. If we find one...disaster! */
|
||||
else if (h5->rx_skb->data[1] >> 4 == 2 && h5->rx_skb->data[2] == 0 &&
|
||||
!memcmp(&h5->rx_skb->data[4], sync_rsp_pkt, 2)) {
|
||||
BT_ERR
|
||||
("Found a LE sync resp pkt, device go into initialized state");
|
||||
// DO Something here
|
||||
}
|
||||
/* Spot "wakeup" pkts. reply woken message when in active mode */
|
||||
else if (h5->rx_skb->data[1] >> 4 == 2 && h5->rx_skb->data[2] == 0 &&
|
||||
!memcmp(&h5->rx_skb->data[4], wakeup_pkt, 2)) {
|
||||
struct sk_buff *nskb = alloc_skb(2, GFP_ATOMIC);
|
||||
|
||||
BT_ERR("Found a LE Wakeup pkt, and reply woken message");
|
||||
// DO Something here
|
||||
|
||||
memcpy(skb_put(nskb, 2), woken_pkt, 2);
|
||||
bt_cb(nskb)->pkt_type = H5_LE_PKT;
|
||||
|
||||
skb_queue_head(&h5->unrel, nskb);
|
||||
hci_uart_tx_wakeup(hu);
|
||||
}
|
||||
/* Spot "woken" pkts. receive woken message from device */
|
||||
else if (h5->rx_skb->data[1] >> 4 == 2 && h5->rx_skb->data[2] == 0 &&
|
||||
!memcmp(&h5->rx_skb->data[4], woken_pkt, 2)) {
|
||||
BT_ERR("Found a LE woken pkt from device");
|
||||
// DO Something here
|
||||
}
|
||||
/* Spot "Sleep" pkts */
|
||||
else if (h5->rx_skb->data[1] >> 4 == 2 && h5->rx_skb->data[2] == 0 &&
|
||||
!memcmp(&h5->rx_indent: Standard input:620: Error:Unmatched 'else'
|
||||
skb->data[4], sleep_pkt, 2)) {
|
||||
BT_ERR("Found a LE Sleep pkt");
|
||||
// DO Something here
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void h5_unslip_one_byte(struct h5_struct *h5, unsigned char byte)
|
||||
{
|
||||
const u8 c0 = 0xc0, db = 0xdb;
|
||||
const u8 oof1 = 0x11, oof2 = 0x13;
|
||||
|
||||
switch (h5->rx_esc_state) {
|
||||
case H5_ESCSTATE_NOESC:
|
||||
switch (byte) {
|
||||
case 0xdb:
|
||||
h5->rx_esc_state = H5_ESCSTATE_ESC;
|
||||
break;
|
||||
default:
|
||||
memcpy(skb_put(h5->rx_skb, 1), &byte, 1);
|
||||
if ((h5->rx_skb->data[0] & 0x40) != 0 &&
|
||||
h5->rx_state != H5_W4_CRC)
|
||||
h5_crc_update(&h5->message_crc, byte);
|
||||
h5->rx_count--;
|
||||
}
|
||||
break;
|
||||
|
||||
case H5_ESCSTATE_ESC:
|
||||
switch (byte) {
|
||||
case 0xdc:
|
||||
memcpy(skb_put(h5->rx_skb, 1), &c0, 1);
|
||||
if ((h5->rx_skb->data[0] & 0x40) != 0 &&
|
||||
h5->rx_state != H5_W4_CRC)
|
||||
h5_crc_update(&h5->message_crc, 0xc0);
|
||||
h5->rx_esc_state = H5_ESCSTATE_NOESC;
|
||||
h5->rx_count--;
|
||||
break;
|
||||
|
||||
case 0xdd:
|
||||
memcpy(skb_put(h5->rx_skb, 1), &db, 1);
|
||||
if ((h5->rx_skb->data[0] & 0x40) != 0 &&
|
||||
h5->rx_state != H5_W4_CRC)
|
||||
h5_crc_update(&h5->message_crc, 0xdb);
|
||||
h5->rx_esc_state = H5_ESCSTATE_NOESC;
|
||||
h5->rx_count--;
|
||||
break;
|
||||
|
||||
case 0xde:
|
||||
memcpy(skb_put(h5->rx_skb, 1), &oof1, 1);
|
||||
if ((h5->rx_skb->data[0] & 0x40) != 0
|
||||
&& h5->rx_state != H5_W4_CRC)
|
||||
h5_crc_update(&h5->message_crc, oof1);
|
||||
h5->rx_esc_state = H5_ESCSTATE_NOESC;
|
||||
h5->rx_count--;
|
||||
break;
|
||||
|
||||
case 0xdf:
|
||||
memcpy(skb_put(h5->rx_skb, 1), &oof2, 1);
|
||||
if ((h5->rx_skb->data[0] & 0x40) != 0
|
||||
&& h5->rx_state != H5_W4_CRC)
|
||||
h5_crc_update(&h5->message_crc, oof2);
|
||||
h5->rx_esc_state = H5_ESCSTATE_NOESC;
|
||||
h5->rx_count--;
|
||||
break;
|
||||
|
||||
default:
|
||||
BT_ERR("Invalid byte %02x after esc byte", byte);
|
||||
kfree_skb(h5->rx_skb);
|
||||
h5->rx_skb = NULL;
|
||||
h5->rx_state = H5_W4_PKT_DELIMITER;
|
||||
h5->rx_count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void h5_complete_rx_pkt(struct hci_uart *hu)
|
||||
{
|
||||
struct h5_struct *h5 = hu->priv;
|
||||
int pass_up;
|
||||
|
||||
if (h5->rx_skb->data[0] & 0x80) { /* reliable pkt */
|
||||
unsigned long flags;
|
||||
u8 rxseq;
|
||||
|
||||
spin_lock_irqsave(&h5->lock, flags);
|
||||
rxseq = h5->rxseq_txack;
|
||||
h5->rxseq_txack++;
|
||||
h5->rxseq_txack %= 0x8;
|
||||
h5->txack_req = 1;
|
||||
spin_unlock_irqrestore(&h5->lock, flags);
|
||||
|
||||
BT_DBG("Received seqno %u from card", rxseq);
|
||||
}
|
||||
|
||||
h5->rxack = (h5->rx_skb->data[0] >> 3) & 0x07;
|
||||
BT_DBG("Request for pkt %u from card", h5->rxack);
|
||||
|
||||
h5_pkt_cull(h5);
|
||||
|
||||
hci_uart_tx_wakeup(hu);
|
||||
|
||||
if ((h5->rx_skb->data[1] & 0x0f) == 2 && h5->rx_skb->data[0] & 0x80) {
|
||||
bt_cb(h5->rx_skb)->pkt_type = HCI_ACLDATA_PKT;
|
||||
pass_up = 1;
|
||||
} else if ((h5->rx_skb->data[1] & 0x0f) == 4 &&
|
||||
h5->rx_skb->data[0] & 0x80) {
|
||||
bt_cb(h5->rx_skb)->pkt_type = HCI_EVENT_PKT;
|
||||
pass_up = 1;
|
||||
} else if ((h5->rx_skb->data[1] & 0x0f) == 3) {
|
||||
bt_cb(h5->rx_skb)->pkt_type = HCI_SCODATA_PKT;
|
||||
pass_up = 1;
|
||||
} else if ((h5->rx_skb->data[1] & 0x0f) == 15 &&
|
||||
!(h5->rx_skb->data[0] & 0x80)) {
|
||||
//h5_handle_le_pkt(hu);//Link Establishment Pkt
|
||||
pass_up = 0;
|
||||
} else if ((h5->rx_skb->data[1] & 0x0f) == 1 &&
|
||||
h5->rx_skb->data[0] & 0x80) {
|
||||
bt_cb(h5->rx_skb)->pkt_type = HCI_COMMAND_PKT;
|
||||
pass_up = 1;
|
||||
} else if ((h5->rx_skb->data[1] & 0x0f) == 14) {
|
||||
bt_cb(h5->rx_skb)->pkt_type = H5_VDRSPEC_PKT;
|
||||
pass_up = 1;
|
||||
} else
|
||||
pass_up = 0;
|
||||
|
||||
if (!pass_up) {
|
||||
/* struct hci_event_hdr hdr; */
|
||||
u8 desc = (h5->rx_skb->data[1] & 0x0f);
|
||||
|
||||
if (desc != H5_ACK_PKT && desc != H5_LE_PKT) {
|
||||
/* if (hciextn) {
|
||||
* desc |= 0xc0;
|
||||
* skb_pull(h5->rx_skb, 4);
|
||||
* memcpy(skb_push(h5->rx_skb, 1), &desc, 1);
|
||||
|
||||
* hdr.evt = 0xff;
|
||||
* hdr.plen = h5->rx_skb->len;
|
||||
* memcpy(skb_push(h5->rx_skb, HCI_EVENT_HDR_SIZE),
|
||||
* &hdr, HCI_EVENT_HDR_SIZE);
|
||||
* bt_cb(h5->rx_skb)->pkt_type = HCI_EVENT_PKT;
|
||||
|
||||
* hci_recv_frame(h5->rx_skb);
|
||||
* } else { */
|
||||
BT_ERR("Packet for unknown channel (%u %s)",
|
||||
h5->rx_skb->data[1] & 0x0f,
|
||||
h5->rx_skb->data[0] & 0x80 ?
|
||||
"reliable" : "unreliable");
|
||||
kfree_skb(h5->rx_skb);
|
||||
/* } */
|
||||
} else
|
||||
kfree_skb(h5->rx_skb);
|
||||
} else {
|
||||
/* Pull out H5 hdr */
|
||||
skb_pull(h5->rx_skb, 4);
|
||||
|
||||
#ifdef BTCOEX
|
||||
if (bt_cb(h5->rx_skb)->pkt_type == HCI_EVENT_PKT)
|
||||
rtk_btcoex_parse_event(h5->rx_skb->data,
|
||||
h5->rx_skb->len);
|
||||
|
||||
if (bt_cb(h5->rx_skb)->pkt_type == HCI_ACLDATA_PKT)
|
||||
rtk_btcoex_parse_l2cap_data_rx(h5->rx_skb->data,
|
||||
h5->rx_skb->len);
|
||||
#endif
|
||||
|
||||
#if HCI_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
|
||||
hci_recv_frame(h5->rx_skb);
|
||||
#else
|
||||
hci_recv_frame(hu->hdev, h5->rx_skb);
|
||||
#endif
|
||||
}
|
||||
|
||||
h5->rx_state = H5_W4_PKT_DELIMITER;
|
||||
h5->rx_skb = NULL;
|
||||
}
|
||||
|
||||
static u16 bscp_get_crc(struct h5_struct *h5) {
|
||||
return get_unaligned_be16(&h5->rx_skb->
|
||||
data[h5->rx_skb->len - 2]);
|
||||
}
|
||||
|
||||
/* Recv data */
|
||||
static int h5_recv(struct hci_uart *hu, void *data, int count)
|
||||
{
|
||||
struct h5_struct *h5 = hu->priv;
|
||||
register unsigned char *ptr;
|
||||
u8 rxseq;
|
||||
unsigned long flags;
|
||||
|
||||
BT_DBG("hu %p count %d rx_state %d rx_count %ld",
|
||||
hu, count, h5->rx_state, h5->rx_count);
|
||||
|
||||
ptr = data;
|
||||
while (count) {
|
||||
if (h5->rx_count) {
|
||||
if (*ptr == 0xc0) {
|
||||
BT_ERR("Short H5 packet");
|
||||
kfree_skb(h5->rx_skb);
|
||||
h5->rx_state = H5_W4_PKT_START;
|
||||
h5->rx_count = 0;
|
||||
} else
|
||||
h5_unslip_one_byte(h5, *ptr);
|
||||
|
||||
ptr++;
|
||||
count--;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (h5->rx_state) {
|
||||
case H5_W4_HDR:
|
||||
if ((0xff & (u8) ~
|
||||
(h5->rx_skb->data[0] +
|
||||
h5->rx_skb->data[1] +
|
||||
h5->rx_skb->data[2])) != h5->rx_skb->data[3]) {
|
||||
BT_ERR("Error in H5 hdr checksum");
|
||||
kfree_skb(h5->rx_skb);
|
||||
h5->rx_state = H5_W4_PKT_DELIMITER;
|
||||
h5->rx_count = 0;
|
||||
continue;
|
||||
}
|
||||
rxseq = h5->rxseq_txack;
|
||||
if (h5->rx_skb->data[0] & 0x80 /* reliable pkt */
|
||||
&& (h5->rx_skb->data[0] & 0x07) != rxseq) {
|
||||
BT_ERR("Out-of-order packet arrived, got %u expected %u",
|
||||
h5->rx_skb->data[0] & 0x07, rxseq);
|
||||
|
||||
spin_lock_irqsave(&h5->lock, flags);
|
||||
h5->txack_req = 1;
|
||||
spin_unlock_irqrestore(&h5->lock, flags);
|
||||
hci_uart_tx_wakeup(hu);
|
||||
kfree_skb(h5->rx_skb);
|
||||
h5->rx_state = H5_W4_PKT_DELIMITER;
|
||||
h5->rx_count = 0;
|
||||
continue;
|
||||
}
|
||||
h5->rx_state = H5_W4_DATA;
|
||||
h5->rx_count = (h5->rx_skb->data[1] >> 4) + (h5->rx_skb->data[2] << 4); /* May be 0 */
|
||||
continue;
|
||||
|
||||
case H5_W4_DATA:
|
||||
if (h5->rx_skb->data[0] & 0x40) { /* pkt with crc */
|
||||
h5->rx_state = H5_W4_CRC;
|
||||
h5->rx_count = 2;
|
||||
} else
|
||||
h5_complete_rx_pkt(hu);
|
||||
continue;
|
||||
|
||||
case H5_W4_CRC:
|
||||
if (bitrev16(h5->message_crc) != bscp_get_crc(h5)) {
|
||||
BT_ERR
|
||||
("Checksum failed: computed %04x received %04x",
|
||||
bitrev16(h5->message_crc),
|
||||
bscp_get_crc(h5));
|
||||
|
||||
kfree_skb(h5->rx_skb);
|
||||
h5->rx_state = H5_W4_PKT_DELIMITER;
|
||||
h5->rx_count = 0;
|
||||
continue;
|
||||
}
|
||||
skb_trim(h5->rx_skb, h5->rx_skb->len - 2);
|
||||
h5_complete_rx_pkt(hu);
|
||||
continue;
|
||||
|
||||
case H5_W4_PKT_DELIMITER:
|
||||
switch (*ptr) {
|
||||
case 0xc0:
|
||||
h5->rx_state = H5_W4_PKT_START;
|
||||
break;
|
||||
default:
|
||||
/*BT_ERR("Ignoring byte %02x", *ptr); */
|
||||
break;
|
||||
}
|
||||
ptr++;
|
||||
count--;
|
||||
break;
|
||||
|
||||
case H5_W4_PKT_START:
|
||||
switch (*ptr) {
|
||||
case 0xc0:
|
||||
ptr++;
|
||||
count--;
|
||||
break;
|
||||
|
||||
default:
|
||||
h5->rx_state = H5_W4_HDR;
|
||||
h5->rx_count = 4;
|
||||
h5->rx_esc_state = H5_ESCSTATE_NOESC;
|
||||
H5_CRC_INIT(h5->message_crc);
|
||||
|
||||
/* Do not increment ptr or decrement count
|
||||
* Allocate packet. Max len of a H5 pkt=
|
||||
* 0xFFF (payload) +4 (header) +2 (crc) */
|
||||
|
||||
h5->rx_skb = bt_skb_alloc(0x1005, GFP_ATOMIC);
|
||||
if (!h5->rx_skb) {
|
||||
BT_ERR
|
||||
("Can't allocate mem for new packet");
|
||||
h5->rx_state = H5_W4_PKT_DELIMITER;
|
||||
h5->rx_count = 0;
|
||||
return 0;
|
||||
}
|
||||
h5->rx_skb->dev = (void *)hu->hdev;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/* Arrange to retransmit all messages in the relq. */
|
||||
static void h5_timed_event(struct work_struct *work)
|
||||
{
|
||||
struct h5_struct *h5;
|
||||
struct hci_uart *hu;
|
||||
unsigned long flags;
|
||||
unsigned long flags2;
|
||||
struct sk_buff *skb;
|
||||
|
||||
h5 = container_of(work, struct h5_struct, retrans_work.work);
|
||||
hu = h5->hu;
|
||||
|
||||
BT_INFO("hu %p retransmitting %u pkts", hu, h5->unack.qlen);
|
||||
|
||||
spin_lock_irqsave_nested(&h5->unack.lock, flags, SINGLE_DEPTH_NESTING);
|
||||
|
||||
/* Move the pkt from unack queue to the head of reliable tx queue and
|
||||
* roll back the tx seq number
|
||||
*/
|
||||
while ((skb = __skb_dequeue_tail(&h5->unack)) != NULL) {
|
||||
spin_lock_irqsave(&h5->lock, flags2);
|
||||
h5->msgq_txseq = (h5->msgq_txseq - 1) & 0x07;
|
||||
spin_unlock_irqrestore(&h5->lock, flags2);
|
||||
skb_queue_head(&h5->rel, skb);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&h5->unack.lock, flags);
|
||||
|
||||
hci_uart_tx_wakeup(hu);
|
||||
}
|
||||
|
||||
static int h5_open(struct hci_uart *hu)
|
||||
{
|
||||
struct h5_struct *h5;
|
||||
|
||||
BT_DBG("hu %p", hu);
|
||||
|
||||
BT_INFO("h5_open");
|
||||
h5 = kzalloc(sizeof(*h5), GFP_ATOMIC);
|
||||
if (!h5)
|
||||
return -ENOMEM;
|
||||
|
||||
hu->priv = h5;
|
||||
skb_queue_head_init(&h5->unack);
|
||||
skb_queue_head_init(&h5->rel);
|
||||
skb_queue_head_init(&h5->unrel);
|
||||
spin_lock_init(&h5->lock);
|
||||
|
||||
h5->hu = hu;
|
||||
INIT_DELAYED_WORK(&h5->retrans_work, (void *)h5_timed_event);
|
||||
|
||||
h5->rx_state = H5_W4_PKT_DELIMITER;
|
||||
|
||||
if (txcrc)
|
||||
h5->use_crc = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int h5_close(struct hci_uart *hu)
|
||||
{
|
||||
struct h5_struct *h5 = hu->priv;
|
||||
|
||||
BT_INFO("h5_close");
|
||||
|
||||
cancel_delayed_work_sync(&h5->retrans_work);
|
||||
|
||||
hu->priv = NULL;
|
||||
|
||||
skb_queue_purge(&h5->unack);
|
||||
skb_queue_purge(&h5->rel);
|
||||
skb_queue_purge(&h5->unrel);
|
||||
|
||||
kfree(h5);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct hci_uart_proto h5 = {
|
||||
.id = HCI_UART_3WIRE,
|
||||
.open = h5_open,
|
||||
.close = h5_close,
|
||||
.enqueue = h5_enqueue,
|
||||
.dequeue = h5_dequeue,
|
||||
.recv = h5_recv,
|
||||
.flush = h5_flush
|
||||
};
|
||||
|
||||
int h5_init(void)
|
||||
{
|
||||
int err = hci_uart_register_proto(&h5);
|
||||
|
||||
if (!err)
|
||||
BT_INFO("HCI Realtek H5 protocol initialized");
|
||||
else
|
||||
BT_ERR("HCI Realtek H5 protocol registration failed");
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int h5_deinit(void)
|
||||
{
|
||||
return hci_uart_unregister_proto(&h5);
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
*
|
||||
* Bluetooth HCI UART driver
|
||||
@@ -5,50 +6,12 @@
|
||||
* Copyright (C) 2000-2001 Qualcomm Incorporated
|
||||
* Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
|
||||
* Copyright (C) 2004-2005 Marcel Holtmann <marcel@holtmann.org>
|
||||
*
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
#include <linux/version.h>
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
#include <net/bluetooth/hci_core.h>
|
||||
|
||||
/* #define HCI_VERSION_CODE KERNEL_VERSION(3, 14, 41) */
|
||||
#define HCI_VERSION_CODE LINUX_VERSION_CODE
|
||||
|
||||
#ifndef N_HCI
|
||||
#define N_HCI 15
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_BT_HCIUART_H4
|
||||
#define CONFIG_BT_HCIUART_H4
|
||||
#endif
|
||||
|
||||
#define BTCOEX
|
||||
|
||||
/* Send host sleep notification to Controller */
|
||||
#define WOBT_NOTIFY 0 /* 1 enable; 0 disable */
|
||||
|
||||
/* Send LE whitelist only for Background scan parameters */
|
||||
#define WOBT_NOTIFY_BG_SCAN_LE_WHITELIST_ONLY (0 * WOBT_NOTIFY) /* 1 enable; 0 disable */
|
||||
|
||||
/* RTKBT Power-on Whitelist for sideband wake-up by LE Advertising from Remote.
|
||||
* Note that it's necessary to apply TV FW Patch. */
|
||||
#define RTKBT_TV_POWERON_WHITELIST (0 * WOBT_NOTIFY) /* 1 enable; 0 disable */
|
||||
|
||||
/* Ioctls */
|
||||
#define HCIUARTSETPROTO _IOW('U', 200, int)
|
||||
#define HCIUARTGETPROTO _IOR('U', 201, int)
|
||||
@@ -57,7 +20,7 @@
|
||||
#define HCIUARTGETFLAGS _IOR('U', 204, int)
|
||||
|
||||
/* UART protocols */
|
||||
#define HCI_UART_MAX_PROTO 6
|
||||
#define HCI_UART_MAX_PROTO 12
|
||||
|
||||
#define HCI_UART_H4 0
|
||||
#define HCI_UART_BCSP 1
|
||||
@@ -65,6 +28,12 @@
|
||||
#define HCI_UART_H4DS 3
|
||||
#define HCI_UART_LL 4
|
||||
#define HCI_UART_ATH3K 5
|
||||
#define HCI_UART_INTEL 6
|
||||
#define HCI_UART_BCM 7
|
||||
#define HCI_UART_QCA 8
|
||||
#define HCI_UART_AG6XX 9
|
||||
#define HCI_UART_NOKIA 10
|
||||
#define HCI_UART_MRVL 11
|
||||
|
||||
#define HCI_UART_RAW_DEVICE 0
|
||||
#define HCI_UART_RESET_ON_INIT 1
|
||||
@@ -74,42 +43,46 @@
|
||||
#define HCI_UART_VND_DETECT 5
|
||||
|
||||
struct hci_uart;
|
||||
struct serdev_device;
|
||||
|
||||
struct hci_uart_proto {
|
||||
unsigned int id;
|
||||
const char *name;
|
||||
unsigned int manufacturer;
|
||||
unsigned int init_speed;
|
||||
unsigned int oper_speed;
|
||||
int (*open)(struct hci_uart *hu);
|
||||
int (*close)(struct hci_uart *hu);
|
||||
int (*flush)(struct hci_uart *hu);
|
||||
int (*recv)(struct hci_uart *hu, void *data, int len);
|
||||
int (*setup)(struct hci_uart *hu);
|
||||
int (*set_baudrate)(struct hci_uart *hu, unsigned int speed);
|
||||
int (*recv)(struct hci_uart *hu, const void *data, int len);
|
||||
int (*enqueue)(struct hci_uart *hu, struct sk_buff *skb);
|
||||
struct sk_buff *(*dequeue)(struct hci_uart *hu);
|
||||
};
|
||||
|
||||
struct hci_uart {
|
||||
struct tty_struct *tty;
|
||||
struct serdev_device *serdev;
|
||||
struct hci_dev *hdev;
|
||||
unsigned long flags;
|
||||
unsigned long hdev_flags;
|
||||
|
||||
struct work_struct init_ready;
|
||||
struct work_struct write_work;
|
||||
struct workqueue_struct *hci_uart_wq;
|
||||
|
||||
struct hci_uart_proto *proto;
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)
|
||||
struct percpu_rw_semaphore proto_lock; /* Stop work for proto close */
|
||||
#else
|
||||
struct rw_semaphore proto_lock;
|
||||
#endif
|
||||
const struct hci_uart_proto *proto;
|
||||
struct percpu_rw_semaphore proto_lock; /* Stop work for proto close */
|
||||
void *priv;
|
||||
|
||||
struct semaphore tx_sem; /* semaphore for tx */
|
||||
|
||||
struct sk_buff *tx_skb;
|
||||
unsigned long tx_state;
|
||||
|
||||
#if WOBT_NOTIFY
|
||||
struct notifier_block pm_notify_block;
|
||||
#endif
|
||||
unsigned int init_speed;
|
||||
unsigned int oper_speed;
|
||||
|
||||
u8 alignment;
|
||||
u8 padding;
|
||||
};
|
||||
|
||||
/* HCI_UART proto flag bits */
|
||||
@@ -121,20 +94,108 @@ struct hci_uart {
|
||||
#define HCI_UART_SENDING 1
|
||||
#define HCI_UART_TX_WAKEUP 2
|
||||
|
||||
extern int hci_uart_register_proto(struct hci_uart_proto *p);
|
||||
extern int hci_uart_unregister_proto(struct hci_uart_proto *p);
|
||||
extern int hci_uart_tx_wakeup(struct hci_uart *hu);
|
||||
int hci_uart_register_proto(const struct hci_uart_proto *p);
|
||||
int hci_uart_unregister_proto(const struct hci_uart_proto *p);
|
||||
int hci_uart_register_device(struct hci_uart *hu, const struct hci_uart_proto *p);
|
||||
void hci_uart_unregister_device(struct hci_uart *hu);
|
||||
|
||||
int hci_uart_tx_wakeup(struct hci_uart *hu);
|
||||
int hci_uart_wait_until_sent(struct hci_uart *hu);
|
||||
int hci_uart_init_ready(struct hci_uart *hu);
|
||||
void hci_uart_init_work(struct work_struct *work);
|
||||
void hci_uart_set_baudrate(struct hci_uart *hu, unsigned int speed);
|
||||
bool hci_uart_has_flow_control(struct hci_uart *hu);
|
||||
void hci_uart_set_flow_control(struct hci_uart *hu, bool enable);
|
||||
void hci_uart_set_speeds(struct hci_uart *hu, unsigned int init_speed,
|
||||
unsigned int oper_speed);
|
||||
|
||||
#ifdef CONFIG_BT_HCIUART_H4
|
||||
extern int h4_init(void);
|
||||
extern int h4_deinit(void);
|
||||
int h4_init(void);
|
||||
int h4_deinit(void);
|
||||
|
||||
struct h4_recv_pkt {
|
||||
u8 type; /* Packet type */
|
||||
u8 hlen; /* Header length */
|
||||
u8 loff; /* Data length offset in header */
|
||||
u8 lsize; /* Data length field size */
|
||||
u16 maxlen; /* Max overall packet length */
|
||||
int (*recv)(struct hci_dev *hdev, struct sk_buff *skb);
|
||||
};
|
||||
|
||||
#define H4_RECV_ACL \
|
||||
.type = HCI_ACLDATA_PKT, \
|
||||
.hlen = HCI_ACL_HDR_SIZE, \
|
||||
.loff = 2, \
|
||||
.lsize = 2, \
|
||||
.maxlen = HCI_MAX_FRAME_SIZE \
|
||||
|
||||
#define H4_RECV_SCO \
|
||||
.type = HCI_SCODATA_PKT, \
|
||||
.hlen = HCI_SCO_HDR_SIZE, \
|
||||
.loff = 2, \
|
||||
.lsize = 1, \
|
||||
.maxlen = HCI_MAX_SCO_SIZE
|
||||
|
||||
#define H4_RECV_EVENT \
|
||||
.type = HCI_EVENT_PKT, \
|
||||
.hlen = HCI_EVENT_HDR_SIZE, \
|
||||
.loff = 1, \
|
||||
.lsize = 1, \
|
||||
.maxlen = HCI_MAX_EVENT_SIZE
|
||||
|
||||
#define H4_RECV_ISO \
|
||||
.type = HCI_ISODATA_PKT, \
|
||||
.hlen = HCI_ISO_HDR_SIZE, \
|
||||
.loff = 2, \
|
||||
.lsize = 2, \
|
||||
.maxlen = HCI_MAX_FRAME_SIZE \
|
||||
|
||||
struct sk_buff *h4_recv_buf(struct hci_dev *hdev, struct sk_buff *skb,
|
||||
const unsigned char *buffer, int count,
|
||||
const struct h4_recv_pkt *pkts, int pkts_count);
|
||||
#endif
|
||||
|
||||
extern int h5_init(void);
|
||||
extern int h5_deinit(void);
|
||||
|
||||
#if HCI_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
|
||||
extern int hci_uart_send_frame(struct sk_buff *skb);
|
||||
#else
|
||||
extern int hci_uart_send_frame(struct hci_dev *hdev, struct sk_buff *skb);
|
||||
#ifdef CONFIG_BT_HCIUART_BCSP
|
||||
int bcsp_init(void);
|
||||
int bcsp_deinit(void);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BT_HCIUART_LL
|
||||
int ll_init(void);
|
||||
int ll_deinit(void);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BT_HCIUART_ATH3K
|
||||
int ath_init(void);
|
||||
int ath_deinit(void);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BT_HCIUART_3WIRE
|
||||
int h5_init(void);
|
||||
int h5_deinit(void);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BT_HCIUART_INTEL
|
||||
int intel_init(void);
|
||||
int intel_deinit(void);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BT_HCIUART_BCM
|
||||
int bcm_init(void);
|
||||
int bcm_deinit(void);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BT_HCIUART_QCA
|
||||
int qca_init(void);
|
||||
int qca_deinit(void);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BT_HCIUART_AG6XX
|
||||
int ag6xx_init(void);
|
||||
int ag6xx_deinit(void);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BT_HCIUART_MRVL
|
||||
int mrvl_init(void);
|
||||
int mrvl_deinit(void);
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,373 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Realtek Bluetooth USB driver
|
||||
*
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
#include <net/bluetooth/hci_core.h>
|
||||
#include <linux/list.h>
|
||||
|
||||
/***********************************
|
||||
** Realtek - For coexistence **
|
||||
***********************************/
|
||||
#define BTRTL_HCIUSB 0
|
||||
#define BTRTL_HCIUART 1
|
||||
|
||||
#define BTRTL_HCI_IF BTRTL_HCIUART
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
#define CONNECT_PORT 30001
|
||||
#define CONNECT_PORT_WIFI 30000
|
||||
|
||||
#define invite_req "INVITE_REQ"
|
||||
#define invite_rsp "INVITE_RSP"
|
||||
#define attend_req "ATTEND_REQ"
|
||||
#define attend_ack "ATTEND_ACK"
|
||||
#define wifi_leave "WIFI_LEAVE"
|
||||
#define leave_ack "LEAVE_ACK"
|
||||
#define bt_leave "BT_LEAVE"
|
||||
|
||||
#define HCI_OP_PERIODIC_INQ 0x0403
|
||||
#define HCI_EV_LE_META 0x3e
|
||||
#define HCI_EV_LE_CONN_COMPLETE 0x01
|
||||
#define HCI_EV_LE_CONN_UPDATE_COMPLETE 0x03
|
||||
#define HCI_EV_LE_ENHANCED_CONN_COMPLETE 0x0a
|
||||
|
||||
//vendor cmd to fw
|
||||
#define HCI_VENDOR_ENABLE_PROFILE_REPORT_COMMAND 0xfc18
|
||||
#define HCI_VENDOR_SET_PROFILE_REPORT_COMMAND 0xfc19
|
||||
#define HCI_VENDOR_MAILBOX_CMD 0xfc8f
|
||||
#define HCI_VENDOR_SET_BITPOOL 0xfc51
|
||||
|
||||
//subcmd to fw
|
||||
#define HCI_VENDOR_SUB_CMD_WIFI_CHANNEL_AND_BANDWIDTH_CMD 0x11
|
||||
#define HCI_VENDOR_SUB_CMD_WIFI_FORCE_TX_POWER_CMD 0x17
|
||||
#define HCI_VENDOR_SUB_CMD_BT_ENABLE_IGNORE_WLAN_ACT_CMD 0x1B
|
||||
#define HCI_VENDOR_SUB_CMD_BT_REPORT_CONN_SCO_INQ_INFO 0x23
|
||||
#define HCI_VENDOR_SUB_CMD_BT_AUTO_REPORT_STATUS_INFO 0x27
|
||||
#define HCI_VENDOR_SUB_CMD_BT_AUTO_REPORT_ENABLE 0x28
|
||||
#define HCI_VENDOR_SUB_CMD_BT_SET_TXRETRY_REPORT_PARAM 0x29
|
||||
#define HCI_VENDOR_SUB_CMD_BT_SET_PTATABLE 0x2A
|
||||
#define HCI_VENDOR_SUB_CMD_SET_BT_PSD_MODE 0x31
|
||||
#define HCI_VENDOR_SUB_CMD_SET_BT_LNA_CONSTRAINT 0x32
|
||||
#define HCI_VENDOR_SUB_CMD_GET_AFH_MAP_L 0x40
|
||||
#define HCI_VENDOR_SUB_CMD_GET_AFH_MAP_M 0x41
|
||||
#define HCI_VENDOR_SUB_CMD_GET_AFH_MAP_H 0x42
|
||||
#define HCI_VENDOR_SUB_CMD_RD_REG_REQ 0x43
|
||||
#define HCI_VENDOR_SUB_CMD_WR_REG_REQ 0x44
|
||||
|
||||
#define HCI_EV_VENDOR_SPECIFIC 0xff
|
||||
|
||||
//sub event from fw start
|
||||
#define HCI_VENDOR_PTA_REPORT_EVENT 0x24
|
||||
#define HCI_VENDOR_PTA_AUTO_REPORT_EVENT 0x25
|
||||
|
||||
//vendor cmd to wifi driver
|
||||
#define HCI_GRP_VENDOR_SPECIFIC (0x3f << 10)
|
||||
#define HCI_OP_HCI_EXTENSION_VERSION_NOTIFY (0x0100 | HCI_GRP_VENDOR_SPECIFIC)
|
||||
#define HCI_OP_BT_OPERATION_NOTIFY (0x0102 | HCI_GRP_VENDOR_SPECIFIC)
|
||||
#define HCI_OP_HCI_BT_INFO_NOTIFY (0x0106 | HCI_GRP_VENDOR_SPECIFIC)
|
||||
#define HCI_OP_HCI_BT_COEX_NOTIFY (0x0107 | HCI_GRP_VENDOR_SPECIFIC)
|
||||
#define HCI_OP_HCI_BT_PATCH_VER_NOTIFY (0x0108 | HCI_GRP_VENDOR_SPECIFIC)
|
||||
#define HCI_OP_HCI_BT_AFH_MAP_NOTIFY (0x0109 | HCI_GRP_VENDOR_SPECIFIC)
|
||||
#define HCI_OP_HCI_BT_REGISTER_VALUE_NOTIFY (0x010a | HCI_GRP_VENDOR_SPECIFIC)
|
||||
|
||||
//bt info reason to wifi
|
||||
#define HOST_RESPONSE 0 //Host response when receive the BT Info Control Event
|
||||
#define POLLING_RESPONSE 1 //The BT Info response for polling by BT firmware.
|
||||
#define AUTO_REPORT 2 //BT auto report by BT firmware.
|
||||
#define STACK_REPORT_WHILE_DEVICE_D2 3 //Stack report when BT firmware is under power save state(ex:D2)
|
||||
|
||||
// vendor event from wifi
|
||||
#define RTK_HS_EXTENSION_EVENT_WIFI_SCAN 0x01
|
||||
#define RTK_HS_EXTENSION_EVENT_RADIO_STATUS_NOTIFY 0x02
|
||||
#define RTK_HS_EXTENSION_EVENT_HCI_BT_INFO_CONTROL 0x03
|
||||
#define RTK_HS_EXTENSION_EVENT_HCI_BT_COEX_CONTROL 0x04
|
||||
|
||||
//op code from wifi
|
||||
#define BT_PATCH_VERSION_QUERY 0x00
|
||||
#define IGNORE_WLAN_ACTIVE_CONTROL 0x01
|
||||
#define LNA_CONSTRAIN_CONTROL 0x02
|
||||
#define BT_POWER_DECREASE_CONTROL 0x03
|
||||
#define BT_PSD_MODE_CONTROL 0x04
|
||||
#define WIFI_BW_CHNL_NOTIFY 0x05
|
||||
#define QUERY_BT_AFH_MAP 0x06
|
||||
#define BT_REGISTER_ACCESS 0x07
|
||||
|
||||
//bt operation to notify
|
||||
#define BT_OPCODE_NONE 0
|
||||
#define BT_OPCODE_INQUIRY_START 1
|
||||
#define BT_OPCODE_INQUIRY_END 2
|
||||
#define BT_OPCODE_PAGE_START 3
|
||||
#define BT_OPCODE_PAGE_SUCCESS_END 4
|
||||
#define BT_OPCODE_PAGE_UNSUCCESS_END 5
|
||||
#define BT_OPCODE_PAIR_START 6
|
||||
#define BT_OPCODE_PAIR_END 7
|
||||
#define BT_OPCODE_ENABLE_BT 8
|
||||
#define BT_OPCODE_DISABLE_BT 9
|
||||
|
||||
#define HCI_EXTENSION_VERSION 0x0004
|
||||
#define HCI_CMD_PREAMBLE_SIZE 3
|
||||
#define PAN_PACKET_COUNT 5
|
||||
|
||||
#define STREAM_TO_UINT16(u16, p) {u16 = ((uint16_t)(*(p)) + (((uint16_t)(*((p) + 1))) << 8)); (p) += 2;}
|
||||
#define UINT16_TO_STREAM(p, u16) {*(p)++ = (uint8_t)(u16); *(p)++ = (uint8_t)((u16) >> 8);}
|
||||
|
||||
#define PSM_SDP 0x0001
|
||||
#define PSM_RFCOMM 0x0003
|
||||
#define PSM_PAN 0x000F
|
||||
#define PSM_HID 0x0011
|
||||
#define PSM_HID_INT 0x0013
|
||||
#define PSM_AVCTP 0x0017
|
||||
#define PSM_AVDTP 0x0019
|
||||
#define PSM_FTP 0x1001
|
||||
#define PSM_BIP 0x1003
|
||||
#define PSM_OPP 0x1015
|
||||
//--add more if needed--//
|
||||
|
||||
enum {
|
||||
profile_sco = 0,
|
||||
profile_hid = 1,
|
||||
profile_a2dp = 2,
|
||||
profile_pan = 3,
|
||||
profile_hid_interval = 4,
|
||||
profile_hogp = 5,
|
||||
profile_voice = 6,
|
||||
profile_sink = 7,
|
||||
profile_max = 8
|
||||
};
|
||||
|
||||
#define A2DP_SIGNAL 0x01
|
||||
#define A2DP_MEDIA 0x02
|
||||
//profile info data
|
||||
typedef struct {
|
||||
struct list_head list;
|
||||
uint16_t handle;
|
||||
uint16_t psm;
|
||||
uint16_t dcid;
|
||||
uint16_t scid;
|
||||
uint8_t profile_index;
|
||||
uint8_t flags;
|
||||
} rtk_prof_info, *prtk_prof_info;
|
||||
|
||||
//profile info for each connection
|
||||
typedef struct rtl_hci_conn {
|
||||
struct list_head list;
|
||||
uint16_t handle;
|
||||
uint8_t type; // 0:l2cap, 1:sco/esco, 2:le
|
||||
uint8_t profile_bitmap;
|
||||
int8_t profile_refcount[8];
|
||||
} rtk_conn_prof, *prtk_conn_prof;
|
||||
|
||||
#ifdef RTB_SOFTWARE_MAILBOX
|
||||
|
||||
struct rtl_btinfo {
|
||||
u8 cmd;
|
||||
u8 len;
|
||||
u8 data[6];
|
||||
};
|
||||
#define RTL_BTINFO_LEN (sizeof(struct rtl_btinfo))
|
||||
/* typedef struct {
|
||||
* uint8_t cmd_index;
|
||||
* uint8_t cmd_length;
|
||||
* uint8_t link_status;
|
||||
* uint8_t retry_cnt;
|
||||
* uint8_t rssi;
|
||||
* uint8_t mailbox_info;
|
||||
* uint16_t acl_throughput;
|
||||
* } hci_linkstatus_report; */
|
||||
|
||||
typedef struct {
|
||||
uint8_t type;
|
||||
uint32_t offset;
|
||||
uint32_t value;
|
||||
} hci_mailbox_register;
|
||||
|
||||
struct rtl_btinfo_ctl {
|
||||
uint8_t polling_enable;
|
||||
uint8_t polling_time;
|
||||
uint8_t autoreport_enable;
|
||||
};
|
||||
#endif /* RTB_SOFTWARE_MAILBOX */
|
||||
|
||||
#define MAX_LEN_OF_HCI_EV 32
|
||||
#define NUM_RTL_HCI_EV 32
|
||||
struct rtl_hci_ev {
|
||||
__u8 data[MAX_LEN_OF_HCI_EV];
|
||||
__u16 len;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
#define L2_MAX_SUBSEC_LEN 128
|
||||
#define L2_MAX_PKTS 16
|
||||
struct rtl_l2_buff {
|
||||
__u8 data[L2_MAX_SUBSEC_LEN];
|
||||
__u16 len;
|
||||
__u16 out;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
struct rtl_coex_struct {
|
||||
struct list_head conn_hash; //hash for connections
|
||||
struct list_head profile_list; //hash for profile info
|
||||
struct hci_dev *hdev;
|
||||
#ifdef RTB_SOFTWARE_MAILBOX
|
||||
struct socket *udpsock;
|
||||
struct sockaddr_in addr;
|
||||
struct sockaddr_in wifi_addr;
|
||||
struct timer_list polling_timer;
|
||||
#endif
|
||||
struct timer_list a2dp_count_timer;
|
||||
struct timer_list pan_count_timer;
|
||||
struct timer_list hogp_count_timer;
|
||||
#ifdef RTB_SOFTWARE_MAILBOX
|
||||
struct workqueue_struct *sock_wq;
|
||||
struct delayed_work sock_work;
|
||||
#endif
|
||||
struct workqueue_struct *fw_wq;
|
||||
struct delayed_work fw_work;
|
||||
struct delayed_work l2_work;
|
||||
#ifdef RTB_SOFTWARE_MAILBOX
|
||||
struct sock *sk;
|
||||
#endif
|
||||
struct urb *urb;
|
||||
spinlock_t spin_lock_sock;
|
||||
spinlock_t spin_lock_profile;
|
||||
uint32_t a2dp_packet_count;
|
||||
uint32_t pan_packet_count;
|
||||
uint32_t hogp_packet_count;
|
||||
uint32_t voice_packet_count;
|
||||
uint8_t profile_bitmap;
|
||||
uint8_t profile_status;
|
||||
int8_t profile_refcount[8];
|
||||
uint8_t ispairing;
|
||||
uint8_t isinquirying;
|
||||
uint8_t ispaging;
|
||||
#ifdef RTB_SOFTWARE_MAILBOX
|
||||
uint8_t wifi_state;
|
||||
uint8_t autoreport;
|
||||
uint8_t polling_enable;
|
||||
uint8_t polling_interval;
|
||||
uint8_t piconet_id;
|
||||
uint8_t mode;
|
||||
uint8_t afh_map[10];
|
||||
#endif
|
||||
uint16_t hci_reversion;
|
||||
uint16_t lmp_subversion;
|
||||
#ifdef RTB_SOFTWARE_MAILBOX
|
||||
uint8_t wifi_on;
|
||||
uint8_t sock_open;
|
||||
#endif
|
||||
unsigned long cmd_last_tx;
|
||||
|
||||
/* hci ev buff */
|
||||
struct list_head ev_used_list;
|
||||
struct list_head ev_free_list;
|
||||
|
||||
spinlock_t rxlock;
|
||||
__u8 pkt_type;
|
||||
__u16 expect;
|
||||
__u8 *tbuff;
|
||||
__u16 elen;
|
||||
__u8 back_buff[HCI_MAX_EVENT_SIZE];
|
||||
|
||||
/* l2cap rx buff */
|
||||
struct list_head l2_used_list;
|
||||
struct list_head l2_free_list;
|
||||
|
||||
/* buff addr and size */
|
||||
spinlock_t buff_lock;
|
||||
unsigned long pages_addr;
|
||||
unsigned long buff_size;
|
||||
|
||||
#define RTL_COEX_RUNNING (1 << 0)
|
||||
unsigned long flags;
|
||||
|
||||
};
|
||||
|
||||
#ifdef __LITTLE_ENDIAN
|
||||
struct sbc_frame_hdr {
|
||||
uint8_t syncword:8; /* Sync word */
|
||||
uint8_t subbands:1; /* Subbands */
|
||||
uint8_t allocation_method:1; /* Allocation method */
|
||||
uint8_t channel_mode:2; /* Channel mode */
|
||||
uint8_t blocks:2; /* Blocks */
|
||||
uint8_t sampling_frequency:2; /* Sampling frequency */
|
||||
uint8_t bitpool:8; /* Bitpool */
|
||||
uint8_t crc_check:8; /* CRC check */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* NOTE: The code is copied from pa.
|
||||
* only the bit field in 8-bit is affected by endian, not the 16-bit or 32-bit.
|
||||
* why?
|
||||
*/
|
||||
struct rtp_header {
|
||||
unsigned cc:4;
|
||||
unsigned x:1;
|
||||
unsigned p:1;
|
||||
unsigned v:2;
|
||||
|
||||
unsigned pt:7;
|
||||
unsigned m:1;
|
||||
|
||||
uint16_t sequence_number;
|
||||
uint32_t timestamp;
|
||||
uint32_t ssrc;
|
||||
uint32_t csrc[0];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#else
|
||||
/* big endian */
|
||||
struct sbc_frame_hdr {
|
||||
uint8_t syncword:8; /* Sync word */
|
||||
uint8_t sampling_frequency:2; /* Sampling frequency */
|
||||
uint8_t blocks:2; /* Blocks */
|
||||
uint8_t channel_mode:2; /* Channel mode */
|
||||
uint8_t allocation_method:1; /* Allocation method */
|
||||
uint8_t subbands:1; /* Subbands */
|
||||
uint8_t bitpool:8; /* Bitpool */
|
||||
uint8_t crc_check:8; /* CRC check */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct rtp_header {
|
||||
unsigned v:2;
|
||||
unsigned p:1;
|
||||
unsigned x:1;
|
||||
unsigned cc:4;
|
||||
|
||||
unsigned m:1;
|
||||
unsigned pt:7;
|
||||
|
||||
uint16_t sequence_number;
|
||||
uint32_t timestamp;
|
||||
uint32_t ssrc;
|
||||
uint32_t csrc[0];
|
||||
} __attribute__ ((packed));
|
||||
#endif /* __LITTLE_ENDIAN */
|
||||
|
||||
void rtk_btcoex_parse_event(uint8_t *buffer, int count);
|
||||
void rtk_btcoex_parse_cmd(uint8_t *buffer, int count);
|
||||
void rtk_btcoex_parse_l2cap_data_tx(uint8_t *buffer, int count);
|
||||
void rtk_btcoex_parse_l2cap_data_rx(uint8_t *buffer, int count);
|
||||
|
||||
void rtk_btcoex_open(struct hci_dev *hdev);
|
||||
void rtk_btcoex_close(void);
|
||||
void rtk_btcoex_probe(struct hci_dev *hdev);
|
||||
void rtk_btcoex_init(void);
|
||||
void rtk_btcoex_exit(void);
|
||||
@@ -1947,6 +1947,7 @@ _SetHardwareOptions(
|
||||
gcmkASSERT(gcvSTATUS_TRUE == gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_SECURITY_AHB));
|
||||
|
||||
options->secureMode = gcvSECURE_IN_NORMAL;
|
||||
pr_err("gcvSECURE_IN_NORMAL because of SECURITY\n");
|
||||
|
||||
status = gckOS_QueryOption(Hardware->os, "TA", &data);
|
||||
|
||||
@@ -1958,6 +1959,7 @@ _SetHardwareOptions(
|
||||
else if (gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_SECURITY_AHB))
|
||||
{
|
||||
options->secureMode = gcvSECURE_IN_NORMAL;
|
||||
pr_err("gcvSECURE_IN_NORMAL because of SECURITY_AHB\n");
|
||||
}
|
||||
|
||||
options->hasShader = database->NumShaderCores;
|
||||
|
||||
@@ -25,7 +25,7 @@ struct c910_priv {
|
||||
static gcsPLATFORM c910_platform;
|
||||
|
||||
static const struct of_device_id c910_gc620_dt_ids[] = {
|
||||
{ .compatible = "thead,c910-gc620", },
|
||||
{ .compatible = "vivante,gc", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, c910_gc620_dt_ids);
|
||||
@@ -37,7 +37,7 @@ static gceSTATUS c910_adjustParam(IN gcsPLATFORM * Platform,
|
||||
struct resource *res;
|
||||
struct platform_device *pdev = Platform->device;
|
||||
|
||||
irq = platform_get_irq_byname(pdev, "irq_2d");
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0)
|
||||
return gcvSTATUS_NOT_FOUND;
|
||||
|
||||
@@ -58,15 +58,15 @@ static gceSTATUS c910_getPower(IN gcsPLATFORM * Platform)
|
||||
struct c910_priv *c910 = Platform->priv;
|
||||
struct platform_device *pdev = c910_platform.device;
|
||||
|
||||
c910->pclk = devm_clk_get(&pdev->dev, "pclk");
|
||||
c910->pclk = devm_clk_get(&pdev->dev, "bus");
|
||||
if (IS_ERR(c910->pclk))
|
||||
return gcvSTATUS_NOT_FOUND;
|
||||
|
||||
c910->aclk = devm_clk_get(&pdev->dev, "aclk");
|
||||
c910->aclk = devm_clk_get(&pdev->dev, "core");
|
||||
if (IS_ERR(c910->aclk))
|
||||
return gcvSTATUS_NOT_FOUND;
|
||||
|
||||
c910->cclk = devm_clk_get(&pdev->dev, "cclk");
|
||||
c910->cclk = devm_clk_get(&pdev->dev, "shader");
|
||||
if (IS_ERR(c910->cclk))
|
||||
return gcvSTATUS_NOT_FOUND;
|
||||
|
||||
@@ -118,7 +118,7 @@ int gckPLATFORM_Init(struct platform_driver *pdrv, gcsPLATFORM **platform)
|
||||
struct platform_device *pdev;
|
||||
struct c910_priv *c910;
|
||||
|
||||
np = of_find_compatible_node(NULL, NULL, "thead,c910-gc620");
|
||||
np = of_find_compatible_node(NULL, NULL, "vivante,gc");
|
||||
if (!np)
|
||||
return -ENODEV;
|
||||
of_node_put(np);
|
||||
|
||||
@@ -65,6 +65,7 @@ DEALINGS IN THE SOFTWARE.
|
||||
#define chipModel_GC520 0x00000520
|
||||
#define chipModel_GC530 0x00000530
|
||||
#define chipModel_GC600 0x00000600
|
||||
#define chipModel_GC620 0x00000620
|
||||
#define chipModel_GC700 0x00000700
|
||||
#define chipModel_GC800 0x00000800
|
||||
#define chipModel_GC860 0x00000860
|
||||
|
||||
@@ -53,11 +53,12 @@ static inline void CMD_END(struct etnaviv_cmdbuf *buffer)
|
||||
OUT(buffer, VIV_FE_END_HEADER_OP_END);
|
||||
}
|
||||
|
||||
static inline void CMD_WAIT(struct etnaviv_cmdbuf *buffer)
|
||||
static inline void CMD_WAIT(struct etnaviv_cmdbuf *buffer,
|
||||
unsigned int waitcycles)
|
||||
{
|
||||
buffer->user_size = ALIGN(buffer->user_size, 8);
|
||||
|
||||
OUT(buffer, VIV_FE_WAIT_HEADER_OP_WAIT | 200);
|
||||
OUT(buffer, VIV_FE_WAIT_HEADER_OP_WAIT | waitcycles);
|
||||
}
|
||||
|
||||
static inline void CMD_LINK(struct etnaviv_cmdbuf *buffer,
|
||||
@@ -168,7 +169,7 @@ u16 etnaviv_buffer_init(struct etnaviv_gpu *gpu)
|
||||
/* initialize buffer */
|
||||
buffer->user_size = 0;
|
||||
|
||||
CMD_WAIT(buffer);
|
||||
CMD_WAIT(buffer, gpu->fe_waitcycles);
|
||||
CMD_LINK(buffer, 2,
|
||||
etnaviv_cmdbuf_get_va(buffer, &gpu->mmu_context->cmdbuf_mapping)
|
||||
+ buffer->user_size - 4);
|
||||
@@ -320,7 +321,7 @@ void etnaviv_sync_point_queue(struct etnaviv_gpu *gpu, unsigned int event)
|
||||
CMD_END(buffer);
|
||||
|
||||
/* Append waitlink */
|
||||
CMD_WAIT(buffer);
|
||||
CMD_WAIT(buffer, gpu->fe_waitcycles);
|
||||
CMD_LINK(buffer, 2,
|
||||
etnaviv_cmdbuf_get_va(buffer, &gpu->mmu_context->cmdbuf_mapping)
|
||||
+ buffer->user_size - 4);
|
||||
@@ -416,8 +417,11 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, u32 exec_state,
|
||||
|
||||
if (switch_mmu_context &&
|
||||
gpu->sec_mode == ETNA_SEC_KERNEL) {
|
||||
unsigned short id =
|
||||
etnaviv_iommuv2_get_pta_id(gpu->mmu_context);
|
||||
unsigned short id;
|
||||
|
||||
etnaviv_iommuv2_update_pta_entry(gpu->mmu_context);
|
||||
|
||||
id = etnaviv_iommuv2_get_pta_id(gpu->mmu_context);
|
||||
CMD_LOAD_STATE(buffer,
|
||||
VIVS_MMUv2_PTA_CONFIG,
|
||||
VIVS_MMUv2_PTA_CONFIG_INDEX(id));
|
||||
@@ -503,7 +507,7 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, u32 exec_state,
|
||||
|
||||
CMD_LOAD_STATE(buffer, VIVS_GL_EVENT, VIVS_GL_EVENT_EVENT_ID(event) |
|
||||
VIVS_GL_EVENT_FROM_PE);
|
||||
CMD_WAIT(buffer);
|
||||
CMD_WAIT(buffer, gpu->fe_waitcycles);
|
||||
CMD_LINK(buffer, 2,
|
||||
etnaviv_cmdbuf_get_va(buffer, &gpu->mmu_context->cmdbuf_mapping)
|
||||
+ buffer->user_size - 4);
|
||||
|
||||
@@ -121,6 +121,9 @@ void etnaviv_cmdbuf_free(struct etnaviv_cmdbuf *cmdbuf)
|
||||
int order = order_base_2(ALIGN(cmdbuf->size, SUBALLOC_GRANULE) /
|
||||
SUBALLOC_GRANULE);
|
||||
|
||||
if (!suballoc)
|
||||
return;
|
||||
|
||||
mutex_lock(&suballoc->lock);
|
||||
bitmap_release_region(suballoc->granule_map,
|
||||
cmdbuf->suballoc_offset / SUBALLOC_GRANULE,
|
||||
|
||||
@@ -468,12 +468,6 @@ static const struct drm_ioctl_desc etnaviv_ioctls[] = {
|
||||
ETNA_IOCTL(PM_QUERY_SIG, pm_query_sig, DRM_RENDER_ALLOW),
|
||||
};
|
||||
|
||||
static const struct vm_operations_struct vm_ops = {
|
||||
.fault = etnaviv_gem_fault,
|
||||
.open = drm_gem_vm_open,
|
||||
.close = drm_gem_vm_close,
|
||||
};
|
||||
|
||||
static const struct file_operations fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = drm_open,
|
||||
@@ -490,16 +484,9 @@ static struct drm_driver etnaviv_drm_driver = {
|
||||
.driver_features = DRIVER_GEM | DRIVER_RENDER,
|
||||
.open = etnaviv_open,
|
||||
.postclose = etnaviv_postclose,
|
||||
.gem_free_object_unlocked = etnaviv_gem_free_object,
|
||||
.gem_vm_ops = &vm_ops,
|
||||
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
|
||||
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
|
||||
.gem_prime_pin = etnaviv_gem_prime_pin,
|
||||
.gem_prime_unpin = etnaviv_gem_prime_unpin,
|
||||
.gem_prime_get_sg_table = etnaviv_gem_prime_get_sg_table,
|
||||
.gem_prime_import_sg_table = etnaviv_gem_prime_import_sg_table,
|
||||
.gem_prime_vmap = etnaviv_gem_prime_vmap,
|
||||
.gem_prime_vunmap = etnaviv_gem_prime_vunmap,
|
||||
.gem_prime_mmap = etnaviv_gem_prime_mmap,
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
.debugfs_init = etnaviv_debugfs_init,
|
||||
@@ -685,8 +672,24 @@ static int __init etnaviv_init(void)
|
||||
of_node_put(np);
|
||||
goto unregister_platform_driver;
|
||||
}
|
||||
pdev->dev.coherent_dma_mask = DMA_BIT_MASK(40);
|
||||
pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
|
||||
|
||||
/*
|
||||
* PTA and MTLB can have 40 bit base addresses, but
|
||||
* unfortunately, an entry in the MTLB can only point to a
|
||||
* 32 bit base address of a STLB. Moreover, to initialize the
|
||||
* MMU we need a command buffer with a 32 bit address because
|
||||
* without an MMU there is only an indentity mapping between
|
||||
* the internal 32 bit addresses and the bus addresses.
|
||||
*
|
||||
* To make things easy, we set the dma_coherent_mask to 32
|
||||
* bit to make sure we are allocating the command buffers and
|
||||
* TLBs in the lower 4 GiB address space.
|
||||
*/
|
||||
if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(40)) ||
|
||||
dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32))) {
|
||||
dev_dbg(&pdev->dev, "No suitable DMA available\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/*
|
||||
* Apply the same DMA configuration to the virtual etnaviv
|
||||
|
||||
@@ -49,7 +49,6 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
|
||||
struct drm_file *file);
|
||||
|
||||
int etnaviv_gem_mmap(struct file *filp, struct vm_area_struct *vma);
|
||||
vm_fault_t etnaviv_gem_fault(struct vm_fault *vmf);
|
||||
int etnaviv_gem_mmap_offset(struct drm_gem_object *obj, u64 *offset);
|
||||
struct sg_table *etnaviv_gem_prime_get_sg_table(struct drm_gem_object *obj);
|
||||
void *etnaviv_gem_prime_vmap(struct drm_gem_object *obj);
|
||||
|
||||
@@ -125,9 +125,9 @@ void etnaviv_core_dump(struct etnaviv_gem_submit *submit)
|
||||
return;
|
||||
etnaviv_dump_core = false;
|
||||
|
||||
mutex_lock(&gpu->mmu_context->lock);
|
||||
mutex_lock(&submit->mmu_context->lock);
|
||||
|
||||
mmu_size = etnaviv_iommu_dump_size(gpu->mmu_context);
|
||||
mmu_size = etnaviv_iommu_dump_size(submit->mmu_context);
|
||||
|
||||
/* We always dump registers, mmu, ring, hanging cmdbuf and end marker */
|
||||
n_obj = 5;
|
||||
@@ -157,7 +157,7 @@ void etnaviv_core_dump(struct etnaviv_gem_submit *submit)
|
||||
iter.start = __vmalloc(file_size, GFP_KERNEL | __GFP_NOWARN |
|
||||
__GFP_NORETRY);
|
||||
if (!iter.start) {
|
||||
mutex_unlock(&gpu->mmu_context->lock);
|
||||
mutex_unlock(&submit->mmu_context->lock);
|
||||
dev_warn(gpu->dev, "failed to allocate devcoredump file\n");
|
||||
return;
|
||||
}
|
||||
@@ -169,18 +169,18 @@ void etnaviv_core_dump(struct etnaviv_gem_submit *submit)
|
||||
memset(iter.hdr, 0, iter.data - iter.start);
|
||||
|
||||
etnaviv_core_dump_registers(&iter, gpu);
|
||||
etnaviv_core_dump_mmu(&iter, gpu->mmu_context, mmu_size);
|
||||
etnaviv_core_dump_mmu(&iter, submit->mmu_context, mmu_size);
|
||||
etnaviv_core_dump_mem(&iter, ETDUMP_BUF_RING, gpu->buffer.vaddr,
|
||||
gpu->buffer.size,
|
||||
etnaviv_cmdbuf_get_va(&gpu->buffer,
|
||||
&gpu->mmu_context->cmdbuf_mapping));
|
||||
&submit->mmu_context->cmdbuf_mapping));
|
||||
|
||||
etnaviv_core_dump_mem(&iter, ETDUMP_BUF_CMD,
|
||||
submit->cmdbuf.vaddr, submit->cmdbuf.size,
|
||||
etnaviv_cmdbuf_get_va(&submit->cmdbuf,
|
||||
&gpu->mmu_context->cmdbuf_mapping));
|
||||
&submit->mmu_context->cmdbuf_mapping));
|
||||
|
||||
mutex_unlock(&gpu->mmu_context->lock);
|
||||
mutex_unlock(&submit->mmu_context->lock);
|
||||
|
||||
/* Reserve space for the bomap */
|
||||
if (n_bomap_pages) {
|
||||
|
||||
@@ -130,8 +130,7 @@ static int etnaviv_gem_mmap_obj(struct etnaviv_gem_object *etnaviv_obj,
|
||||
{
|
||||
pgprot_t vm_page_prot;
|
||||
|
||||
vma->vm_flags &= ~VM_PFNMAP;
|
||||
vma->vm_flags |= VM_MIXEDMAP;
|
||||
vma->vm_flags |= VM_PFNMAP;
|
||||
|
||||
vm_page_prot = vm_get_page_prot(vma->vm_flags);
|
||||
|
||||
@@ -171,12 +170,13 @@ int etnaviv_gem_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
return obj->ops->mmap(obj, vma);
|
||||
}
|
||||
|
||||
vm_fault_t etnaviv_gem_fault(struct vm_fault *vmf)
|
||||
static vm_fault_t etnaviv_gem_fault(struct vm_fault *vmf)
|
||||
{
|
||||
struct vm_area_struct *vma = vmf->vma;
|
||||
struct drm_gem_object *obj = vma->vm_private_data;
|
||||
struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
|
||||
struct page **pages, *page;
|
||||
struct page **pages;
|
||||
unsigned long pfn;
|
||||
pgoff_t pgoff;
|
||||
int err;
|
||||
|
||||
@@ -200,12 +200,12 @@ vm_fault_t etnaviv_gem_fault(struct vm_fault *vmf)
|
||||
/* We don't use vmf->pgoff since that has the fake offset: */
|
||||
pgoff = (vmf->address - vma->vm_start) >> PAGE_SHIFT;
|
||||
|
||||
page = pages[pgoff];
|
||||
pfn = page_to_pfn(pages[pgoff]);
|
||||
|
||||
VERB("Inserting %p pfn %lx, pa %lx", (void *)vmf->address,
|
||||
page_to_pfn(page), page_to_pfn(page) << PAGE_SHIFT);
|
||||
pfn, pfn << PAGE_SHIFT);
|
||||
|
||||
return vmf_insert_page(vma, vmf->address, page);
|
||||
return vmf_insert_pfn(vma, vmf->address, pfn);
|
||||
}
|
||||
|
||||
int etnaviv_gem_mmap_offset(struct drm_gem_object *obj, u64 *offset)
|
||||
@@ -269,7 +269,12 @@ struct etnaviv_vram_mapping *etnaviv_gem_mapping_get(
|
||||
if (mapping->use == 0) {
|
||||
mutex_lock(&mmu_context->lock);
|
||||
if (mapping->context == mmu_context)
|
||||
mapping->use += 1;
|
||||
if (va && mapping->iova != va) {
|
||||
etnaviv_iommu_reap_mapping(mapping);
|
||||
mapping = NULL;
|
||||
} else {
|
||||
mapping->use += 1;
|
||||
}
|
||||
else
|
||||
mapping = NULL;
|
||||
mutex_unlock(&mmu_context->lock);
|
||||
@@ -305,18 +310,15 @@ struct etnaviv_vram_mapping *etnaviv_gem_mapping_get(
|
||||
list_del(&mapping->obj_node);
|
||||
}
|
||||
|
||||
mapping->context = etnaviv_iommu_context_get(mmu_context);
|
||||
mapping->use = 1;
|
||||
|
||||
ret = etnaviv_iommu_map_gem(mmu_context, etnaviv_obj,
|
||||
mmu_context->global->memory_base,
|
||||
mapping, va);
|
||||
if (ret < 0) {
|
||||
etnaviv_iommu_context_put(mmu_context);
|
||||
if (ret < 0)
|
||||
kfree(mapping);
|
||||
} else {
|
||||
else
|
||||
list_add_tail(&mapping->obj_node, &etnaviv_obj->vram_list);
|
||||
}
|
||||
|
||||
out:
|
||||
mutex_unlock(&etnaviv_obj->lock);
|
||||
@@ -532,10 +534,8 @@ void etnaviv_gem_free_object(struct drm_gem_object *obj)
|
||||
|
||||
WARN_ON(mapping->use);
|
||||
|
||||
if (context) {
|
||||
if (context)
|
||||
etnaviv_iommu_unmap_gem(context, mapping);
|
||||
etnaviv_iommu_context_put(context);
|
||||
}
|
||||
|
||||
list_del(&mapping->obj_node);
|
||||
kfree(mapping);
|
||||
@@ -558,6 +558,22 @@ void etnaviv_gem_obj_add(struct drm_device *dev, struct drm_gem_object *obj)
|
||||
mutex_unlock(&priv->gem_lock);
|
||||
}
|
||||
|
||||
static const struct vm_operations_struct vm_ops = {
|
||||
.fault = etnaviv_gem_fault,
|
||||
.open = drm_gem_vm_open,
|
||||
.close = drm_gem_vm_close,
|
||||
};
|
||||
|
||||
static const struct drm_gem_object_funcs etnaviv_gem_object_funcs = {
|
||||
.free = etnaviv_gem_free_object,
|
||||
.pin = etnaviv_gem_prime_pin,
|
||||
.unpin = etnaviv_gem_prime_unpin,
|
||||
.get_sg_table = etnaviv_gem_prime_get_sg_table,
|
||||
.vmap = etnaviv_gem_prime_vmap,
|
||||
.vunmap = etnaviv_gem_prime_vunmap,
|
||||
.vm_ops = &vm_ops,
|
||||
};
|
||||
|
||||
static int etnaviv_gem_new_impl(struct drm_device *dev, u32 size, u32 flags,
|
||||
const struct etnaviv_gem_ops *ops, struct drm_gem_object **obj)
|
||||
{
|
||||
@@ -592,6 +608,7 @@ static int etnaviv_gem_new_impl(struct drm_device *dev, u32 size, u32 flags,
|
||||
INIT_LIST_HEAD(&etnaviv_obj->vram_list);
|
||||
|
||||
*obj = &etnaviv_obj->base;
|
||||
(*obj)->funcs = &etnaviv_gem_object_funcs;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -99,6 +99,7 @@ struct etnaviv_gem_submit {
|
||||
int out_fence_id;
|
||||
struct list_head node; /* GPU active submit list */
|
||||
struct etnaviv_cmdbuf cmdbuf;
|
||||
struct pid *pid; /* submitting process */
|
||||
bool runtime_resumed;
|
||||
u32 exec_state;
|
||||
u32 flags;
|
||||
|
||||
@@ -93,7 +93,15 @@ static void *etnaviv_gem_prime_vmap_impl(struct etnaviv_gem_object *etnaviv_obj)
|
||||
static int etnaviv_gem_prime_mmap_obj(struct etnaviv_gem_object *etnaviv_obj,
|
||||
struct vm_area_struct *vma)
|
||||
{
|
||||
return dma_buf_mmap(etnaviv_obj->base.dma_buf, vma, 0);
|
||||
int ret;
|
||||
|
||||
ret = dma_buf_mmap(etnaviv_obj->base.dma_buf, vma, 0);
|
||||
if (!ret) {
|
||||
/* Drop the reference acquired by drm_gem_mmap_obj(). */
|
||||
drm_gem_object_put(&etnaviv_obj->base);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct etnaviv_gem_ops etnaviv_gem_prime_ops = {
|
||||
|
||||
@@ -407,11 +407,14 @@ static void submit_cleanup(struct kref *kref)
|
||||
dma_fence_put(submit->in_fence);
|
||||
if (submit->out_fence) {
|
||||
/* first remove from IDR, so fence can not be found anymore */
|
||||
mutex_lock(&submit->gpu->fence_lock);
|
||||
mutex_lock(&submit->gpu->idr_lock);
|
||||
idr_remove(&submit->gpu->fence_idr, submit->out_fence_id);
|
||||
mutex_unlock(&submit->gpu->fence_lock);
|
||||
mutex_unlock(&submit->gpu->idr_lock);
|
||||
dma_fence_put(submit->out_fence);
|
||||
}
|
||||
|
||||
put_pid(submit->pid);
|
||||
|
||||
kfree(submit->pmrs);
|
||||
kfree(submit);
|
||||
}
|
||||
@@ -435,6 +438,7 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
|
||||
struct sync_file *sync_file = NULL;
|
||||
struct ww_acquire_ctx ticket;
|
||||
int out_fence_fd = -1;
|
||||
struct pid *pid = get_pid(task_pid(current));
|
||||
void *stream;
|
||||
int ret;
|
||||
|
||||
@@ -532,6 +536,8 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
|
||||
goto err_submit_ww_acquire;
|
||||
}
|
||||
|
||||
submit->pid = pid;
|
||||
|
||||
ret = etnaviv_cmdbuf_init(priv->cmdbuf_suballoc, &submit->cmdbuf,
|
||||
ALIGN(args->stream_size, 8) + 8);
|
||||
if (ret)
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/string_helpers.h>
|
||||
#include <linux/thermal.h>
|
||||
|
||||
#include "etnaviv_cmdbuf.h"
|
||||
@@ -27,10 +28,6 @@
|
||||
#include "state_hi.xml.h"
|
||||
#include "cmdstream.xml.h"
|
||||
|
||||
#ifndef PHYS_OFFSET
|
||||
#define PHYS_OFFSET 0
|
||||
#endif
|
||||
|
||||
static const struct platform_device_id gpu_ids[] = {
|
||||
{ .name = "etnaviv-gpu,2d" },
|
||||
{ },
|
||||
@@ -156,6 +153,18 @@ int etnaviv_gpu_get_param(struct etnaviv_gpu *gpu, u32 param, u64 *value)
|
||||
*value = ~0ULL;
|
||||
break;
|
||||
|
||||
case ETNAVIV_PARAM_GPU_PRODUCT_ID:
|
||||
*value = gpu->identity.product_id;
|
||||
break;
|
||||
|
||||
case ETNAVIV_PARAM_GPU_CUSTOMER_ID:
|
||||
*value = gpu->identity.customer_id;
|
||||
break;
|
||||
|
||||
case ETNAVIV_PARAM_GPU_ECO_ID:
|
||||
*value = gpu->identity.eco_id;
|
||||
break;
|
||||
|
||||
default:
|
||||
DBG("%s: invalid param: %u", dev_name(gpu->dev), param);
|
||||
return -EINVAL;
|
||||
@@ -408,6 +417,12 @@ static void etnaviv_hw_identify(struct etnaviv_gpu *gpu)
|
||||
if (gpu->identity.model == chipModel_GC700)
|
||||
gpu->identity.features &= ~chipFeatures_FAST_CLEAR;
|
||||
|
||||
/* These models/revisions don't have the 2D pipe bit */
|
||||
if ((gpu->identity.model == chipModel_GC500 &&
|
||||
gpu->identity.revision <= 2) ||
|
||||
gpu->identity.model == chipModel_GC300)
|
||||
gpu->identity.features |= chipFeatures_PIPE_2D;
|
||||
|
||||
if ((gpu->identity.model == chipModel_GC500 &&
|
||||
gpu->identity.revision < 2) ||
|
||||
(gpu->identity.model == chipModel_GC300 &&
|
||||
@@ -441,8 +456,9 @@ static void etnaviv_hw_identify(struct etnaviv_gpu *gpu)
|
||||
gpu_read(gpu, VIVS_HI_CHIP_MINOR_FEATURE_5);
|
||||
}
|
||||
|
||||
/* GC600 idle register reports zero bits where modules aren't present */
|
||||
if (gpu->identity.model == chipModel_GC600)
|
||||
/* GC600/300 idle register reports zero bits where modules aren't present */
|
||||
if (gpu->identity.model == chipModel_GC600 ||
|
||||
gpu->identity.model == chipModel_GC300)
|
||||
gpu->idle_mask = VIVS_HI_IDLE_STATE_TX |
|
||||
VIVS_HI_IDLE_STATE_RA |
|
||||
VIVS_HI_IDLE_STATE_SE |
|
||||
@@ -478,6 +494,14 @@ static void etnaviv_gpu_update_clock(struct etnaviv_gpu *gpu)
|
||||
clock |= VIVS_HI_CLOCK_CONTROL_FSCALE_VAL(fscale);
|
||||
etnaviv_gpu_load_clock(gpu, clock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Choose number of wait cycles to target a ~30us (1/32768) max latency
|
||||
* until new work is picked up by the FE when it polls in the idle loop.
|
||||
* If the GPU base frequency is unknown use 200 wait cycles.
|
||||
*/
|
||||
gpu->fe_waitcycles = clamp(gpu->base_rate_core >> (15 - gpu->freq_scale),
|
||||
200UL, 0xffffUL);
|
||||
}
|
||||
|
||||
static int etnaviv_hw_reset(struct etnaviv_gpu *gpu)
|
||||
@@ -499,7 +523,11 @@ static int etnaviv_hw_reset(struct etnaviv_gpu *gpu)
|
||||
control |= VIVS_HI_CLOCK_CONTROL_ISOLATE_GPU;
|
||||
gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, control);
|
||||
|
||||
if (gpu->sec_mode == ETNA_SEC_KERNEL) {
|
||||
if (etnaviv_is_model_rev(gpu, GC620, 0x5552)) {
|
||||
gpu_write(gpu, 0x00800, 0x10);
|
||||
}
|
||||
|
||||
if (gpu->identity.minor_features7 & chipMinorFeatures7_BIT_SECURITY) {
|
||||
gpu_write(gpu, VIVS_MMUv2_AHB_CONTROL,
|
||||
VIVS_MMUv2_AHB_CONTROL_RESET);
|
||||
} else {
|
||||
@@ -561,7 +589,7 @@ static int etnaviv_hw_reset(struct etnaviv_gpu *gpu)
|
||||
/* We rely on the GPU running, so program the clock */
|
||||
etnaviv_gpu_update_clock(gpu);
|
||||
|
||||
gpu->fe_running = false;
|
||||
gpu->state = ETNA_GPU_STATE_RESET;
|
||||
gpu->exec_state = -1;
|
||||
if (gpu->mmu_context)
|
||||
etnaviv_iommu_context_put(gpu->mmu_context);
|
||||
@@ -629,8 +657,6 @@ void etnaviv_gpu_start_fe(struct etnaviv_gpu *gpu, u32 address, u16 prefetch)
|
||||
VIVS_MMUv2_SEC_COMMAND_CONTROL_ENABLE |
|
||||
VIVS_MMUv2_SEC_COMMAND_CONTROL_PREFETCH(prefetch));
|
||||
}
|
||||
|
||||
gpu->fe_running = true;
|
||||
}
|
||||
|
||||
static void etnaviv_gpu_start_fe_idleloop(struct etnaviv_gpu *gpu,
|
||||
@@ -639,6 +665,8 @@ static void etnaviv_gpu_start_fe_idleloop(struct etnaviv_gpu *gpu,
|
||||
u16 prefetch;
|
||||
u32 address;
|
||||
|
||||
WARN_ON(gpu->state != ETNA_GPU_STATE_INITIALIZED);
|
||||
|
||||
/* setup the MMU */
|
||||
etnaviv_iommu_restore(gpu, context);
|
||||
|
||||
@@ -648,6 +676,8 @@ static void etnaviv_gpu_start_fe_idleloop(struct etnaviv_gpu *gpu,
|
||||
&gpu->mmu_context->cmdbuf_mapping);
|
||||
|
||||
etnaviv_gpu_start_fe(gpu, address, prefetch);
|
||||
|
||||
gpu->state = ETNA_GPU_STATE_RUNNING;
|
||||
}
|
||||
|
||||
static void etnaviv_gpu_setup_pulse_eater(struct etnaviv_gpu *gpu)
|
||||
@@ -683,6 +713,9 @@ static void etnaviv_gpu_setup_pulse_eater(struct etnaviv_gpu *gpu)
|
||||
|
||||
static void etnaviv_gpu_hw_init(struct etnaviv_gpu *gpu)
|
||||
{
|
||||
WARN_ON(!(gpu->state == ETNA_GPU_STATE_IDENTIFIED ||
|
||||
gpu->state == ETNA_GPU_STATE_RESET));
|
||||
|
||||
if ((etnaviv_is_model_rev(gpu, GC320, 0x5007) ||
|
||||
etnaviv_is_model_rev(gpu, GC320, 0x5220)) &&
|
||||
gpu_read(gpu, VIVS_HI_CHIP_TIME) != 0x2062400) {
|
||||
@@ -719,7 +752,13 @@ static void etnaviv_gpu_hw_init(struct etnaviv_gpu *gpu)
|
||||
gpu_write(gpu, VIVS_MC_BUS_CONFIG, bus_config);
|
||||
}
|
||||
|
||||
if (gpu->sec_mode == ETNA_SEC_KERNEL) {
|
||||
/* FIXME: use feature bit 5 of minor features 12, G2D_DEC400EX */
|
||||
if (etnaviv_is_model_rev(gpu, GC620, 0x5552)) {
|
||||
gpu_write(gpu, 0x800, 0x2010188);
|
||||
gpu_write(gpu, 0x808, 0x3fc104);
|
||||
}
|
||||
|
||||
if (gpu->identity.minor_features7 & chipMinorFeatures7_BIT_SECURITY) {
|
||||
u32 val = gpu_read(gpu, VIVS_MMUv2_AHB_CONTROL);
|
||||
val |= VIVS_MMUv2_AHB_CONTROL_NONSEC_ACCESS;
|
||||
gpu_write(gpu, VIVS_MMUv2_AHB_CONTROL, val);
|
||||
@@ -729,11 +768,14 @@ static void etnaviv_gpu_hw_init(struct etnaviv_gpu *gpu)
|
||||
etnaviv_gpu_setup_pulse_eater(gpu);
|
||||
|
||||
gpu_write(gpu, VIVS_HI_INTR_ENBL, ~0U);
|
||||
|
||||
gpu->state = ETNA_GPU_STATE_INITIALIZED;
|
||||
}
|
||||
|
||||
int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
|
||||
{
|
||||
struct etnaviv_drm_private *priv = gpu->drm->dev_private;
|
||||
dma_addr_t cmdbuf_paddr;
|
||||
int ret, i;
|
||||
|
||||
ret = pm_runtime_get_sync(gpu->dev);
|
||||
@@ -762,10 +804,12 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
|
||||
* On cores with security features supported, we claim control over the
|
||||
* security states.
|
||||
*/
|
||||
if ((gpu->identity.minor_features7 & chipMinorFeatures7_BIT_SECURITY) &&
|
||||
if ((gpu->identity.minor_features7 & chipMinorFeatures7_BIT_SECURITY) ||
|
||||
(gpu->identity.minor_features10 & chipMinorFeatures10_SECURITY_AHB))
|
||||
gpu->sec_mode = ETNA_SEC_KERNEL;
|
||||
|
||||
gpu->state = ETNA_GPU_STATE_IDENTIFIED;
|
||||
|
||||
ret = etnaviv_hw_reset(gpu);
|
||||
if (ret) {
|
||||
dev_err(gpu->dev, "GPU reset failed\n");
|
||||
@@ -776,28 +820,6 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
/*
|
||||
* Set the GPU linear window to be at the end of the DMA window, where
|
||||
* the CMA area is likely to reside. This ensures that we are able to
|
||||
* map the command buffers while having the linear window overlap as
|
||||
* much RAM as possible, so we can optimize mappings for other buffers.
|
||||
*
|
||||
* For 3D cores only do this if MC2.0 is present, as with MC1.0 it leads
|
||||
* to different views of the memory on the individual engines.
|
||||
*/
|
||||
if (!(gpu->identity.features & chipFeatures_PIPE_3D) ||
|
||||
(gpu->identity.minor_features0 & chipMinorFeatures0_MC20)) {
|
||||
u32 dma_mask = (u32)dma_get_required_mask(gpu->dev);
|
||||
if (dma_mask < PHYS_OFFSET + SZ_2G)
|
||||
priv->mmu_global->memory_base = PHYS_OFFSET;
|
||||
else
|
||||
priv->mmu_global->memory_base = dma_mask - SZ_2G + 1;
|
||||
} else if (PHYS_OFFSET >= SZ_2G) {
|
||||
dev_info(gpu->dev, "Need to move linear window on MC1.0, disabling TS\n");
|
||||
priv->mmu_global->memory_base = PHYS_OFFSET;
|
||||
gpu->identity.features &= ~chipFeatures_FAST_CLEAR;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the GPU is part of a system with DMA addressing limitations,
|
||||
* request pages for our SHM backend buffers from the DMA32 zone to
|
||||
@@ -814,6 +836,31 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the GPU linear window to cover the cmdbuf region, as the GPU
|
||||
* won't be able to start execution otherwise. The alignment to 128M is
|
||||
* chosen arbitrarily but helps in debugging, as the MMU offset
|
||||
* calculations are much more straight forward this way.
|
||||
*
|
||||
* On MC1.0 cores the linear window offset is ignored by the TS engine,
|
||||
* leading to inconsistent memory views. Avoid using the offset on those
|
||||
* cores if possible, otherwise disable the TS feature.
|
||||
*/
|
||||
cmdbuf_paddr = ALIGN_DOWN(etnaviv_cmdbuf_get_pa(&gpu->buffer), SZ_128M);
|
||||
|
||||
if (!(gpu->identity.features & chipFeatures_PIPE_3D) ||
|
||||
(gpu->identity.minor_features0 & chipMinorFeatures0_MC20)) {
|
||||
if (cmdbuf_paddr >= SZ_2G)
|
||||
priv->mmu_global->memory_base = SZ_2G;
|
||||
else
|
||||
priv->mmu_global->memory_base = cmdbuf_paddr;
|
||||
} else if (cmdbuf_paddr + SZ_128M >= SZ_2G) {
|
||||
dev_info(gpu->dev,
|
||||
"Need to move linear window on MC1.0, disabling TS\n");
|
||||
gpu->identity.features &= ~chipFeatures_FAST_CLEAR;
|
||||
priv->mmu_global->memory_base = SZ_2G;
|
||||
}
|
||||
|
||||
/* Setup event management */
|
||||
spin_lock_init(&gpu->event_spinlock);
|
||||
init_completion(&gpu->event_free);
|
||||
@@ -829,8 +876,6 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
|
||||
pm_runtime_mark_last_busy(gpu->dev);
|
||||
pm_runtime_put_autosuspend(gpu->dev);
|
||||
|
||||
gpu->initialized = true;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
@@ -1027,12 +1072,28 @@ pm_put:
|
||||
}
|
||||
#endif
|
||||
|
||||
void etnaviv_gpu_recover_hang(struct etnaviv_gpu *gpu)
|
||||
void etnaviv_gpu_recover_hang(struct etnaviv_gem_submit *submit)
|
||||
{
|
||||
struct etnaviv_gpu *gpu = submit->gpu;
|
||||
char *comm = NULL, *cmd = NULL;
|
||||
struct task_struct *task;
|
||||
unsigned int i = 0;
|
||||
|
||||
dev_err(gpu->dev, "recover hung GPU!\n");
|
||||
|
||||
task = get_pid_task(submit->pid, PIDTYPE_PID);
|
||||
if (task) {
|
||||
comm = kstrdup(task->comm, GFP_KERNEL);
|
||||
cmd = kstrdup_quotable_cmdline(task, GFP_KERNEL);
|
||||
put_task_struct(task);
|
||||
}
|
||||
|
||||
if (comm && cmd)
|
||||
dev_err(gpu->dev, "offending task: %s (%s)\n", comm, cmd);
|
||||
|
||||
kfree(cmd);
|
||||
kfree(comm);
|
||||
|
||||
if (pm_runtime_get_sync(gpu->dev) < 0)
|
||||
goto pm_put;
|
||||
|
||||
@@ -1359,7 +1420,7 @@ struct dma_fence *etnaviv_gpu_submit(struct etnaviv_gem_submit *submit)
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
if (!gpu->fe_running)
|
||||
if (gpu->state == ETNA_GPU_STATE_INITIALIZED)
|
||||
etnaviv_gpu_start_fe_idleloop(gpu, submit->mmu_context);
|
||||
|
||||
if (submit->prev_mmu_context)
|
||||
@@ -1408,6 +1469,15 @@ static void sync_point_worker(struct work_struct *work)
|
||||
|
||||
static void dump_mmu_fault(struct etnaviv_gpu *gpu)
|
||||
{
|
||||
static const char *fault_reasons[] = {
|
||||
"slave not present",
|
||||
"page not present",
|
||||
"write violation",
|
||||
"out of bounds",
|
||||
"read security violation",
|
||||
"write security violation",
|
||||
};
|
||||
|
||||
u32 status_reg, status;
|
||||
int i;
|
||||
|
||||
@@ -1420,18 +1490,25 @@ static void dump_mmu_fault(struct etnaviv_gpu *gpu)
|
||||
dev_err_ratelimited(gpu->dev, "MMU fault status 0x%08x\n", status);
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
const char *reason = "unknown";
|
||||
u32 address_reg;
|
||||
u32 mmu_status;
|
||||
|
||||
if (!(status & (VIVS_MMUv2_STATUS_EXCEPTION0__MASK << (i * 4))))
|
||||
mmu_status = (status >> (i * 4)) & VIVS_MMUv2_STATUS_EXCEPTION0__MASK;
|
||||
if (!mmu_status)
|
||||
continue;
|
||||
|
||||
if ((mmu_status - 1) < ARRAY_SIZE(fault_reasons))
|
||||
reason = fault_reasons[mmu_status - 1];
|
||||
|
||||
if (gpu->sec_mode == ETNA_SEC_NONE)
|
||||
address_reg = VIVS_MMUv2_EXCEPTION_ADDR(i);
|
||||
else
|
||||
address_reg = VIVS_MMUv2_SEC_EXCEPTION_ADDR;
|
||||
|
||||
dev_err_ratelimited(gpu->dev, "MMU %d fault addr 0x%08x\n", i,
|
||||
gpu_read(gpu, address_reg));
|
||||
dev_err_ratelimited(gpu->dev,
|
||||
"MMU %d fault (%s) addr 0x%08x\n",
|
||||
i, reason, gpu_read(gpu, address_reg));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1456,6 +1533,8 @@ static irqreturn_t irq_handler(int irq, void *data)
|
||||
|
||||
if (intr & VIVS_HI_INTR_ACKNOWLEDGE_MMU_EXCEPTION) {
|
||||
dump_mmu_fault(gpu);
|
||||
gpu->state = ETNA_GPU_STATE_FAULT;
|
||||
drm_sched_fault(&gpu->sched);
|
||||
intr &= ~VIVS_HI_INTR_ACKNOWLEDGE_MMU_EXCEPTION;
|
||||
}
|
||||
|
||||
@@ -1566,7 +1645,7 @@ int etnaviv_gpu_wait_idle(struct etnaviv_gpu *gpu, unsigned int timeout_ms)
|
||||
|
||||
static int etnaviv_gpu_hw_suspend(struct etnaviv_gpu *gpu)
|
||||
{
|
||||
if (gpu->initialized && gpu->fe_running) {
|
||||
if (gpu->state == ETNA_GPU_STATE_RUNNING) {
|
||||
/* Replace the last WAIT with END */
|
||||
mutex_lock(&gpu->lock);
|
||||
etnaviv_buffer_end(gpu);
|
||||
@@ -1579,11 +1658,13 @@ static int etnaviv_gpu_hw_suspend(struct etnaviv_gpu *gpu)
|
||||
*/
|
||||
etnaviv_gpu_wait_idle(gpu, 100);
|
||||
|
||||
gpu->fe_running = false;
|
||||
gpu->state = ETNA_GPU_STATE_INITIALIZED;
|
||||
}
|
||||
|
||||
gpu->exec_state = -1;
|
||||
|
||||
gpu->state = ETNA_GPU_STATE_IDENTIFIED;
|
||||
|
||||
return etnaviv_gpu_clk_disable(gpu);
|
||||
}
|
||||
|
||||
@@ -1671,13 +1752,11 @@ static int etnaviv_gpu_bind(struct device *dev, struct device *master,
|
||||
if (ret)
|
||||
goto out_workqueue;
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
ret = pm_runtime_get_sync(gpu->dev);
|
||||
#else
|
||||
#ifndef CONFIG_PM
|
||||
ret = etnaviv_gpu_clk_enable(gpu);
|
||||
#endif
|
||||
if (ret < 0)
|
||||
goto out_sched;
|
||||
#endif
|
||||
|
||||
|
||||
gpu->drm = drm;
|
||||
@@ -1690,9 +1769,6 @@ static int etnaviv_gpu_bind(struct device *dev, struct device *master,
|
||||
|
||||
priv->gpu[priv->num_gpus++] = gpu;
|
||||
|
||||
pm_runtime_mark_last_busy(gpu->dev);
|
||||
pm_runtime_put_autosuspend(gpu->dev);
|
||||
|
||||
return 0;
|
||||
|
||||
out_sched:
|
||||
@@ -1730,11 +1806,8 @@ static void etnaviv_gpu_unbind(struct device *dev, struct device *master,
|
||||
if (gpu->mmu_context)
|
||||
etnaviv_iommu_context_put(gpu->mmu_context);
|
||||
|
||||
if (gpu->initialized) {
|
||||
etnaviv_cmdbuf_free(&gpu->buffer);
|
||||
etnaviv_iommu_global_fini(gpu);
|
||||
gpu->initialized = false;
|
||||
}
|
||||
etnaviv_cmdbuf_free(&gpu->buffer);
|
||||
etnaviv_iommu_global_fini(gpu);
|
||||
|
||||
gpu->drm = NULL;
|
||||
idr_destroy(&gpu->fence_idr);
|
||||
@@ -1769,7 +1842,8 @@ static int etnaviv_gpu_platform_probe(struct platform_device *pdev)
|
||||
|
||||
gpu->dev = &pdev->dev;
|
||||
mutex_init(&gpu->lock);
|
||||
mutex_init(&gpu->fence_lock);
|
||||
mutex_init(&gpu->sched_lock);
|
||||
mutex_init(&gpu->idr_lock);
|
||||
|
||||
/* Map registers: */
|
||||
gpu->mmio = devm_platform_ioremap_resource(pdev, 0);
|
||||
@@ -1874,7 +1948,7 @@ static int etnaviv_gpu_rpm_resume(struct device *dev)
|
||||
return ret;
|
||||
|
||||
/* Re-initialise the basic hardware state */
|
||||
if (gpu->drm && gpu->initialized) {
|
||||
if (gpu->state == ETNA_GPU_STATE_IDENTIFIED) {
|
||||
ret = etnaviv_gpu_hw_resume(gpu);
|
||||
if (ret) {
|
||||
etnaviv_gpu_clk_disable(gpu);
|
||||
|
||||
@@ -91,6 +91,15 @@ struct clk;
|
||||
|
||||
#define ETNA_NR_EVENTS 30
|
||||
|
||||
enum etnaviv_gpu_state {
|
||||
ETNA_GPU_STATE_UNKNOWN = 0,
|
||||
ETNA_GPU_STATE_IDENTIFIED,
|
||||
ETNA_GPU_STATE_RESET,
|
||||
ETNA_GPU_STATE_INITIALIZED,
|
||||
ETNA_GPU_STATE_RUNNING,
|
||||
ETNA_GPU_STATE_FAULT,
|
||||
};
|
||||
|
||||
struct etnaviv_gpu {
|
||||
struct drm_device *drm;
|
||||
struct thermal_cooling_device *cooling;
|
||||
@@ -99,9 +108,9 @@ struct etnaviv_gpu {
|
||||
struct etnaviv_chip_identity identity;
|
||||
enum etnaviv_sec_mode sec_mode;
|
||||
struct workqueue_struct *wq;
|
||||
struct mutex sched_lock;
|
||||
struct drm_gpu_scheduler sched;
|
||||
bool initialized;
|
||||
bool fe_running;
|
||||
enum etnaviv_gpu_state state;
|
||||
|
||||
/* 'ring'-buffer: */
|
||||
struct etnaviv_cmdbuf buffer;
|
||||
@@ -116,7 +125,7 @@ struct etnaviv_gpu {
|
||||
u32 idle_mask;
|
||||
|
||||
/* Fencing support */
|
||||
struct mutex fence_lock;
|
||||
struct mutex idr_lock;
|
||||
struct idr fence_idr;
|
||||
u32 next_fence;
|
||||
u32 completed_fence;
|
||||
@@ -145,6 +154,7 @@ struct etnaviv_gpu {
|
||||
struct clk *clk_shader;
|
||||
|
||||
unsigned int freq_scale;
|
||||
unsigned int fe_waitcycles;
|
||||
unsigned long base_rate_core;
|
||||
unsigned long base_rate_shader;
|
||||
};
|
||||
@@ -168,7 +178,7 @@ bool etnaviv_fill_identity_from_hwdb(struct etnaviv_gpu *gpu);
|
||||
int etnaviv_gpu_debugfs(struct etnaviv_gpu *gpu, struct seq_file *m);
|
||||
#endif
|
||||
|
||||
void etnaviv_gpu_recover_hang(struct etnaviv_gpu *gpu);
|
||||
void etnaviv_gpu_recover_hang(struct etnaviv_gem_submit *submit);
|
||||
void etnaviv_gpu_retire(struct etnaviv_gpu *gpu);
|
||||
int etnaviv_gpu_wait_fence_interruptible(struct etnaviv_gpu *gpu,
|
||||
u32 fence, struct drm_etnaviv_timespec *timeout);
|
||||
|
||||
@@ -37,6 +37,37 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = {
|
||||
.minor_features10 = 0x0,
|
||||
.minor_features11 = 0x0,
|
||||
},
|
||||
{
|
||||
.model = 0x620,
|
||||
.revision = 0x5552,
|
||||
.product_id = 0x6200,
|
||||
.customer_id = 0x20b,
|
||||
.eco_id = 0,
|
||||
.stream_count = 1,
|
||||
.register_max = 64,
|
||||
.thread_count = 256,
|
||||
.shader_core_count = 1,
|
||||
.vertex_cache_size = 8,
|
||||
.vertex_output_buffer_size = 512,
|
||||
.pixel_pipes = 1,
|
||||
.instruction_count = 256,
|
||||
.num_constants = 168,
|
||||
.buffer_size = 0,
|
||||
.varyings_count = 8,
|
||||
.features = 0x001b4a40,
|
||||
.minor_features0 = 0xa0600080,
|
||||
.minor_features1 = 0x18050000,
|
||||
.minor_features2 = 0x04f30000,
|
||||
.minor_features3 = 0x00060005,
|
||||
.minor_features4 = 0x20629000,
|
||||
.minor_features5 = 0x0003380c,
|
||||
.minor_features6 = 0x00000000,
|
||||
.minor_features7 = 0x00001000,
|
||||
.minor_features8 = 0x00000000,
|
||||
.minor_features9 = 0x00000180,
|
||||
.minor_features10 = 0x00004000,
|
||||
.minor_features11 = 0x00000000,
|
||||
},
|
||||
{
|
||||
.model = 0x7000,
|
||||
.revision = 0x6214,
|
||||
|
||||
@@ -186,6 +186,14 @@ static void etnaviv_iommuv2_restore_nonsec(struct etnaviv_gpu *gpu,
|
||||
gpu_write(gpu, VIVS_MMUv2_CONTROL, VIVS_MMUv2_CONTROL_ENABLE);
|
||||
}
|
||||
|
||||
void etnaviv_iommuv2_update_pta_entry(struct etnaviv_iommu_context *context)
|
||||
{
|
||||
struct etnaviv_iommuv2_context *v2_context = to_v2_context(context);
|
||||
|
||||
context->global->v2.pta_cpu[v2_context->id] = v2_context->mtlb_dma |
|
||||
VIVS_MMUv2_CONFIGURATION_MODE_MODE4_K;
|
||||
}
|
||||
|
||||
static void etnaviv_iommuv2_restore_sec(struct etnaviv_gpu *gpu,
|
||||
struct etnaviv_iommu_context *context)
|
||||
{
|
||||
@@ -216,8 +224,7 @@ static void etnaviv_iommuv2_restore_sec(struct etnaviv_gpu *gpu,
|
||||
VIVS_MMUv2_SAFE_ADDRESS_CONFIG_SEC_SAFE_ADDR_HIGH(
|
||||
upper_32_bits(context->global->bad_page_dma)));
|
||||
|
||||
context->global->v2.pta_cpu[v2_context->id] = v2_context->mtlb_dma |
|
||||
VIVS_MMUv2_CONFIGURATION_MODE_MODE4_K;
|
||||
etnaviv_iommuv2_update_pta_entry(context);
|
||||
|
||||
/* trigger a PTA load through the FE */
|
||||
prefetch = etnaviv_buffer_config_pta(gpu, v2_context->id);
|
||||
@@ -241,6 +248,7 @@ unsigned short etnaviv_iommuv2_get_pta_id(struct etnaviv_iommu_context *context)
|
||||
|
||||
return v2_context->id;
|
||||
}
|
||||
|
||||
static void etnaviv_iommuv2_restore(struct etnaviv_gpu *gpu,
|
||||
struct etnaviv_iommu_context *context)
|
||||
{
|
||||
@@ -276,6 +284,8 @@ etnaviv_iommuv2_context_alloc(struct etnaviv_iommu_global *global)
|
||||
if (!v2_context)
|
||||
return NULL;
|
||||
|
||||
v2_context->id = 0;
|
||||
#if 0
|
||||
mutex_lock(&global->lock);
|
||||
v2_context->id = find_first_zero_bit(global->v2.pta_alloc,
|
||||
ETNAVIV_PTA_ENTRIES);
|
||||
@@ -286,6 +296,7 @@ etnaviv_iommuv2_context_alloc(struct etnaviv_iommu_global *global)
|
||||
goto out_free;
|
||||
}
|
||||
mutex_unlock(&global->lock);
|
||||
#endif
|
||||
|
||||
v2_context->mtlb_cpu = dma_alloc_wc(global->dev, SZ_4K,
|
||||
&v2_context->mtlb_dma, GFP_KERNEL);
|
||||
|
||||
@@ -80,10 +80,10 @@ static int etnaviv_iommu_map(struct etnaviv_iommu_context *context, u32 iova,
|
||||
return -EINVAL;
|
||||
|
||||
for_each_sgtable_dma_sg(sgt, sg, i) {
|
||||
u32 pa = sg_dma_address(sg) - sg->offset;
|
||||
phys_addr_t pa = sg_dma_address(sg) - sg->offset;
|
||||
size_t bytes = sg_dma_len(sg) + sg->offset;
|
||||
|
||||
VERB("map[%d]: %08x %08x(%zx)", i, iova, pa, bytes);
|
||||
VERB("map[%d]: %08x %pap(%zx)", i, iova, &pa, bytes);
|
||||
|
||||
ret = etnaviv_context_map(context, da, pa, bytes, prot);
|
||||
if (ret)
|
||||
@@ -92,6 +92,8 @@ static int etnaviv_iommu_map(struct etnaviv_iommu_context *context, u32 iova,
|
||||
da += bytes;
|
||||
}
|
||||
|
||||
context->flush_seq++;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
@@ -117,6 +119,8 @@ static void etnaviv_iommu_unmap(struct etnaviv_iommu_context *context, u32 iova,
|
||||
|
||||
da += bytes;
|
||||
}
|
||||
|
||||
context->flush_seq++;
|
||||
}
|
||||
|
||||
static void etnaviv_iommu_remove_mapping(struct etnaviv_iommu_context *context,
|
||||
@@ -124,11 +128,26 @@ static void etnaviv_iommu_remove_mapping(struct etnaviv_iommu_context *context,
|
||||
{
|
||||
struct etnaviv_gem_object *etnaviv_obj = mapping->object;
|
||||
|
||||
lockdep_assert_held(&context->lock);
|
||||
|
||||
etnaviv_iommu_unmap(context, mapping->vram_node.start,
|
||||
etnaviv_obj->sgt, etnaviv_obj->base.size);
|
||||
drm_mm_remove_node(&mapping->vram_node);
|
||||
}
|
||||
|
||||
void etnaviv_iommu_reap_mapping(struct etnaviv_vram_mapping *mapping)
|
||||
{
|
||||
struct etnaviv_iommu_context *context = mapping->context;
|
||||
|
||||
lockdep_assert_held(&context->lock);
|
||||
WARN_ON(mapping->use);
|
||||
|
||||
etnaviv_iommu_remove_mapping(context, mapping);
|
||||
etnaviv_iommu_context_put(mapping->context);
|
||||
mapping->context = NULL;
|
||||
list_del_init(&mapping->mmu_node);
|
||||
}
|
||||
|
||||
static int etnaviv_iommu_find_iova(struct etnaviv_iommu_context *context,
|
||||
struct drm_mm_node *node, size_t size)
|
||||
{
|
||||
@@ -196,10 +215,7 @@ static int etnaviv_iommu_find_iova(struct etnaviv_iommu_context *context,
|
||||
* this mapping.
|
||||
*/
|
||||
list_for_each_entry_safe(m, n, &list, scan_node) {
|
||||
etnaviv_iommu_remove_mapping(context, m);
|
||||
etnaviv_iommu_context_put(m->context);
|
||||
m->context = NULL;
|
||||
list_del_init(&m->mmu_node);
|
||||
etnaviv_iommu_reap_mapping(m);
|
||||
list_del_init(&m->scan_node);
|
||||
}
|
||||
|
||||
@@ -217,6 +233,44 @@ static int etnaviv_iommu_find_iova(struct etnaviv_iommu_context *context,
|
||||
static int etnaviv_iommu_insert_exact(struct etnaviv_iommu_context *context,
|
||||
struct drm_mm_node *node, size_t size, u64 va)
|
||||
{
|
||||
struct etnaviv_vram_mapping *m, *n;
|
||||
struct drm_mm_node *scan_node;
|
||||
LIST_HEAD(scan_list);
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&context->lock);
|
||||
|
||||
ret = drm_mm_insert_node_in_range(&context->mm, node, size, 0, 0, va,
|
||||
va + size, DRM_MM_INSERT_LOWEST);
|
||||
if (ret != -ENOSPC)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* When we can't insert the node, due to a existing mapping blocking
|
||||
* the address space, there are two possible reasons:
|
||||
* 1. Userspace genuinely messed up and tried to reuse address space
|
||||
* before the last job using this VMA has finished executing.
|
||||
* 2. The existing buffer mappings are idle, but the buffers are not
|
||||
* destroyed yet (likely due to being referenced by another context) in
|
||||
* which case the mappings will not be cleaned up and we must reap them
|
||||
* here to make space for the new mapping.
|
||||
*/
|
||||
|
||||
drm_mm_for_each_node_in_range(scan_node, &context->mm, va, va + size) {
|
||||
m = container_of(scan_node, struct etnaviv_vram_mapping,
|
||||
vram_node);
|
||||
|
||||
if (m->use)
|
||||
return -ENOSPC;
|
||||
|
||||
list_add(&m->scan_node, &scan_list);
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(m, n, &scan_list, scan_node) {
|
||||
etnaviv_iommu_reap_mapping(m);
|
||||
list_del_init(&m->scan_node);
|
||||
}
|
||||
|
||||
return drm_mm_insert_node_in_range(&context->mm, node, size, 0, 0, va,
|
||||
va + size, DRM_MM_INSERT_LOWEST);
|
||||
}
|
||||
@@ -241,6 +295,7 @@ int etnaviv_iommu_map_gem(struct etnaviv_iommu_context *context,
|
||||
iova = sg_dma_address(sgt->sgl) - memory_base;
|
||||
if (iova < 0x80000000 - sg_dma_len(sgt->sgl)) {
|
||||
mapping->iova = iova;
|
||||
mapping->context = etnaviv_iommu_context_get(context);
|
||||
list_add_tail(&mapping->mmu_node, &context->mappings);
|
||||
ret = 0;
|
||||
goto unlock;
|
||||
@@ -267,8 +322,8 @@ int etnaviv_iommu_map_gem(struct etnaviv_iommu_context *context,
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
mapping->context = etnaviv_iommu_context_get(context);
|
||||
list_add_tail(&mapping->mmu_node, &context->mappings);
|
||||
context->flush_seq++;
|
||||
unlock:
|
||||
mutex_unlock(&context->lock);
|
||||
|
||||
@@ -282,13 +337,19 @@ void etnaviv_iommu_unmap_gem(struct etnaviv_iommu_context *context,
|
||||
|
||||
mutex_lock(&context->lock);
|
||||
|
||||
/* Bail if the mapping has been reaped by another thread */
|
||||
if (!mapping->context) {
|
||||
mutex_unlock(&context->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
/* If the vram node is on the mm, unmap and remove the node */
|
||||
if (mapping->vram_node.mm == &context->mm)
|
||||
etnaviv_iommu_remove_mapping(context, mapping);
|
||||
|
||||
list_del(&mapping->mmu_node);
|
||||
context->flush_seq++;
|
||||
mutex_unlock(&context->lock);
|
||||
etnaviv_iommu_context_put(context);
|
||||
}
|
||||
|
||||
static void etnaviv_iommu_context_free(struct kref *kref)
|
||||
@@ -492,6 +553,9 @@ void etnaviv_iommu_global_fini(struct etnaviv_gpu *gpu)
|
||||
struct etnaviv_drm_private *priv = gpu->drm->dev_private;
|
||||
struct etnaviv_iommu_global *global = priv->mmu_global;
|
||||
|
||||
if (!global)
|
||||
return;
|
||||
|
||||
if (--global->use > 0)
|
||||
return;
|
||||
|
||||
|
||||
@@ -91,6 +91,7 @@ int etnaviv_iommu_map_gem(struct etnaviv_iommu_context *context,
|
||||
struct etnaviv_vram_mapping *mapping, u64 va);
|
||||
void etnaviv_iommu_unmap_gem(struct etnaviv_iommu_context *context,
|
||||
struct etnaviv_vram_mapping *mapping);
|
||||
void etnaviv_iommu_reap_mapping(struct etnaviv_vram_mapping *mapping);
|
||||
|
||||
int etnaviv_iommu_get_suballoc_va(struct etnaviv_iommu_context *ctx,
|
||||
struct etnaviv_vram_mapping *mapping,
|
||||
@@ -123,4 +124,6 @@ etnaviv_iommuv2_context_alloc(struct etnaviv_iommu_global *global);
|
||||
u32 etnaviv_iommuv2_get_mtlb_addr(struct etnaviv_iommu_context *context);
|
||||
unsigned short etnaviv_iommuv2_get_pta_id(struct etnaviv_iommu_context *context);
|
||||
|
||||
void etnaviv_iommuv2_update_pta_entry(struct etnaviv_iommu_context *context);
|
||||
|
||||
#endif /* __ETNAVIV_MMU_H__ */
|
||||
|
||||
@@ -106,8 +106,9 @@ static void etnaviv_sched_timedout_job(struct drm_sched_job *sched_job)
|
||||
*/
|
||||
dma_addr = gpu_read(gpu, VIVS_FE_DMA_ADDRESS);
|
||||
change = dma_addr - gpu->hangcheck_dma_addr;
|
||||
if (gpu->completed_fence != gpu->hangcheck_fence ||
|
||||
change < 0 || change > 16) {
|
||||
if (gpu->state == ETNA_GPU_STATE_RUNNING &&
|
||||
(gpu->completed_fence != gpu->hangcheck_fence ||
|
||||
change < 0 || change > 16)) {
|
||||
gpu->hangcheck_dma_addr = dma_addr;
|
||||
gpu->hangcheck_fence = gpu->completed_fence;
|
||||
goto out_no_timeout;
|
||||
@@ -118,7 +119,7 @@ static void etnaviv_sched_timedout_job(struct drm_sched_job *sched_job)
|
||||
|
||||
/* get the GPU back into the init state */
|
||||
etnaviv_core_dump(submit);
|
||||
etnaviv_gpu_recover_hang(gpu);
|
||||
etnaviv_gpu_recover_hang(submit);
|
||||
|
||||
drm_sched_resubmit_jobs(&gpu->sched);
|
||||
|
||||
@@ -146,14 +147,16 @@ static const struct drm_sched_backend_ops etnaviv_sched_ops = {
|
||||
int etnaviv_sched_push_job(struct drm_sched_entity *sched_entity,
|
||||
struct etnaviv_gem_submit *submit)
|
||||
{
|
||||
struct etnaviv_gpu *gpu = submit->gpu;
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
* Hold the fence lock across the whole operation to avoid jobs being
|
||||
* Hold the sched lock across the whole operation to avoid jobs being
|
||||
* pushed out of order with regard to their sched fence seqnos as
|
||||
* allocated in drm_sched_job_init.
|
||||
*/
|
||||
mutex_lock(&submit->gpu->fence_lock);
|
||||
mutex_lock(&gpu->sched_lock);
|
||||
|
||||
ret = drm_sched_job_init(&submit->sched_job, sched_entity,
|
||||
submit->ctx);
|
||||
@@ -161,9 +164,11 @@ int etnaviv_sched_push_job(struct drm_sched_entity *sched_entity,
|
||||
goto out_unlock;
|
||||
|
||||
submit->out_fence = dma_fence_get(&submit->sched_job.s_fence->finished);
|
||||
submit->out_fence_id = idr_alloc_cyclic(&submit->gpu->fence_idr,
|
||||
mutex_lock(&gpu->idr_lock);
|
||||
submit->out_fence_id = idr_alloc_cyclic(&gpu->fence_idr,
|
||||
submit->out_fence, 0,
|
||||
INT_MAX, GFP_KERNEL);
|
||||
mutex_unlock(&gpu->idr_lock);
|
||||
if (submit->out_fence_id < 0) {
|
||||
drm_sched_job_cleanup(&submit->sched_job);
|
||||
ret = -ENOMEM;
|
||||
@@ -176,7 +181,7 @@ int etnaviv_sched_push_job(struct drm_sched_entity *sched_entity,
|
||||
drm_sched_entity_push_job(&submit->sched_job, sched_entity);
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&submit->gpu->fence_lock);
|
||||
mutex_unlock(&gpu->sched_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
img_basedir := drivers/gpu/drm/img-rogue
|
||||
img_basedir := $(srctree)/$(src)
|
||||
include $(img_basedir)/config_kernel.mk
|
||||
|
||||
obj-$(CONFIG_DRM_POWERVR_ROGUE) += pvrsrvkm.o
|
||||
|
||||
@@ -519,4 +519,13 @@ config DRM_PANEL_HX8394
|
||||
Say Y if you want to enable support for panels based on the
|
||||
HX8394 controller.
|
||||
|
||||
config DRM_PANEL_JADARD_JD9365DA_H3
|
||||
tristate "Jadard JD9365DA-H3 WXGA DSI panel"
|
||||
depends on OF
|
||||
depends on DRM_MIPI_DSI
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
help
|
||||
Say Y here if you want to enable support for Jadard JD9365DA-H3
|
||||
WXGA MIPI DSI panel. The panel support TFT dot matrix LCD with
|
||||
800RGBx1280 dots at maximum.
|
||||
endmenu
|
||||
|
||||
@@ -55,3 +55,4 @@ obj-$(CONFIG_DRM_PANEL_VISIONOX_RM69299) += panel-visionox-rm69299.o
|
||||
obj-$(CONFIG_DRM_PANEL_XINPENG_XPP055C272) += panel-xinpeng-xpp055c272.o
|
||||
obj-$(CONFIG_DRM_PANEL_ILI9881D) += panel-ili9881d.o
|
||||
obj-$(CONFIG_DRM_PANEL_HX8394) += panel-himax8394.o
|
||||
obj-$(CONFIG_DRM_PANEL_JADARD_JD9365DA_H3) += panel-jadard-jd9365da-h3.o
|
||||
|
||||
356
drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c
Normal file
356
drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c
Normal file
@@ -0,0 +1,356 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (c) 2019 Radxa Limited
|
||||
* Copyright (c) 2022 Edgeble AI Technologies Pvt. Ltd.
|
||||
*
|
||||
* Author:
|
||||
* - Jagan Teki <jagan@amarulasolutions.com>
|
||||
* - Stephen Chen <stephen@radxa.com>
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
#include <drm/drm_modes.h>
|
||||
#include <drm/drm_panel.h>
|
||||
|
||||
#include <video/mipi_display.h>
|
||||
|
||||
struct jadard_panel_desc {
|
||||
const struct drm_display_mode *display_mode;
|
||||
|
||||
unsigned long mode_flags;
|
||||
enum mipi_dsi_pixel_format format;
|
||||
unsigned int lanes;
|
||||
// const struct jadard_panel_cmd *on_cmds;
|
||||
unsigned int on_cmds_num;
|
||||
};
|
||||
|
||||
struct panel_info {
|
||||
struct drm_panel base;
|
||||
struct mipi_dsi_device *link;
|
||||
const struct jadard_panel_desc *desc;
|
||||
|
||||
struct gpio_desc *reset;
|
||||
struct regulator *hsvcc;
|
||||
struct regulator *vspn3v3;
|
||||
|
||||
bool prepared;
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
static inline struct panel_info *to_panel_info(struct drm_panel *panel)
|
||||
{
|
||||
return container_of(panel, struct panel_info, base);
|
||||
}
|
||||
|
||||
//static int jadard_send_mipi_cmds(struct drm_panel *panel, const struct jadard_panel_cmd *cmds)
|
||||
//{
|
||||
// struct panel_info *pinfo = to_panel_info(panel);
|
||||
// unsigned int i = 0;
|
||||
// int err;
|
||||
//
|
||||
// for (i = 0; i < pinfo->desc->on_cmds_num; i++) {
|
||||
// err = mipi_dsi_dcs_write_buffer(pinfo->link, &(cmds[i].cmddata[0]), cmds[i].cmdlen);
|
||||
// if (err < 0)
|
||||
// return err;
|
||||
// }
|
||||
//
|
||||
// return 0;
|
||||
//}
|
||||
|
||||
static int jadard_disable(struct drm_panel *panel)
|
||||
{
|
||||
struct panel_info *pinfo = to_panel_info(panel);
|
||||
int err;
|
||||
|
||||
if (!pinfo->enabled)
|
||||
return 0;
|
||||
|
||||
err = mipi_dsi_dcs_set_display_off(pinfo->link);
|
||||
if (err < 0) {
|
||||
dev_err(panel->dev, "failed to set display off: %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
pinfo->enabled = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int jadard_unprepare(struct drm_panel *panel)
|
||||
{
|
||||
struct panel_info *pinfo = to_panel_info(panel);
|
||||
int err;
|
||||
|
||||
if (!pinfo->prepared)
|
||||
return 0;
|
||||
|
||||
err = mipi_dsi_dcs_set_display_off(pinfo->link);
|
||||
if (err < 0)
|
||||
dev_err(panel->dev, "failed to set display off: %d\n", err);
|
||||
|
||||
err = mipi_dsi_dcs_enter_sleep_mode(pinfo->link);
|
||||
if (err < 0)
|
||||
dev_err(panel->dev, "failed to enter sleep mode: %d\n", err);
|
||||
|
||||
/* sleep_mode_delay: 1ms - 2ms */
|
||||
usleep_range(1000, 2000);
|
||||
|
||||
gpiod_set_value(pinfo->reset, 1);
|
||||
regulator_disable(pinfo->hsvcc);
|
||||
regulator_disable(pinfo->vspn3v3);
|
||||
|
||||
pinfo->prepared = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int jadard_prepare(struct drm_panel *panel)
|
||||
{
|
||||
struct panel_info *pinfo = to_panel_info(panel);
|
||||
int ret;
|
||||
|
||||
if (pinfo->prepared)
|
||||
return 0;
|
||||
gpiod_set_value(pinfo->reset, 0);
|
||||
|
||||
/* Power the panel */
|
||||
ret = regulator_enable(pinfo->hsvcc);
|
||||
if (ret) {
|
||||
dev_err(pinfo->base.dev, "Failed to enable hsvcc supply: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
usleep_range(1000, 2000);
|
||||
ret = regulator_enable(pinfo->vspn3v3);
|
||||
if (ret) {
|
||||
dev_err(pinfo->base.dev, "Failed to enable vspn3v3 supply: %d\n", ret);
|
||||
goto fail;
|
||||
}
|
||||
usleep_range(5000, 6000);
|
||||
|
||||
gpiod_set_value(pinfo->reset, 1);
|
||||
msleep(180);
|
||||
|
||||
pinfo->prepared = true;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
gpiod_set_value(pinfo->reset, 1);
|
||||
regulator_disable(pinfo->hsvcc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int jadard_enable(struct drm_panel *panel)
|
||||
{
|
||||
struct panel_info *pinfo = to_panel_info(panel);
|
||||
int ret;
|
||||
|
||||
if (pinfo->enabled)
|
||||
return 0;
|
||||
|
||||
ret = mipi_dsi_dcs_exit_sleep_mode(pinfo->link);
|
||||
if (ret < 0) {
|
||||
dev_err(panel->dev, "failed to exit sleep mode: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
msleep(120);
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_on(pinfo->link);
|
||||
if (ret < 0) {
|
||||
dev_err(panel->dev, "failed to set display on: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
pinfo->enabled = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int jadard_get_modes(struct drm_panel *panel,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct panel_info *pinfo = to_panel_info(panel);
|
||||
const struct drm_display_mode *m = pinfo->desc->display_mode;
|
||||
struct drm_display_mode *mode;
|
||||
|
||||
mode = drm_mode_duplicate(connector->dev, m);
|
||||
if (!mode) {
|
||||
dev_err(pinfo->base.dev, "failed to add mode %ux%u@%u\n",
|
||||
m->hdisplay, m->vdisplay, drm_mode_vrefresh(m));
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
drm_mode_set_name(mode);
|
||||
|
||||
mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
|
||||
drm_mode_probed_add(connector, mode);
|
||||
|
||||
connector->display_info.width_mm = mode->width_mm;
|
||||
connector->display_info.height_mm = mode->height_mm;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct drm_panel_funcs panel_funcs = {
|
||||
.disable = jadard_disable,
|
||||
.unprepare = jadard_unprepare,
|
||||
.prepare = jadard_prepare,
|
||||
.enable = jadard_enable,
|
||||
.get_modes = jadard_get_modes,
|
||||
};
|
||||
|
||||
static const struct drm_display_mode jadard_default_mode = {
|
||||
.clock = 76000,
|
||||
.hdisplay = 800,
|
||||
.hsync_start = 800 + 32,
|
||||
.hsync_end = 800 + 32 + 8,
|
||||
.htotal = 800 + 32 + 8 + 32,
|
||||
|
||||
.vdisplay = 1280,
|
||||
.vsync_start = 1280 + 16,
|
||||
.vsync_end = 1280 + 16 + 8,
|
||||
.vtotal = 1280 + 16 + 8 + 16,
|
||||
|
||||
.width_mm = 62,
|
||||
.height_mm = 110,
|
||||
.flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
|
||||
};
|
||||
|
||||
|
||||
static const struct jadard_panel_desc jadard_panel_desc = {
|
||||
.display_mode = &jadard_default_mode,
|
||||
.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_VIDEO_BURST,
|
||||
.format = MIPI_DSI_FMT_RGB888,
|
||||
.lanes = 4,
|
||||
};
|
||||
|
||||
static const struct of_device_id panel_of_match[] = {
|
||||
{
|
||||
.compatible = "jadard,jd9365da-h3",
|
||||
.data = &jadard_panel_desc,
|
||||
},
|
||||
{
|
||||
/* sentinel */
|
||||
}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, panel_of_match);
|
||||
|
||||
static int jd9365da_panel_add(struct panel_info *pinfo)
|
||||
{
|
||||
struct device *dev = &pinfo->link->dev;
|
||||
int ret;
|
||||
|
||||
pinfo->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(pinfo->reset))
|
||||
return dev_err_probe(dev, PTR_ERR(pinfo->reset),
|
||||
"Couldn't get our reset GPIO\n");
|
||||
|
||||
pinfo->hsvcc = devm_regulator_get(dev, "hsvcc");
|
||||
if (IS_ERR(pinfo->hsvcc))
|
||||
return dev_err_probe(dev, PTR_ERR(pinfo->hsvcc),
|
||||
"Failed to request hsvcc regulator\n");
|
||||
|
||||
pinfo->vspn3v3 = devm_regulator_get(dev, "vspn3v3");
|
||||
if (IS_ERR(pinfo->vspn3v3))
|
||||
return dev_err_probe(dev, PTR_ERR(pinfo->vspn3v3),
|
||||
"Failed to request vspn3v3 regulator\n");
|
||||
|
||||
drm_panel_init(&pinfo->base, dev, &panel_funcs,
|
||||
DRM_MODE_CONNECTOR_DSI);
|
||||
|
||||
ret = drm_panel_of_backlight(&pinfo->base);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
drm_panel_add(&pinfo->base);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int jadard_dsi_probe(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct panel_info *pinfo;
|
||||
const struct jadard_panel_desc *desc;
|
||||
int err;
|
||||
|
||||
pinfo = devm_kzalloc(&dsi->dev, sizeof(*pinfo), GFP_KERNEL);
|
||||
if (!pinfo)
|
||||
return -ENOMEM;
|
||||
|
||||
desc = of_device_get_match_data(&dsi->dev);
|
||||
dsi->mode_flags = desc->mode_flags;
|
||||
dsi->format = desc->format;
|
||||
dsi->lanes = desc->lanes;
|
||||
pinfo->desc = desc;
|
||||
|
||||
pinfo->link = dsi;
|
||||
mipi_dsi_set_drvdata(dsi, pinfo);
|
||||
|
||||
err = jd9365da_panel_add(pinfo);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = mipi_dsi_attach(dsi);
|
||||
if (err < 0)
|
||||
drm_panel_remove(&pinfo->base);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int jadard_dsi_remove(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct panel_info *pinfo = mipi_dsi_get_drvdata(dsi);
|
||||
int err;
|
||||
|
||||
err = jadard_disable(&pinfo->base);
|
||||
if (err < 0)
|
||||
dev_err(&dsi->dev, "failed to disable panel: %d\n", err);
|
||||
|
||||
err = jadard_unprepare(&pinfo->base);
|
||||
if (err < 0)
|
||||
dev_err(&dsi->dev, "failed to unprepare panel: %d\n", err);
|
||||
|
||||
err = mipi_dsi_detach(dsi);
|
||||
if (err < 0)
|
||||
dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err);
|
||||
|
||||
drm_panel_remove(&pinfo->base);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void jd9365da_panel_shutdown(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct panel_info *pinfo = mipi_dsi_get_drvdata(dsi);
|
||||
|
||||
jadard_disable(&pinfo->base);
|
||||
jadard_unprepare(&pinfo->base);
|
||||
}
|
||||
|
||||
static struct mipi_dsi_driver jadard_driver = {
|
||||
.driver = {
|
||||
.name = "jadard-jd9365da",
|
||||
.of_match_table = panel_of_match,
|
||||
},
|
||||
.probe = jadard_dsi_probe,
|
||||
.remove = jadard_dsi_remove,
|
||||
.shutdown = jd9365da_panel_shutdown,
|
||||
};
|
||||
module_mipi_dsi_driver(jadard_driver);
|
||||
|
||||
MODULE_AUTHOR("Jagan Teki <jagan@edgeble.ai>");
|
||||
MODULE_AUTHOR("Stephen Chen <stephen@radxa.com>");
|
||||
MODULE_DESCRIPTION("Jadard JD9365DA-H3 WXGA DSI panel");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -745,8 +745,8 @@ static void update_cursor_plane(struct vs_dc *dc, struct vs_plane *plane)
|
||||
struct dc_hw_cursor cursor;
|
||||
|
||||
cursor.address = plane->dma_addr[0];
|
||||
cursor.x = state->crtc_x;
|
||||
cursor.y = state->crtc_y;
|
||||
cursor.x = state->crtc_x + drm_fb->hot_x;
|
||||
cursor.y = state->crtc_y + drm_fb->hot_y;
|
||||
cursor.hot_x = drm_fb->hot_x;
|
||||
cursor.hot_y = drm_fb->hot_y;
|
||||
cursor.display_id = to_vs_display_id(dc, state->crtc);
|
||||
|
||||
@@ -641,6 +641,16 @@ static struct phy_driver realtek_drvs[] = {
|
||||
.resume = rtl821x_resume,
|
||||
.read_page = rtl821x_read_page,
|
||||
.write_page = rtl821x_write_page,
|
||||
}, {
|
||||
PHY_ID_MATCH_EXACT(0x001cc878),
|
||||
.name = "RTL8211F-VD Gigabit Ethernet",
|
||||
.config_init = &rtl8211f_config_init,
|
||||
.ack_interrupt = &rtl8211f_ack_interrupt,
|
||||
.config_intr = &rtl8211f_config_intr,
|
||||
.suspend = genphy_suspend,
|
||||
.resume = rtl821x_resume,
|
||||
.read_page = rtl821x_read_page,
|
||||
.write_page = rtl821x_write_page,
|
||||
}, {
|
||||
.name = "Generic FE-GE Realtek PHY",
|
||||
.match_phy_device = rtlgen_match_phy_device,
|
||||
|
||||
@@ -49,6 +49,8 @@ source "drivers/net/wireless/ti/Kconfig"
|
||||
source "drivers/net/wireless/zydas/Kconfig"
|
||||
source "drivers/net/wireless/quantenna/Kconfig"
|
||||
source "drivers/net/wireless/rtl8723ds/Kconfig"
|
||||
source "drivers/net/wireless/bcmdhd.101.10.361.x/Kconfig"
|
||||
source "drivers/net/wireless/aic8800/Kconfig"
|
||||
|
||||
config PCMCIA_RAYCS
|
||||
tristate "Aviator/Raytheon 2.4GHz wireless support"
|
||||
|
||||
@@ -31,3 +31,7 @@ obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o
|
||||
|
||||
obj-$(CONFIG_VIRT_WIFI) += virt_wifi.o
|
||||
obj-$(CONFIG_RTL8723DS) += rtl8723ds/
|
||||
|
||||
obj-$(CONFIG_BCMDHD) += bcmdhd.101.10.361.x/
|
||||
|
||||
obj-$(CONFIG_AIC_WLAN_SUPPORT) += aic8800/
|
||||
|
||||
18
drivers/net/wireless/aic8800/Kconfig
Normal file
18
drivers/net/wireless/aic8800/Kconfig
Normal file
@@ -0,0 +1,18 @@
|
||||
config AIC_WLAN_SUPPORT
|
||||
bool "AIC wireless Support"
|
||||
default n
|
||||
help
|
||||
This is support for aic wireless chip.
|
||||
|
||||
config AIC_FW_PATH
|
||||
depends on AIC_WLAN_SUPPORT
|
||||
string "Firmware & config file path"
|
||||
#default "/vendor/etc/firmware"
|
||||
default "/lib/firmware/aic8800"
|
||||
help
|
||||
Path to the firmware & config file.
|
||||
|
||||
if AIC_WLAN_SUPPORT
|
||||
source "drivers/net/wireless/aic8800/aic8800_fdrv/Kconfig"
|
||||
source "drivers/net/wireless/aic8800/aic8800_btlpm/Kconfig"
|
||||
endif
|
||||
70
drivers/net/wireless/aic8800/Makefile
Normal file
70
drivers/net/wireless/aic8800/Makefile
Normal file
@@ -0,0 +1,70 @@
|
||||
obj-$(CONFIG_AIC8800_BTLPM_SUPPORT) += aic8800_btlpm/
|
||||
obj-$(CONFIG_AIC8800_WLAN_SUPPORT) += aic8800_fdrv/
|
||||
obj-$(CONFIG_AIC_WLAN_SUPPORT) += aic8800_bsp/
|
||||
|
||||
# Platform support list
|
||||
CONFIG_PLATFORM_ROCKCHIP ?= n
|
||||
CONFIG_PLATFORM_ALLWINNER ?= n
|
||||
CONFIG_PLATFORM_AMLOGIC ?= n
|
||||
CONFIG_PLATFORM_UBUNTU ?= y
|
||||
|
||||
ifeq ($(CONFIG_PLATFORM_ROCKCHIP), y)
|
||||
#KDIR = /home/yaya/E/Rockchip/3229/Android7/RK3229_ANDROID7.1_v1.01_20170914/rk3229_Android7.1_v1.01_xml0914/kernel
|
||||
#ARCH = arm
|
||||
#CROSS_COMPILE = /home/yaya/E/Rockchip/3229/Android7/RK3229_ANDROID7.1_v1.01_20170914/rk3229_Android7.1_v1.01_xml0914/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-
|
||||
KDIR = /home/yaya/E/Rockchip/3229/Android9/rk3229_android9.0_box/kernel
|
||||
ARCH = arm
|
||||
CROSS_COMPILE = /home/yaya/E/Rockchip/3229/Android9/rk3229_android9.0_box/prebuilts/gcc/linux-x86/arm/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-
|
||||
#KDIR = /home/yaya/E/Rockchip/3399/rk3399-android-10/kernel
|
||||
#ARCH = arm64
|
||||
#CROSS_COMPILE = /home/yaya/E/Rockchip/3399/rk3399-android-10/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
|
||||
ccflags-y += -DANDROID_PLATFORM
|
||||
ccflags-y += -DCONFIG_PLATFORM_ROCKCHIP
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_PLATFORM_ALLWINNER), y)
|
||||
KDIR = /home/yaya/E/Allwinner/R818/R818/AndroidQ/lichee/kernel/linux-4.9
|
||||
ARCH = arm64
|
||||
CROSS_COMPILE = /home/yaya/E/Allwinner/R818/R818/AndroidQ/lichee/out/gcc-linaro-5.3.1-2016.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
|
||||
ccflags-y += -DANDROID_PLATFORM
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_PLATFORM_AMLOGIC), y)
|
||||
ccflags-y += -DANDROID_PLATFORM
|
||||
ARCH = arm
|
||||
CROSS_COMPILE = /home/yaya/D/Workspace/CyberQuantum/JinHaoYue/amls905x3/SDK/20191101-0tt-asop/android9.0/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/bin/arm-linux-androidkernel-
|
||||
KDIR = /home/yaya/D/Workspace/CyberQuantum/JinHaoYue/amls905x3/SDK/20191101-0tt-asop/android9.0/out/target/product/u202/obj/KERNEL_OBJ/
|
||||
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_PLATFORM_UBUNTU), y)
|
||||
KDIR = /lib/modules/$(shell uname -r)/build
|
||||
PWD = $(shell pwd)
|
||||
KVER = $(shell uname -r)
|
||||
MODDESTDIR = /lib/modules/$(KVER)/kernel/drivers/net/wireless/aic8800
|
||||
ARCH = x86_64
|
||||
CROSS_COMPILE =
|
||||
endif
|
||||
all: modules
|
||||
modules:
|
||||
make -C $(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
|
||||
|
||||
install:
|
||||
mkdir -p $(MODDESTDIR)
|
||||
install -p -m 644 aic8800_bsp/aic8800_bsp.ko $(MODDESTDIR)/
|
||||
install -p -m 644 aic8800_fdrv/aic8800_fdrv.ko $(MODDESTDIR)/
|
||||
install -p -m 644 aic8800_btlpm/aic8800_btlpm.ko $(MODDESTDIR)/
|
||||
/sbin/depmod -a ${KVER}
|
||||
|
||||
uninstall:
|
||||
rm -rfv $(MODDESTDIR)/aic8800_bsp.ko
|
||||
rm -rfv $(MODDESTDIR)/aic8800_fdrv.ko
|
||||
rm -rfv $(MODDESTDIR)/aic8800_btlpm.ko
|
||||
/sbin/depmod -a ${KVER}
|
||||
|
||||
clean:
|
||||
cd aic8800_bsp/;make clean;cd ..
|
||||
cd aic8800_fdrv/;make clean;cd ..
|
||||
cd aic8800_btlpm/;make clean;cd ..
|
||||
rm -rf modules.order Module.symvers .tmp_versions/
|
||||
|
||||
141
drivers/net/wireless/aic8800/aic8800_bsp/Makefile
Normal file
141
drivers/net/wireless/aic8800/aic8800_bsp/Makefile
Normal file
@@ -0,0 +1,141 @@
|
||||
CONFIG_SDIO_SUPPORT := y
|
||||
CONFIG_SDIO_PWRCTRL := y
|
||||
#CONFIG_AIC_FW_PATH = "/vendor/etc/firmware"
|
||||
CONFIG_AIC_FW_PATH = "/lib/firmware/aic8800"
|
||||
export CONFIG_AIC_FW_PATH
|
||||
ccflags-y += -DCONFIG_AIC_FW_PATH=\"$(CONFIG_AIC_FW_PATH)\"
|
||||
|
||||
MODULE_NAME := aic8800_bsp
|
||||
ifeq ($(CONFIG_SDIO_SUPPORT), y)
|
||||
ccflags-y += -DAICWF_SDIO_SUPPORT
|
||||
ccflags-$(CONFIG_SDIO_PWRCTRL) += -DCONFIG_SDIO_PWRCTRL
|
||||
endif
|
||||
|
||||
CONFIG_GPIO_WAKEUP = n
|
||||
CONFIG_LINK_DET_5G = y
|
||||
CONFIG_MCU_MESSAGE = n
|
||||
CONFIG_FIRMWARE_ARRAY = n
|
||||
# Need to set fw path in BOARD_KERNEL_CMDLINE
|
||||
CONFIG_USE_FW_REQUEST = n
|
||||
CONFIG_FDRV_NO_REG_SDIO = n
|
||||
CONFIG_VRF_DCDC_MODE = y
|
||||
CONFIG_OOB = n
|
||||
CONFIG_PREALLOC_TXQ = y
|
||||
CONFIG_ONE_TXQ = n
|
||||
CONFIG_DPD = n
|
||||
CONFIG_FORCE_DPD_CALIB = n
|
||||
|
||||
ccflags-$(CONFIG_GPIO_WAKEUP) += -DCONFIG_GPIO_WAKEUP
|
||||
ccflags-$(CONFIG_LINK_DET_5G) += -DCONFIG_LINK_DET_5G
|
||||
ccflags-$(CONFIG_MCU_MESSAGE) += -DCONFIG_MCU_MESSAGE
|
||||
ccflags-$(CONFIG_FIRMWARE_ARRAY) += -DCONFIG_FIRMWARE_ARRAY
|
||||
ccflags-$(CONFIG_USE_FW_REQUEST) += -DCONFIG_USE_FW_REQUEST
|
||||
ccflags-$(CONFIG_FDRV_NO_REG_SDIO) += -DCONFIG_FDRV_NO_REG_SDIO
|
||||
ccflags-$(CONFIG_VRF_DCDC_MODE) += -DCONFIG_VRF_DCDC_MODE
|
||||
ccflags-$(CONFIG_OOB) += -DCONFIG_OOB
|
||||
ccflags-$(CONFIG_PREALLOC_TXQ) += -DCONFIG_PREALLOC_TXQ
|
||||
ccflags-$(CONFIG_ONE_TXQ) += -DCONFIG_ONE_TXQ
|
||||
ccflags-$(CONFIG_DPD) += -DCONFIG_DPD
|
||||
ccflags-$(CONFIG_FORCE_DPD_CALIB) += -DCONFIG_FORCE_DPD_CALIB -DCONFIG_DPD
|
||||
|
||||
obj-m := $(MODULE_NAME).o
|
||||
$(MODULE_NAME)-y := \
|
||||
aic8800dc_compat.o \
|
||||
aic8800d80_compat.o \
|
||||
aic_bsp_main.o \
|
||||
aic_bsp_driver.o \
|
||||
aicsdio.o \
|
||||
aicsdio_txrxif.o \
|
||||
md5.o
|
||||
|
||||
$(MODULE_NAME)-$(CONFIG_PREALLOC_TXQ) += aicwf_txq_prealloc.o
|
||||
|
||||
ifeq ($(CONFIG_FIRMWARE_ARRAY),y)
|
||||
$(MODULE_NAME)-y += aicwf_firmware_array.o
|
||||
endif
|
||||
|
||||
# Platform support list
|
||||
CONFIG_PLATFORM_ROCKCHIP ?= n
|
||||
CONFIG_PLATFORM_ALLWINNER ?=n
|
||||
CONFIG_PLATFORM_INGENIC_T20 ?= n
|
||||
CONFIG_PLATFORM_AMLOGIC ?= n
|
||||
CONFIG_PLATFORM_UBUNTU ?= y
|
||||
|
||||
ifeq ($(CONFIG_PLATFORM_ROCKCHIP), y)
|
||||
ccflags-$(CONFIG_PLATFORM_ROCKCHIP) += -DCONFIG_PLATFORM_ROCKCHIP
|
||||
#KDIR ?= /home/yaya/E/Rockchip/3399/rk3399-android-10/kernel
|
||||
#ARCH ?= arm64
|
||||
#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3399/rk3399-android-10/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
|
||||
#KDIR ?= /home/yaya/E/Rockchip/3288/Android10/kernel/kernel/
|
||||
#ARCH ?= arm
|
||||
#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3288/Android10/tool/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-
|
||||
#KDIR ?= /home/yaya/E/Rockchip/3229/Android7/RK3229_ANDROID7.1_v1.01_20170914/rk3229_Android7.1_v1.01_xml0914/kernel
|
||||
#ARCH ?= arm
|
||||
#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3229/Android7/RK3229_ANDROID7.1_v1.01_20170914/rk3229_Android7.1_v1.01_xml0914/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-
|
||||
#KDIR ?= /home/yaya/E/Rockchip/3229/Android9/rk3229_android9.0_box/kernel
|
||||
#ARCH ?= arm
|
||||
#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3229/Android9/rk3229_android9.0_box/prebuilts/gcc/linux-x86/arm/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-
|
||||
#KDIR ?= /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/kernel
|
||||
#KDIR ?= /home/yaya/E/Rockchip/3566/oudu/kernel
|
||||
#KDIR ?= /home/yaya/E/Rockchip/3566/shengteng/kernel
|
||||
#ARCH ?= arm64
|
||||
#CROSS_COMPILE ?= ~/E/Rockchip/3566/Android11/rk3566_rk3568_android11_oranth/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
|
||||
#KDIR ?= /home/yaya/E/Rockchip/3328/Android9/SDK/kernel/
|
||||
#ARCH ?= arm64
|
||||
#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3328/Android9/SDK/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
|
||||
KDIR ?= /home/yaya/E/Rockchip/3566/firefly/Android11.0/Firefly-RK356X_Android11.0_git_20210824/RK356X_Android11.0/kernel
|
||||
ARCH ?= arm64
|
||||
CROSS_COMPILE ?= /home/yaya/E/Rockchip/3566/Android11/rk3566_rk3568_android11_oranth/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_PLATFORM_ALLWINNER), y)
|
||||
ccflags-$(CONFIG_PLATFORM_ALLWINNER) += -DCONFIG_PLATFORM_ALLWINNER
|
||||
#KDIR ?= /home/yaya/E/Allwinner/A133/a133-sdk/android/longan/out/kernel/build/
|
||||
#ARCH ?= arm64
|
||||
#CROSS_COMPILE ?= /home/yaya/E/Allwinner/A133/a133-sdk/android/longan/out/gcc-linaro-5.3.1-2016.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
|
||||
KDIR ?= /home/yaya/E/Allwinner/r818/Android10/lichee/kernel/linux-4.9/
|
||||
ARCH ?= arm64
|
||||
CROSS_COMPILE ?= /home/yaya/E/Allwinner/r818/Android10/android/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android-
|
||||
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_PLATFORM_INGENIC_T20), y)
|
||||
KDIR ?= /home/yaya/E/T40/kernel
|
||||
ARCH ?= mips
|
||||
CROSS_COMPILE ?= /home/yaya/E/T40/mips-linux-gnu-ingenic-gcc7.2.0-glibc2.29-fp64/bin/mips-linux-gnu-
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_PLATFORM_AMLOGIC), y)
|
||||
ccflags-$(CONFIG_PLATFORM_AMLOGIC) += -DCONFIG_PLATFORM_AMLOGIC
|
||||
KDIR ?= /home/aiden/D1/SDK/Amlogic/905x3_a9/android9.0/out/target/product/u202/obj/KERNEL_OBJ/
|
||||
ARCH ?= arm
|
||||
CROSS_COMPILE ?= /home/aiden/D1/SDK/Amlogic/905x3_a9/android9.0/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/bin/arm-linux-androideabi-
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_PLATFORM_UBUNTU), y)
|
||||
ccflags-$(CONFIG_PLATFORM_UBUNTU) += -DCONFIG_PLATFORM_UBUNTU
|
||||
KDIR ?= /lib/modules/$(shell uname -r)/build
|
||||
PWD ?= $(shell pwd)
|
||||
KVER ?= $(shell uname -r)
|
||||
MODDESTDIR ?= /lib/modules/$(KVER)/kernel/drivers/net/wireless/
|
||||
ARCH ?= x86_64
|
||||
CROSS_COMPILE ?=
|
||||
endif
|
||||
|
||||
|
||||
all: modules
|
||||
modules:
|
||||
make -C $(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
|
||||
|
||||
install:
|
||||
mkdir -p $(MODDESTDIR)
|
||||
install -p -m 644 $(MODULE_NAME).ko $(MODDESTDIR)
|
||||
/sbin/depmod -a ${KVER}
|
||||
|
||||
uninstall:
|
||||
rm -rfv $(MODDESTDIR)/$(MODULE_NAME).ko
|
||||
/sbin/depmod -a ${KVER}
|
||||
|
||||
clean:
|
||||
rm -rf *.o *.ko *.o.* *.mod.* modules.* Module.* .a* .o* .*.o.* *.mod .tmp* .cache.mk built-in.a
|
||||
|
||||
200
drivers/net/wireless/aic8800/aic8800_bsp/aic8800d80_compat.c
Normal file
200
drivers/net/wireless/aic8800/aic8800_bsp/aic8800d80_compat.c
Normal file
@@ -0,0 +1,200 @@
|
||||
#include "aic8800d80_compat.h"
|
||||
#include "aic_bsp_driver.h"
|
||||
|
||||
extern struct aicbsp_info_t aicbsp_info;
|
||||
extern int adap_test;
|
||||
|
||||
typedef u32 (*array2_tbl_t)[2];
|
||||
|
||||
#define AIC_PATCH_MAGIG_NUM 0x48435450 // "PTCH"
|
||||
#define AIC_PATCH_MAGIG_NUM_2 0x50544348 // "HCTP"
|
||||
#define AIC_PATCH_BLOCK_MAX 4
|
||||
|
||||
typedef struct {
|
||||
uint32_t magic_num;
|
||||
uint32_t pair_start;
|
||||
uint32_t magic_num_2;
|
||||
uint32_t pair_count;
|
||||
uint32_t block_dst[AIC_PATCH_BLOCK_MAX];
|
||||
uint32_t block_src[AIC_PATCH_BLOCK_MAX];
|
||||
uint32_t block_size[AIC_PATCH_BLOCK_MAX]; // word count
|
||||
} aic_patch_t;
|
||||
|
||||
#define AIC_PATCH_OFST(mem) ((size_t) &((aic_patch_t *)0)->mem)
|
||||
#define AIC_PATCH_ADDR(mem) ((u32)(aic_patch_str_base + AIC_PATCH_OFST(mem)))
|
||||
|
||||
u32 aicbsp_syscfg_tbl_8800d80[][2] = {
|
||||
};
|
||||
|
||||
int aicbsp_system_config_8800d80(struct aic_sdio_dev *sdiodev)
|
||||
{
|
||||
int syscfg_num = sizeof(aicbsp_syscfg_tbl_8800d80) / sizeof(u32) / 2;
|
||||
int ret, cnt;
|
||||
for (cnt = 0; cnt < syscfg_num; cnt++) {
|
||||
ret = rwnx_send_dbg_mem_write_req(sdiodev, aicbsp_syscfg_tbl_8800d80[cnt][0], aicbsp_syscfg_tbl_8800d80[cnt][1]);
|
||||
if (ret) {
|
||||
printk("%x write fail: %d\n", aicbsp_syscfg_tbl_8800d80[cnt][0], ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
u32 adaptivity_patch_tbl_8800d80[][2] = {
|
||||
{0x000C, 0x0000320A}, //linkloss_thd
|
||||
{0x009C, 0x00000000}, //ac_param_conf
|
||||
{0x0168, 0x00010000}, //tx_adaptivity_en
|
||||
};
|
||||
|
||||
u32 patch_tbl_8800d80[][2] = {
|
||||
#ifdef USE_5G
|
||||
{0x00b4, 0xf3010001},
|
||||
#else
|
||||
{0x00b4, 0xf3010000},
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef CONFIG_OOB
|
||||
// for 8800d40/d80 map data1 isr to gpiob1
|
||||
u32 gpio_cfg_tbl_8800d40d80[][2] = {
|
||||
{0x40504084, 0x00000006},
|
||||
{0x40500040, 0x00000000},
|
||||
{0x40100030, 0x00000001},
|
||||
{0x40241020, 0x00000001},
|
||||
{0x40240030, 0x00000004},
|
||||
{0x40240020, 0x03020700},
|
||||
};
|
||||
#endif
|
||||
|
||||
int aicwifi_sys_config_8800d80(struct aic_sdio_dev *sdiodev)
|
||||
{
|
||||
#ifdef CONFIG_OOB
|
||||
int ret, cnt;
|
||||
int gpiocfg_num = sizeof(gpio_cfg_tbl_8800d40d80) / sizeof(u32) / 2;
|
||||
for (cnt = 0; cnt < gpiocfg_num; cnt++) {
|
||||
ret = rwnx_send_dbg_mem_write_req(sdiodev, gpio_cfg_tbl_8800d40d80[cnt][0], gpio_cfg_tbl_8800d40d80[cnt][1]);
|
||||
if (ret) {
|
||||
printk("%x write fail: %d\n", gpio_cfg_tbl_8800d40d80[cnt][0], ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int aicwifi_patch_config_8800d80(struct aic_sdio_dev *sdiodev)
|
||||
{
|
||||
const u32 rd_patch_addr = RAM_FMAC_FW_ADDR + 0x0198;
|
||||
u32 aic_patch_addr;
|
||||
u32 config_base, aic_patch_str_base;
|
||||
uint32_t start_addr = 0x0016F800;
|
||||
u32 patch_addr = start_addr;
|
||||
u32 patch_cnt = sizeof(patch_tbl_8800d80)/sizeof(u32)/2;
|
||||
struct dbg_mem_read_cfm rd_patch_addr_cfm;
|
||||
int ret = 0;
|
||||
int cnt = 0;
|
||||
//adap test
|
||||
int adap_patch_cnt = 0;
|
||||
|
||||
if (adap_test) {
|
||||
adap_patch_cnt = sizeof(adaptivity_patch_tbl_8800d80)/sizeof(u32)/2;
|
||||
}
|
||||
|
||||
aic_patch_addr = rd_patch_addr + 8;
|
||||
|
||||
ret = rwnx_send_dbg_mem_read_req(sdiodev, rd_patch_addr, &rd_patch_addr_cfm);
|
||||
if (ret) {
|
||||
printk("patch rd fail\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
config_base = rd_patch_addr_cfm.memdata;
|
||||
|
||||
ret = rwnx_send_dbg_mem_read_req(sdiodev, aic_patch_addr, &rd_patch_addr_cfm);
|
||||
if (ret) {
|
||||
printk("patch str rd fail\n");
|
||||
return ret;
|
||||
}
|
||||
aic_patch_str_base = rd_patch_addr_cfm.memdata;
|
||||
|
||||
ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(magic_num), AIC_PATCH_MAGIG_NUM);
|
||||
if (ret) {
|
||||
printk("0x%x write fail\n", AIC_PATCH_ADDR(magic_num));
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(magic_num_2), AIC_PATCH_MAGIG_NUM_2);
|
||||
if (ret) {
|
||||
printk("0x%x write fail\n", AIC_PATCH_ADDR(magic_num_2));
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(pair_start), patch_addr);
|
||||
if (ret) {
|
||||
printk("0x%x write fail\n", AIC_PATCH_ADDR(pair_start));
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(pair_count), patch_cnt + adap_patch_cnt);
|
||||
if (ret) {
|
||||
printk("0x%x write fail\n", AIC_PATCH_ADDR(pair_count));
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (cnt = 0; cnt < patch_cnt; cnt++) {
|
||||
ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*cnt, patch_tbl_8800d80[cnt][0]+config_base);
|
||||
if (ret) {
|
||||
printk("%x write fail\n", start_addr+8*cnt);
|
||||
return ret;
|
||||
}
|
||||
ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*cnt+4, patch_tbl_8800d80[cnt][1]);
|
||||
if (ret) {
|
||||
printk("%x write fail\n", start_addr+8*cnt+4);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (adap_test){
|
||||
int tmp_cnt = patch_cnt + adap_patch_cnt;
|
||||
for (cnt = patch_cnt; cnt < tmp_cnt; cnt++) {
|
||||
int tbl_idx = cnt - patch_cnt;
|
||||
ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*cnt, adaptivity_patch_tbl_8800d80[tbl_idx][0]+config_base);
|
||||
if(ret) {
|
||||
printk("%x write fail\n", start_addr+8*cnt);
|
||||
return ret;
|
||||
}
|
||||
ret = rwnx_send_dbg_mem_write_req(sdiodev, start_addr+8*cnt+4, adaptivity_patch_tbl_8800d80[tbl_idx][1]);
|
||||
if(ret) {
|
||||
printk("%x write fail\n", start_addr+8*cnt+4);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(block_size[0]), 0);
|
||||
if (ret) {
|
||||
printk("block_size[0x%x] write fail: %d\n", AIC_PATCH_ADDR(block_size[0]), ret);
|
||||
return ret;
|
||||
}
|
||||
ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(block_size[1]), 0);
|
||||
if (ret) {
|
||||
printk("block_size[0x%x] write fail: %d\n", AIC_PATCH_ADDR(block_size[1]), ret);
|
||||
return ret;
|
||||
}
|
||||
ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(block_size[2]), 0);
|
||||
if (ret) {
|
||||
printk("block_size[0x%x] write fail: %d\n", AIC_PATCH_ADDR(block_size[2]), ret);
|
||||
return ret;
|
||||
}
|
||||
ret = rwnx_send_dbg_mem_write_req(sdiodev, AIC_PATCH_ADDR(block_size[3]), 0);
|
||||
if (ret) {
|
||||
printk("block_size[0x%x] write fail: %d\n", AIC_PATCH_ADDR(block_size[3]), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
24
drivers/net/wireless/aic8800/aic8800_bsp/aic8800d80_compat.h
Normal file
24
drivers/net/wireless/aic8800/aic8800_bsp/aic8800d80_compat.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef _AIC8800D80_COMPAT_H_
|
||||
#define _AIC8800D80_COMPAT_H_
|
||||
|
||||
#include "aicsdio.h"
|
||||
/*typedef u32 (*array2_tbl_t)[2];
|
||||
|
||||
typedef uint8_t u8_l;
|
||||
typedef int8_t s8_l;
|
||||
typedef bool bool_l;
|
||||
typedef uint16_t u16_l;
|
||||
typedef int16_t s16_l;
|
||||
typedef uint32_t u32_l;
|
||||
typedef int32_t s32_l;
|
||||
typedef uint64_t u64_l;*/
|
||||
|
||||
int aicbsp_system_config_8800d80(struct aic_sdio_dev *sdiodev);
|
||||
int aicwifi_sys_config_8800d80(struct aic_sdio_dev *sdiodev);
|
||||
int aicwifi_patch_config_8800d80(struct aic_sdio_dev *sdiodev);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
1993
drivers/net/wireless/aic8800/aic8800_bsp/aic8800dc_compat.c
Normal file
1993
drivers/net/wireless/aic8800/aic8800_bsp/aic8800dc_compat.c
Normal file
File diff suppressed because it is too large
Load Diff
35
drivers/net/wireless/aic8800/aic8800_bsp/aic8800dc_compat.h
Normal file
35
drivers/net/wireless/aic8800/aic8800_bsp/aic8800dc_compat.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#ifndef _AIC8800DC_COMPAT_H_
|
||||
#define _AIC8800DC_COMPAT_H_
|
||||
|
||||
#include "aicsdio.h"
|
||||
typedef u32 (*array2_tbl_t)[2];
|
||||
typedef u32 (*array3_tbl_t)[3];
|
||||
|
||||
typedef uint8_t u8_l;
|
||||
typedef int8_t s8_l;
|
||||
typedef bool bool_l;
|
||||
typedef uint16_t u16_l;
|
||||
typedef int16_t s16_l;
|
||||
typedef uint32_t u32_l;
|
||||
typedef int32_t s32_l;
|
||||
typedef uint64_t u64_l;
|
||||
|
||||
extern u8 chip_sub_id;
|
||||
extern u8 chip_mcu_id;
|
||||
#define DPD_RESULT_SIZE_8800DC 1880
|
||||
#define FW_PATH_MAX_LEN 200
|
||||
|
||||
void aicwf_patch_config_8800dc(struct aic_sdio_dev *rwnx_hw);
|
||||
void system_config_8800dc(struct aic_sdio_dev *rwnx_hw);
|
||||
int aicwf_misc_ram_init_8800dc(struct aic_sdio_dev *sdiodev);
|
||||
|
||||
#ifdef CONFIG_DPD
|
||||
int aicwf_dpd_calib_8800dc(struct aic_sdio_dev *sdiodev, uint32_t *dpd_res);
|
||||
int aicwf_dpd_result_load_8800dc(struct aic_sdio_dev *sdiodev);
|
||||
int aicwf_dpd_result_write_8800dc(void *buf, int buf_len);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
1747
drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_driver.c
Normal file
1747
drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_driver.c
Normal file
File diff suppressed because it is too large
Load Diff
535
drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_driver.h
Normal file
535
drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_driver.h
Normal file
@@ -0,0 +1,535 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* rwnx_cmds.h
|
||||
*
|
||||
* Copyright (C) RivieraWaves 2014-2019
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef _AIC_BSP_DRIVER_H
|
||||
#define _AIC_BSP_DRIVER_H
|
||||
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/module.h>
|
||||
#include "aic_bsp_export.h"
|
||||
|
||||
#define RWNX_80211_CMD_TIMEOUT_MS 3000//500//300
|
||||
|
||||
#define RWNX_CMD_FLAG_NONBLOCK BIT(0)
|
||||
#define RWNX_CMD_FLAG_REQ_CFM BIT(1)
|
||||
#define RWNX_CMD_FLAG_WAIT_PUSH BIT(2)
|
||||
#define RWNX_CMD_FLAG_WAIT_ACK BIT(3)
|
||||
#define RWNX_CMD_FLAG_WAIT_CFM BIT(4)
|
||||
#define RWNX_CMD_FLAG_DONE BIT(5)
|
||||
/* ATM IPC design makes it possible to get the CFM before the ACK,
|
||||
* otherwise this could have simply been a state enum */
|
||||
#define RWNX_CMD_WAIT_COMPLETE(flags) \
|
||||
(!(flags & (RWNX_CMD_FLAG_WAIT_ACK | RWNX_CMD_FLAG_WAIT_CFM)))
|
||||
|
||||
#define RWNX_CMD_MAX_QUEUED 8
|
||||
|
||||
#define IPC_E2A_MSG_PARAM_SIZE 256
|
||||
|
||||
#define RWNX_FN_ENTRY_STR ">>> %s()\n", __func__
|
||||
|
||||
/* message levels */
|
||||
#define LOGERROR 0x0001
|
||||
#define LOGINFO 0x0002
|
||||
#define LOGTRACE 0x0004
|
||||
#define LOGDEBUG 0x0008
|
||||
#define LOGDATA 0x0010
|
||||
|
||||
extern int aicwf_dbg_level_bsp;
|
||||
|
||||
#define AICWF_LOG "AICWFDBG("
|
||||
|
||||
#define AICWFDBG(level, args, arg...) \
|
||||
do { \
|
||||
if (aicwf_dbg_level_bsp & level) { \
|
||||
printk(AICWF_LOG#level")\t" args, ##arg); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define RWNX_DBG(fmt, ...) \
|
||||
do { \
|
||||
if (aicwf_dbg_level_bsp & LOGTRACE) { \
|
||||
printk(AICWF_LOG"LOGTRACE)\t"fmt , ##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/// Message structure for MSGs from Emb to App
|
||||
struct ipc_e2a_msg {
|
||||
u16 id; ///< Message id.
|
||||
u16 dummy_dest_id;
|
||||
u16 dummy_src_id;
|
||||
u16 param_len; ///< Parameter embedded struct length.
|
||||
u32 pattern; ///< Used to stamp a valid MSG buffer
|
||||
u32 param[IPC_E2A_MSG_PARAM_SIZE]; ///< Parameter embedded struct. Must be word-aligned.
|
||||
};
|
||||
|
||||
typedef u16 lmac_msg_id_t;
|
||||
typedef u16 lmac_task_id_t;
|
||||
|
||||
struct lmac_msg {
|
||||
lmac_msg_id_t id; ///< Message id.
|
||||
lmac_task_id_t dest_id; ///< Destination kernel identifier.
|
||||
lmac_task_id_t src_id; ///< Source kernel identifier.
|
||||
u16 param_len; ///< Parameter embedded struct length.
|
||||
u32 param[]; ///< Parameter embedded struct. Must be word-aligned.
|
||||
};
|
||||
|
||||
#define rwnx_cmd_e2amsg ipc_e2a_msg
|
||||
#define rwnx_cmd_a2emsg lmac_msg
|
||||
#define RWNX_CMD_A2EMSG_LEN(m) (sizeof(struct lmac_msg) + m->param_len)
|
||||
#define RWNX_CMD_E2AMSG_LEN_MAX (IPC_E2A_MSG_PARAM_SIZE * 4)
|
||||
|
||||
static inline void put_u16(u8 *buf, u16 data)
|
||||
{
|
||||
buf[0] = (u8)(data&0x00ff);
|
||||
buf[1] = (u8)((data >> 8)&0x00ff);
|
||||
}
|
||||
|
||||
enum rwnx_cmd_mgr_state {
|
||||
RWNX_CMD_MGR_STATE_DEINIT,
|
||||
RWNX_CMD_MGR_STATE_INITED,
|
||||
RWNX_CMD_MGR_STATE_CRASHED,
|
||||
};
|
||||
|
||||
struct rwnx_cmd {
|
||||
struct list_head list;
|
||||
lmac_msg_id_t id;
|
||||
lmac_msg_id_t reqid;
|
||||
struct rwnx_cmd_a2emsg *a2e_msg;
|
||||
char *e2a_msg;
|
||||
u32 tkn;
|
||||
u16 flags;
|
||||
struct completion complete;
|
||||
u32 result;
|
||||
};
|
||||
|
||||
struct aic_sdio_dev;
|
||||
struct rwnx_cmd;
|
||||
typedef int (*msg_cb_fct)(struct rwnx_cmd *cmd, struct rwnx_cmd_e2amsg *msg);
|
||||
|
||||
struct rwnx_cmd_mgr {
|
||||
enum rwnx_cmd_mgr_state state;
|
||||
spinlock_t lock;
|
||||
u32 next_tkn;
|
||||
u32 queue_sz;
|
||||
u32 max_queue_sz;
|
||||
spinlock_t cb_lock;
|
||||
void *sdiodev;
|
||||
|
||||
struct list_head cmds;
|
||||
|
||||
int (*queue)(struct rwnx_cmd_mgr *, struct rwnx_cmd *);
|
||||
int (*llind)(struct rwnx_cmd_mgr *, struct rwnx_cmd *);
|
||||
int (*msgind)(struct rwnx_cmd_mgr *, struct rwnx_cmd_e2amsg *, msg_cb_fct);
|
||||
void (*print)(struct rwnx_cmd_mgr *);
|
||||
void (*drain)(struct rwnx_cmd_mgr *);
|
||||
|
||||
struct work_struct cmdWork;
|
||||
struct workqueue_struct *cmd_wq;
|
||||
};
|
||||
|
||||
void rwnx_cmd_mgr_init(struct rwnx_cmd_mgr *cmd_mgr);
|
||||
void rwnx_cmd_mgr_deinit(struct rwnx_cmd_mgr *cmd_mgr);
|
||||
int cmd_mgr_queue_force_defer(struct rwnx_cmd_mgr *cmd_mgr, struct rwnx_cmd *cmd);
|
||||
void rwnx_set_cmd_tx(void *dev, struct lmac_msg *msg, uint len);
|
||||
|
||||
enum {
|
||||
TASK_NONE = (u8) -1,
|
||||
|
||||
// MAC Management task.
|
||||
TASK_MM = 0,
|
||||
// DEBUG task
|
||||
TASK_DBG,
|
||||
/// SCAN task
|
||||
TASK_SCAN,
|
||||
/// TDLS task
|
||||
TASK_TDLS,
|
||||
/// SCANU task
|
||||
TASK_SCANU,
|
||||
/// ME task
|
||||
TASK_ME,
|
||||
/// SM task
|
||||
TASK_SM,
|
||||
/// APM task
|
||||
TASK_APM,
|
||||
/// BAM task
|
||||
TASK_BAM,
|
||||
/// MESH task
|
||||
TASK_MESH,
|
||||
/// RXU task
|
||||
TASK_RXU,
|
||||
// This is used to define the last task that is running on the EMB processor
|
||||
TASK_LAST_EMB = TASK_RXU,
|
||||
|
||||
// nX API task
|
||||
TASK_API,
|
||||
TASK_MAX,
|
||||
};
|
||||
|
||||
#define LMAC_FIRST_MSG(task) ((lmac_msg_id_t)((task) << 10))
|
||||
#define DRV_TASK_ID 100
|
||||
#define MSG_I(msg) ((msg) & ((1<<10)-1))
|
||||
#define MSG_T(msg) ((lmac_task_id_t)((msg) >> 10))
|
||||
|
||||
enum dbg_msg_tag {
|
||||
/// Memory read request
|
||||
DBG_MEM_READ_REQ = LMAC_FIRST_MSG(TASK_DBG),
|
||||
/// Memory read confirm
|
||||
DBG_MEM_READ_CFM,
|
||||
/// Memory write request
|
||||
DBG_MEM_WRITE_REQ,
|
||||
/// Memory write confirm
|
||||
DBG_MEM_WRITE_CFM,
|
||||
/// Module filter request
|
||||
DBG_SET_MOD_FILTER_REQ,
|
||||
/// Module filter confirm
|
||||
DBG_SET_MOD_FILTER_CFM,
|
||||
/// Severity filter request
|
||||
DBG_SET_SEV_FILTER_REQ,
|
||||
/// Severity filter confirm
|
||||
DBG_SET_SEV_FILTER_CFM,
|
||||
/// LMAC/MAC HW fatal error indication
|
||||
DBG_ERROR_IND,
|
||||
/// Request to get system statistics
|
||||
DBG_GET_SYS_STAT_REQ,
|
||||
/// COnfirmation of system statistics
|
||||
DBG_GET_SYS_STAT_CFM,
|
||||
/// Memory block write request
|
||||
DBG_MEM_BLOCK_WRITE_REQ,
|
||||
/// Memory block write confirm
|
||||
DBG_MEM_BLOCK_WRITE_CFM,
|
||||
/// Start app request
|
||||
DBG_START_APP_REQ,
|
||||
/// Start app confirm
|
||||
DBG_START_APP_CFM,
|
||||
/// Start npc request
|
||||
DBG_START_NPC_REQ,
|
||||
/// Start npc confirm
|
||||
DBG_START_NPC_CFM,
|
||||
/// Memory mask write request
|
||||
DBG_MEM_MASK_WRITE_REQ,
|
||||
/// Memory mask write confirm
|
||||
DBG_MEM_MASK_WRITE_CFM,
|
||||
|
||||
DBG_RFTEST_CMD_REQ,
|
||||
DBG_RFTEST_CMD_CFM,
|
||||
DBG_BINDING_REQ,
|
||||
DBG_BINDING_CFM,
|
||||
DBG_BINDING_IND,
|
||||
|
||||
DBG_CUSTOM_MSG_REQ,
|
||||
DBG_CUSTOM_MSG_CFM,
|
||||
DBG_CUSTOM_MSG_IND,
|
||||
|
||||
DBG_GPIO_WRITE_REQ,
|
||||
DBG_GPIO_WRITE_CFM,
|
||||
|
||||
|
||||
/// Max number of Debug messages
|
||||
DBG_MAX,
|
||||
};
|
||||
|
||||
enum {
|
||||
HOST_START_APP_AUTO = 1,
|
||||
HOST_START_APP_CUSTOM,
|
||||
HOST_START_APP_FNCALL = 4,
|
||||
HOST_START_APP_DUMMY = 5,
|
||||
};
|
||||
|
||||
|
||||
struct dbg_mem_block_write_req {
|
||||
u32 memaddr;
|
||||
u32 memsize;
|
||||
u32 memdata[1024 / sizeof(u32)];
|
||||
};
|
||||
|
||||
/// Structure containing the parameters of the @ref DBG_MEM_BLOCK_WRITE_CFM message.
|
||||
struct dbg_mem_block_write_cfm {
|
||||
u32 wstatus;
|
||||
};
|
||||
|
||||
/// Structure containing the parameters of the @ref DBG_MEM_WRITE_REQ message.
|
||||
struct dbg_mem_write_req {
|
||||
u32 memaddr;
|
||||
u32 memdata;
|
||||
};
|
||||
|
||||
/// Structure containing the parameters of the @ref DBG_MEM_WRITE_CFM message.
|
||||
struct dbg_mem_write_cfm {
|
||||
u32 memaddr;
|
||||
u32 memdata;
|
||||
};
|
||||
|
||||
/// Structure containing the parameters of the @ref DBG_MEM_READ_REQ message.
|
||||
struct dbg_mem_read_req {
|
||||
u32 memaddr;
|
||||
};
|
||||
|
||||
/// Structure containing the parameters of the @ref DBG_MEM_READ_CFM message.
|
||||
struct dbg_mem_read_cfm {
|
||||
u32 memaddr;
|
||||
u32 memdata;
|
||||
};
|
||||
|
||||
/// Structure containing the parameters of the @ref DBG_MEM_MASK_WRITE_REQ message.
|
||||
struct dbg_mem_mask_write_req {
|
||||
u32 memaddr;
|
||||
u32 memmask;
|
||||
u32 memdata;
|
||||
};
|
||||
|
||||
/// Structure containing the parameters of the @ref DBG_MEM_MASK_WRITE_CFM message.
|
||||
struct dbg_mem_mask_write_cfm {
|
||||
u32 memaddr;
|
||||
u32 memdata;
|
||||
};
|
||||
|
||||
/// Structure containing the parameters of the @ref DBG_START_APP_REQ message.
|
||||
struct dbg_start_app_req {
|
||||
u32 bootaddr;
|
||||
u32 boottype;
|
||||
};
|
||||
|
||||
/// Structure containing the parameters of the @ref DBG_START_APP_CFM message.
|
||||
struct dbg_start_app_cfm {
|
||||
u32 bootstatus;
|
||||
};
|
||||
|
||||
int aicwf_plat_patch_load_8800dc(struct aic_sdio_dev *sdiodev);
|
||||
int aicwf_plat_rftest_load_8800dc(struct aic_sdio_dev *sdiodev);
|
||||
#ifdef CONFIG_DPD
|
||||
int aicwf_plat_calib_load_8800dc(struct aic_sdio_dev *sdiodev);
|
||||
#endif
|
||||
|
||||
int rwnx_load_firmware(u32 **fw_buf, const char *name, struct device *device);
|
||||
int aicwf_patch_table_load(struct aic_sdio_dev *rwnx_hw, char *filename);
|
||||
|
||||
int rwnx_send_dbg_mem_read_req(struct aic_sdio_dev *sdiodev, u32 mem_addr,
|
||||
struct dbg_mem_read_cfm *cfm);
|
||||
int rwnx_send_dbg_mem_block_write_req(struct aic_sdio_dev *sdiodev, u32 mem_addr,
|
||||
u32 mem_size, u32 *mem_data);
|
||||
int rwnx_send_dbg_mem_write_req(struct aic_sdio_dev *sdiodev, u32 mem_addr, u32 mem_data);
|
||||
int rwnx_send_dbg_mem_mask_write_req(struct aic_sdio_dev *sdiodev, u32 mem_addr,
|
||||
u32 mem_mask, u32 mem_data);
|
||||
int rwnx_send_dbg_start_app_req(struct aic_sdio_dev *sdiodev, u32 boot_addr, u32 boot_type, struct dbg_start_app_cfm *start_app_cfm);
|
||||
|
||||
int rwnx_plat_bin_fw_upload_android(struct aic_sdio_dev *sdiodev, u32 fw_addr, const char *filename);
|
||||
|
||||
void rwnx_rx_handle_msg(struct aic_sdio_dev *sdiodev, struct ipc_e2a_msg *msg);
|
||||
int aicbsp_platform_init(struct aic_sdio_dev *sdiodev);
|
||||
void aicbsp_platform_deinit(struct aic_sdio_dev *sdiodev);
|
||||
int aicbsp_driver_fw_init(struct aic_sdio_dev *sdiodev);
|
||||
#ifdef CONFIG_DPD
|
||||
int is_file_exist(char* name);
|
||||
#endif
|
||||
int aicbsp_resv_mem_init(void);
|
||||
int aicbsp_resv_mem_deinit(void);
|
||||
|
||||
#define AICBSP_FW_PATH CONFIG_AIC_FW_PATH
|
||||
#define AICBSP_FW_PATH_MAX 200
|
||||
|
||||
#define RAM_FMAC_FW_ADDR 0x00120000
|
||||
#define FW_RAM_ADID_BASE_ADDR 0x00161928
|
||||
#define FW_RAM_ADID_BASE_ADDR_U03 0x00161928
|
||||
#define FW_RAM_PATCH_BASE_ADDR 0x00100000
|
||||
#define RAM_8800DC_U01_ADID_ADDR 0x00101788
|
||||
#define RAM_8800DC_U02_ADID_ADDR 0x001017d8
|
||||
#define RAM_8800DC_FW_PATCH_ADDR 0x00184000
|
||||
#define FW_RESET_START_ADDR 0x40500128
|
||||
#define FW_RESET_START_VAL 0x40
|
||||
#define FW_ADID_FLAG_ADDR 0x40500150
|
||||
#define FW_ADID_FLAG_VAL 0x01
|
||||
#define FW_RAM_ADID_BASE_ADDR_8800D80 0x002017E0
|
||||
#define FW_RAM_PATCH_BASE_ADDR_8800D80 0x0020B2B0
|
||||
#define FW_RAM_ADID_BASE_ADDR_8800D80_U02 0x00201940
|
||||
#define FW_RAM_PATCH_BASE_ADDR_8800D80_U02 0x0020b43c
|
||||
|
||||
#define AICBT_PT_TAG "AICBT_PT_TAG"
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Addresses within RWNX_ADDR_CPU
|
||||
*****************************************************************************/
|
||||
#define RAM_LMAC_FW_ADDR 0x00150000
|
||||
|
||||
#define ROM_FMAC_FW_ADDR 0x00010000
|
||||
#define ROM_FMAC_PATCH_ADDR 0x00180000
|
||||
|
||||
#define RWNX_MAC_CALIB_BASE_NAME_8800DC "fmacfw_calib_8800dc"
|
||||
#define RWNX_MAC_CALIB_NAME_8800DC_U02 RWNX_MAC_CALIB_BASE_NAME_8800DC"_u02.bin"
|
||||
|
||||
#ifdef CONFIG_DPD
|
||||
#define ROM_FMAC_CALIB_ADDR 0x00130000
|
||||
#define FW_DPDRESULT_NAME_8800DC "aic_dpdresult_8800dc.bin"
|
||||
#endif
|
||||
|
||||
#define RWNX_MAC_FW_RF_BASE_NAME_8800DC "lmacfw_rf_8800dc.bin"
|
||||
|
||||
#ifdef CONFIG_FOR_IPCOM
|
||||
#define RWNX_MAC_PATCH_BASE_NAME_8800DC "fmacfw_patch_8800dc_ipc"
|
||||
#define RWNX_MAC_PATCH_NAME2_8800DC RWNX_MAC_PATCH_BASE_NAME_8800DC".bin"
|
||||
#else
|
||||
#define RWNX_MAC_PATCH_BASE_NAME_8800DC "fmacfw_patch_8800dc"
|
||||
#define RWNX_MAC_PATCH_NAME2_8800DC RWNX_MAC_PATCH_BASE_NAME_8800DC".bin"
|
||||
#define RWNX_MAC_PATCH_NAME2_8800DC_U02 RWNX_MAC_PATCH_BASE_NAME_8800DC"_u02.bin"
|
||||
#endif
|
||||
|
||||
#define RWNX_MAC_PATCH_TABLE_NAME_8800DC "fmacfw_patch_tbl_8800dc"
|
||||
#define RWNX_MAC_PATCH_TABLE_8800DC RWNX_MAC_PATCH_TABLE_NAME_8800DC ".bin"
|
||||
#define RWNX_MAC_PATCH_TABLE_8800DC_U02 RWNX_MAC_PATCH_TABLE_NAME_8800DC "_u02.bin"
|
||||
|
||||
#define RWNX_MAC_RF_PATCH_BASE_NAME_8800DC "fmacfw_rf_patch_8800dc"
|
||||
#define RWNX_MAC_RF_PATCH_NAME_8800DC RWNX_MAC_RF_PATCH_BASE_NAME_8800DC".bin"
|
||||
#define FW_USERCONFIG_NAME_8800DC "aic_userconfig_8800dc.txt"
|
||||
|
||||
enum {
|
||||
FW_NORMAL_MODE = 0,
|
||||
FW_RFTEST_MODE = 1,
|
||||
FW_BLE_SCAN_WAKEUP_MODE = 2,
|
||||
FW_M2D_OTA_MODE = 3,
|
||||
FW_DPDCALIB_MODE = 4,
|
||||
FW_BLE_SCAN_AD_FILTER_MODE = 5,
|
||||
};
|
||||
|
||||
enum aicbt_patch_table_type {
|
||||
AICBT_PT_INF = 0x00,
|
||||
AICBT_PT_TRAP = 0x1,
|
||||
AICBT_PT_B4,
|
||||
AICBT_PT_BTMODE,
|
||||
AICBT_PT_PWRON,
|
||||
AICBT_PT_AF,
|
||||
AICBT_PT_VER,
|
||||
};
|
||||
|
||||
enum aicbt_btport_type {
|
||||
AICBT_BTPORT_NULL,
|
||||
AICBT_BTPORT_MB,
|
||||
AICBT_BTPORT_UART,
|
||||
};
|
||||
|
||||
/* btmode
|
||||
* used for force bt mode,if not AICBSP_MODE_NULL
|
||||
* efuse valid and vendor_info will be invalid, even has beed set valid
|
||||
*/
|
||||
enum aicbt_btmode_type {
|
||||
AICBT_BTMODE_BT_ONLY_SW = 0x0, // bt only mode with switch
|
||||
AICBT_BTMODE_BT_WIFI_COMBO, // wifi/bt combo mode
|
||||
AICBT_BTMODE_BT_ONLY, // bt only mode without switch
|
||||
AICBT_BTMODE_BT_ONLY_TEST, // bt only test mode
|
||||
AICBT_BTMODE_BT_WIFI_COMBO_TEST, // wifi/bt combo test mode
|
||||
AICBT_BTMODE_BT_ONLY_COANT, // bt only mode with no external switch
|
||||
AICBT_MODE_NULL = 0xFF, // invalid value
|
||||
};
|
||||
|
||||
/* uart_baud
|
||||
* used for config uart baud when btport set to uart,
|
||||
* otherwise meaningless
|
||||
*/
|
||||
enum aicbt_uart_baud_type {
|
||||
AICBT_UART_BAUD_115200 = 115200,
|
||||
AICBT_UART_BAUD_921600 = 921600,
|
||||
AICBT_UART_BAUD_1_5M = 1500000,
|
||||
AICBT_UART_BAUD_3_25M = 3250000,
|
||||
};
|
||||
|
||||
enum aicbt_uart_flowctrl_type {
|
||||
AICBT_UART_FLOWCTRL_DISABLE = 0x0, // uart without flow ctrl
|
||||
AICBT_UART_FLOWCTRL_ENABLE, // uart with flow ctrl
|
||||
};
|
||||
|
||||
enum aicbsp_cpmode_type {
|
||||
AICBSP_CPMODE_WORK,
|
||||
AICBSP_CPMODE_TEST,
|
||||
AICBSP_CPMODE_MAX,
|
||||
};
|
||||
|
||||
enum chip_rev {
|
||||
CHIP_REV_U01 = 1,
|
||||
CHIP_REV_U02 = 3,
|
||||
CHIP_REV_U03 = 7,
|
||||
CHIP_REV_U04 = 7,
|
||||
};
|
||||
///aic bt tx pwr lvl :lsb->msb: first byte, min pwr lvl; second byte, max pwr lvl;
|
||||
///pwr lvl:20(min), 30 , 40 , 50 , 60(max)
|
||||
#define AICBT_TXPWR_LVL 0x00006020
|
||||
#define AICBT_TXPWR_LVL_8800dc 0x00006f2f
|
||||
#define AICBT_TXPWR_LVL_8800d80 0x00006f2f
|
||||
|
||||
#define AICBSP_HWINFO_DEFAULT (-1)
|
||||
#define AICBSP_CPMODE_DEFAULT AICBSP_CPMODE_WORK
|
||||
#define AICBSP_FWLOG_EN_DEFAULT 0
|
||||
|
||||
#define AICBT_BTMODE_DEFAULT AICBT_BTMODE_BT_ONLY_SW
|
||||
#define AICBT_BTPORT_DEFAULT AICBT_BTPORT_UART
|
||||
#define AICBT_UART_BAUD_DEFAULT AICBT_UART_BAUD_1_5M
|
||||
#define AICBT_UART_FC_DEFAULT AICBT_UART_FLOWCTRL_ENABLE
|
||||
#define AICBT_LPM_ENABLE_DEFAULT 0
|
||||
#define AICBT_TXPWR_LVL_DEFAULT AICBT_TXPWR_LVL
|
||||
|
||||
#define FEATURE_SDIO_CLOCK 50000000 // 0: default, other: target clock rate
|
||||
#define FEATURE_SDIO_CLOCK_V3 150000000 // 0: default, other: target clock rate
|
||||
#define FEATURE_SDIO_PHASE 2 // 0: default, 2: 180°
|
||||
|
||||
struct aicbt_patch_table {
|
||||
char *name;
|
||||
uint32_t type;
|
||||
uint32_t *data;
|
||||
uint32_t len;
|
||||
struct aicbt_patch_table *next;
|
||||
};
|
||||
|
||||
struct aicbt_info_t {
|
||||
uint32_t btmode;
|
||||
uint32_t btport;
|
||||
uint32_t uart_baud;
|
||||
uint32_t uart_flowctrl;
|
||||
uint32_t lpm_enable;
|
||||
uint32_t txpwr_lvl;
|
||||
};
|
||||
|
||||
struct aicbt_patch_info_t {
|
||||
uint32_t info_len;
|
||||
uint32_t adid_addrinf;
|
||||
uint32_t addr_adid;
|
||||
uint32_t patch_addrinf;
|
||||
uint32_t addr_patch;
|
||||
uint32_t reset_addr;
|
||||
uint32_t reset_val;
|
||||
uint32_t adid_flag_addr;
|
||||
uint32_t adid_flag;
|
||||
};
|
||||
|
||||
struct aicbsp_firmware {
|
||||
const char *desc;
|
||||
const char *bt_adid;
|
||||
const char *bt_patch;
|
||||
const char *bt_table;
|
||||
const char *wl_fw;
|
||||
};
|
||||
|
||||
struct aicbsp_info_t {
|
||||
int hwinfo;
|
||||
int hwinfo_r;
|
||||
uint32_t cpmode;
|
||||
uint32_t chip_rev;
|
||||
bool fwlog_en;
|
||||
};
|
||||
|
||||
extern struct aicbsp_info_t aicbsp_info;
|
||||
extern struct mutex aicbsp_power_lock;
|
||||
extern const struct aicbsp_firmware *aicbsp_firmware_list;
|
||||
extern const struct aicbsp_firmware fw_u02[];
|
||||
extern const struct aicbsp_firmware fw_u03[];
|
||||
extern const struct aicbsp_firmware fw_8800dc_u01[];
|
||||
extern const struct aicbsp_firmware fw_8800dc_u02[];
|
||||
extern const struct aicbsp_firmware fw_8800d80_u01[];
|
||||
extern const struct aicbsp_firmware fw_8800d80_u02[];
|
||||
|
||||
#endif
|
||||
40
drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_export.h
Normal file
40
drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_export.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#ifndef __AIC_BSP_EXPORT_H
|
||||
#define __AIC_BSP_EXPORT_H
|
||||
|
||||
#define AICBSP_RESV_MEM_SUPPORT 0
|
||||
|
||||
enum aicbsp_subsys {
|
||||
AIC_BLUETOOTH,
|
||||
AIC_WIFI,
|
||||
};
|
||||
|
||||
enum aicbsp_pwr_state {
|
||||
AIC_PWR_OFF,
|
||||
AIC_PWR_ON,
|
||||
};
|
||||
|
||||
enum skb_buff_id {
|
||||
AIC_RESV_MEM_TXDATA,
|
||||
};
|
||||
|
||||
struct skb_buff_pool {
|
||||
uint32_t id;
|
||||
uint32_t size;
|
||||
const char *name;
|
||||
uint8_t used;
|
||||
struct sk_buff *skb;
|
||||
};
|
||||
|
||||
struct aicbsp_feature_t {
|
||||
int hwinfo;
|
||||
uint32_t sdio_clock;
|
||||
uint8_t sdio_phase;
|
||||
bool fwlog_en;
|
||||
};
|
||||
|
||||
int aicbsp_set_subsys(int, int);
|
||||
int aicbsp_get_feature(struct aicbsp_feature_t *feature, char *fw_path);
|
||||
struct sk_buff *aicbsp_resv_mem_alloc_skb(unsigned int length, uint32_t id);
|
||||
void aicbsp_resv_mem_kfree_skb(struct sk_buff *skb, uint32_t id);
|
||||
|
||||
#endif
|
||||
361
drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_main.c
Normal file
361
drivers/net/wireless/aic8800/aic8800_bsp/aic_bsp_main.c
Normal file
@@ -0,0 +1,361 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/inetdevice.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include "aic_bsp_driver.h"
|
||||
#include "rwnx_version_gen.h"
|
||||
#include "aicwf_txq_prealloc.h"
|
||||
|
||||
|
||||
#define DRV_DESCRIPTION "AIC BSP"
|
||||
#define DRV_COPYRIGHT "Copyright(c) 2015-2020 AICSemi"
|
||||
#define DRV_AUTHOR "AICSemi"
|
||||
#define DRV_VERS_MOD "1.0"
|
||||
|
||||
/* int aicwf_dbg_level_bsp = LOGERROR|LOGINFO|LOGDEBUG|LOGTRACE; */
|
||||
int aicwf_dbg_level_bsp = LOGERROR;
|
||||
module_param(aicwf_dbg_level_bsp, int, 0660);
|
||||
|
||||
static struct platform_device *aicbsp_pdev;
|
||||
|
||||
const struct aicbsp_firmware *aicbsp_firmware_list = fw_u02;
|
||||
|
||||
const struct aicbsp_firmware fw_u02[] = {
|
||||
[AICBSP_CPMODE_WORK] = {
|
||||
.desc = "normal work mode(sdio u02)",
|
||||
.bt_adid = "fw_adid.bin",
|
||||
.bt_patch = "fw_patch.bin",
|
||||
.bt_table = "fw_patch_table.bin",
|
||||
.wl_fw = "fmacfw.bin"
|
||||
},
|
||||
[AICBSP_CPMODE_TEST] = {
|
||||
.desc = "rf test mode(sdio u02)",
|
||||
.bt_adid = "fw_adid.bin",
|
||||
.bt_patch = "fw_patch.bin",
|
||||
.bt_table = "fw_patch_table.bin",
|
||||
.wl_fw = "fmacfw_rf.bin"
|
||||
},
|
||||
};
|
||||
|
||||
const struct aicbsp_firmware fw_u03[] = {
|
||||
[AICBSP_CPMODE_WORK] = {
|
||||
.desc = "normal work mode(sdio u03/u04)",
|
||||
.bt_adid = "fw_adid_u03.bin",
|
||||
.bt_patch = "fw_patch_u03.bin",
|
||||
.bt_table = "fw_patch_table_u03.bin",
|
||||
#ifdef CONFIG_MCU_MESSAGE
|
||||
.wl_fw = "fmacfw_8800m_custmsg.bin"
|
||||
#else
|
||||
.wl_fw = "fmacfw.bin"
|
||||
#endif
|
||||
},
|
||||
|
||||
[AICBSP_CPMODE_TEST] = {
|
||||
.desc = "rf test mode(sdio u03/u04)",
|
||||
.bt_adid = "fw_adid_u03.bin",
|
||||
.bt_patch = "fw_patch_u03.bin",
|
||||
.bt_table = "fw_patch_table_u03.bin",
|
||||
.wl_fw = "fmacfw_rf.bin"
|
||||
},
|
||||
};
|
||||
|
||||
const struct aicbsp_firmware fw_8800dc_u01[] = {
|
||||
[AICBSP_CPMODE_WORK] = {
|
||||
.desc = "normal work mode(sdio u01)",
|
||||
.bt_adid = "fw_adid_8800dc.bin",
|
||||
.bt_patch = "fw_patch_8800dc.bin",
|
||||
.bt_table = "fw_patch_table_8800dc.bin",
|
||||
.wl_fw = "fmacfw_8800dc.bin"
|
||||
},
|
||||
|
||||
[AICBSP_CPMODE_TEST] = {
|
||||
.desc = "rf test mode(sdio u01)",
|
||||
.bt_adid = "fw_adid_8800dc.bin",
|
||||
.bt_patch = "fw_patch_8800dc.bin",
|
||||
.bt_table = "fw_patch_table_8800dc.bin",
|
||||
.wl_fw = "fmacfw_rf_8800dc.bin"
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
const struct aicbsp_firmware fw_8800dc_u02[] = {
|
||||
[AICBSP_CPMODE_WORK] = {
|
||||
.desc = "normal work mode(8800dc sdio u02)",
|
||||
.bt_adid = "fw_adid_8800dc_u02.bin",
|
||||
.bt_patch = "fw_patch_8800dc_u02.bin",
|
||||
.bt_table = "fw_patch_table_8800dc_u02.bin",
|
||||
.wl_fw = "fmacfw_patch_8800dc_u02.bin"
|
||||
},
|
||||
|
||||
[AICBSP_CPMODE_TEST] = {
|
||||
.desc = "rf test mode(8800dc sdio u02)",
|
||||
.bt_adid = "fw_adid_8800dc_u02.bin",
|
||||
.bt_patch = "fw_patch_8800dc_u02.bin",
|
||||
.bt_table = "fw_patch_table_8800dc_u02.bin",
|
||||
.wl_fw = "lmacfw_rf_8800dc.bin" //u01,u02 lmacfw load same bin
|
||||
},
|
||||
};
|
||||
|
||||
const struct aicbsp_firmware fw_8800d80_u01[] = {
|
||||
[AICBSP_CPMODE_WORK] = {
|
||||
.desc = "normal work mode(8800d80 sdio u01)",
|
||||
.bt_adid = "fw_adid_8800d80.bin",
|
||||
.bt_patch = "fw_patch_8800d80.bin",
|
||||
.bt_table = "fw_patch_table_8800d80.bin",
|
||||
.wl_fw = "fmacfw_8800d80.bin"
|
||||
},
|
||||
|
||||
[AICBSP_CPMODE_TEST] = {
|
||||
.desc = "rf test mode(8800d80 sdio u01)",
|
||||
.bt_adid = "fw_adid_8800d80.bin",
|
||||
.bt_patch = "fw_patch_8800d80.bin",
|
||||
.bt_table = "fw_patch_table_8800d80.bin",
|
||||
.wl_fw = "lmacfw_rf_8800d80.bin"
|
||||
},
|
||||
};
|
||||
|
||||
const struct aicbsp_firmware fw_8800d80_u02[] = {
|
||||
[AICBSP_CPMODE_WORK] = {
|
||||
.desc = "normal work mode(8800d80 sdio u02)",
|
||||
.bt_adid = "fw_adid_8800d80_u02.bin",
|
||||
.bt_patch = "fw_patch_8800d80_u02.bin",
|
||||
.bt_table = "fw_patch_table_8800d80_u02.bin",
|
||||
.wl_fw = "fmacfw_8800d80_u02.bin"
|
||||
},
|
||||
|
||||
[AICBSP_CPMODE_TEST] = {
|
||||
.desc = "rf test mode(8800d80 sdio u02)",
|
||||
.bt_adid = "fw_adid_8800d80_u02.bin",
|
||||
.bt_patch = "fw_patch_8800d80_u02.bin",
|
||||
.bt_table = "fw_patch_table_8800d80_u02.bin",
|
||||
.wl_fw = "lmacfw_rf_8800d80_u02.bin"
|
||||
},
|
||||
};
|
||||
|
||||
struct aicbsp_info_t aicbsp_info = {
|
||||
.hwinfo_r = AICBSP_HWINFO_DEFAULT,
|
||||
.hwinfo = AICBSP_HWINFO_DEFAULT,
|
||||
.cpmode = AICBSP_CPMODE_DEFAULT,
|
||||
.fwlog_en = AICBSP_FWLOG_EN_DEFAULT,
|
||||
};
|
||||
|
||||
struct mutex aicbsp_power_lock;
|
||||
|
||||
static struct platform_driver aicbsp_driver = {
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "aic_bsp",
|
||||
},
|
||||
//.probe = aicbsp_probe,
|
||||
//.remove = aicbsp_remove,
|
||||
};
|
||||
|
||||
static ssize_t cpmode_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
ssize_t count = 0;
|
||||
uint8_t i = 0;
|
||||
|
||||
count += sprintf(&buf[count], "Support mode value:\n");
|
||||
|
||||
for (i = 0; i < AICBSP_CPMODE_MAX; i++) {
|
||||
if (aicbsp_firmware_list[i].desc)
|
||||
count += sprintf(&buf[count], " %2d: %s\n", i, aicbsp_firmware_list[i].desc);
|
||||
}
|
||||
|
||||
count += sprintf(&buf[count], "Current: %d, firmware info:\n", aicbsp_info.cpmode);
|
||||
count += sprintf(&buf[count], " BT ADID : %s\n", aicbsp_firmware_list[aicbsp_info.cpmode].bt_adid);
|
||||
count += sprintf(&buf[count], " BT PATCH: %s\n", aicbsp_firmware_list[aicbsp_info.cpmode].bt_patch);
|
||||
count += sprintf(&buf[count], " BT TABLE: %s\n", aicbsp_firmware_list[aicbsp_info.cpmode].bt_table);
|
||||
count += sprintf(&buf[count], " WIFI FW : %s\n", aicbsp_firmware_list[aicbsp_info.cpmode].wl_fw);
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t cpmode_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
unsigned long val;
|
||||
int err = kstrtoul(buf, 0, &val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (val >= AICBSP_CPMODE_MAX) {
|
||||
pr_err("mode value must less than %d\n", AICBSP_CPMODE_MAX);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
aicbsp_info.cpmode = val;
|
||||
printk("%s, set mode to: %lu[%s] done\n", __func__, val, aicbsp_firmware_list[val].desc);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t hwinfo_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
ssize_t count = 0;
|
||||
|
||||
count += sprintf(&buf[count], "chip hw rev: ");
|
||||
if (aicbsp_info.hwinfo_r < 0)
|
||||
count += sprintf(&buf[count], "-1(not avalible)\n");
|
||||
else
|
||||
count += sprintf(&buf[count], "0x%02X\n", aicbsp_info.chip_rev);
|
||||
|
||||
count += sprintf(&buf[count], "hwinfo read: ");
|
||||
if (aicbsp_info.hwinfo_r < 0)
|
||||
count += sprintf(&buf[count], "%d(not avalible), ", aicbsp_info.hwinfo_r);
|
||||
else
|
||||
count += sprintf(&buf[count], "0x%02X, ", aicbsp_info.hwinfo_r);
|
||||
|
||||
if (aicbsp_info.hwinfo < 0)
|
||||
count += sprintf(&buf[count], "set: %d(not avalible)\n", aicbsp_info.hwinfo);
|
||||
else
|
||||
count += sprintf(&buf[count], "set: 0x%02X\n", aicbsp_info.hwinfo);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t hwinfo_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
long val;
|
||||
int err = kstrtol(buf, 0, &val);
|
||||
|
||||
if (err) {
|
||||
pr_err("invalid input\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
if ((val == -1) || (val >= 0 && val <= 0xFF)) {
|
||||
aicbsp_info.hwinfo = val;
|
||||
} else {
|
||||
pr_err("invalid values\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t fwdebug_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
ssize_t count = 0;
|
||||
|
||||
count += sprintf(&buf[count], "fw log status: %s\n",
|
||||
aicbsp_info.fwlog_en ? "on" : "off");
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t fwdebug_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
long val;
|
||||
int err = kstrtol(buf, 0, &val);
|
||||
|
||||
if (err) {
|
||||
pr_err("invalid input\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
if (val > 1 || val < 0) {
|
||||
pr_err("must be 0 or 1\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
aicbsp_info.fwlog_en = val;
|
||||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(cpmode, S_IRUGO | S_IWUSR,
|
||||
cpmode_show, cpmode_store);
|
||||
|
||||
static DEVICE_ATTR(hwinfo, S_IRUGO | S_IWUSR,
|
||||
hwinfo_show, hwinfo_store);
|
||||
|
||||
static DEVICE_ATTR(fwdebug, S_IRUGO | S_IWUSR,
|
||||
fwdebug_show, fwdebug_store);
|
||||
|
||||
static struct attribute *aicbsp_attributes[] = {
|
||||
&dev_attr_cpmode.attr,
|
||||
&dev_attr_hwinfo.attr,
|
||||
&dev_attr_fwdebug.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct attribute_group aicbsp_attribute_group = {
|
||||
.name = "aicbsp_info",
|
||||
.attrs = aicbsp_attributes,
|
||||
};
|
||||
|
||||
int testmode = AICBSP_CPMODE_DEFAULT;
|
||||
int adap_test = 0;
|
||||
module_param(testmode, int, 0660);
|
||||
module_param(adap_test, int, 0660);
|
||||
|
||||
|
||||
static int __init aicbsp_init(void)
|
||||
{
|
||||
int ret;
|
||||
printk("%s\n", __func__);
|
||||
printk("RELEASE_DATE:%s\r\n", RELEASE_DATE);
|
||||
|
||||
aicbsp_info.cpmode = testmode;
|
||||
|
||||
aicbsp_resv_mem_init();
|
||||
ret = platform_driver_register(&aicbsp_driver);
|
||||
if (ret) {
|
||||
pr_err("register platform driver failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
aicbsp_pdev = platform_device_alloc("aic-bsp", -1);
|
||||
ret = platform_device_add(aicbsp_pdev);
|
||||
if (ret) {
|
||||
pr_err("register platform device failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = sysfs_create_group(&(aicbsp_pdev->dev.kobj), &aicbsp_attribute_group);
|
||||
if (ret) {
|
||||
pr_err("register sysfs create group failed!\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
mutex_init(&aicbsp_power_lock);
|
||||
#ifdef CONFIG_PLATFORM_ROCKCHIP
|
||||
aicbsp_set_subsys(AIC_BLUETOOTH, AIC_PWR_ON);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void aicbsp_sdio_exit(void);
|
||||
extern struct aic_sdio_dev *aicbsp_sdiodev;
|
||||
|
||||
static void __exit aicbsp_exit(void)
|
||||
{
|
||||
#ifdef CONFIG_PLATFORM_ROCKCHIP
|
||||
if(aicbsp_sdiodev){
|
||||
aicbsp_sdio_exit();
|
||||
}
|
||||
#endif
|
||||
sysfs_remove_group(&(aicbsp_pdev->dev.kobj), &aicbsp_attribute_group);
|
||||
platform_device_del(aicbsp_pdev);
|
||||
platform_driver_unregister(&aicbsp_driver);
|
||||
mutex_destroy(&aicbsp_power_lock);
|
||||
aicbsp_resv_mem_deinit();
|
||||
#ifdef CONFIG_PREALLOC_TXQ
|
||||
aicwf_prealloc_txq_free();
|
||||
#endif
|
||||
printk("%s\n", __func__);
|
||||
}
|
||||
|
||||
module_init(aicbsp_init);
|
||||
module_exit(aicbsp_exit);
|
||||
|
||||
MODULE_DESCRIPTION(DRV_DESCRIPTION);
|
||||
MODULE_VERSION(DRV_VERS_MOD);
|
||||
MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
|
||||
MODULE_LICENSE("GPL");
|
||||
1945
drivers/net/wireless/aic8800/aic8800_bsp/aicsdio.c
Normal file
1945
drivers/net/wireless/aic8800/aic8800_bsp/aicsdio.c
Normal file
File diff suppressed because it is too large
Load Diff
147
drivers/net/wireless/aic8800/aic8800_bsp/aicsdio.h
Normal file
147
drivers/net/wireless/aic8800/aic8800_bsp/aicsdio.h
Normal file
@@ -0,0 +1,147 @@
|
||||
/**
|
||||
* aicwf_sdio.h
|
||||
*
|
||||
* SDIO function declarations
|
||||
*
|
||||
* Copyright (C) AICSemi 2018-2020
|
||||
*/
|
||||
|
||||
#ifndef _AICWF_SDMMC_H_
|
||||
#define _AICWF_SDMMC_H_
|
||||
|
||||
#ifdef AICWF_SDIO_SUPPORT
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/ieee80211.h>
|
||||
#include <linux/semaphore.h>
|
||||
#include "aic_bsp_driver.h"
|
||||
|
||||
#define AICBSP_SDIO_NAME "aicbsp_sdio"
|
||||
#define SDIOWIFI_FUNC_BLOCKSIZE 512
|
||||
|
||||
#define SDIO_VENDOR_ID_AIC 0x8800
|
||||
#define SDIO_DEVICE_ID_AIC 0x0001
|
||||
#define SDIOWIFI_BYTEMODE_LEN_REG 0x02
|
||||
#define SDIOWIFI_INTR_CONFIG_REG 0x04
|
||||
#define SDIOWIFI_SLEEP_REG 0x05
|
||||
#define SDIOWIFI_WAKEUP_REG 0x09
|
||||
#define SDIOWIFI_FLOW_CTRL_REG 0x0A
|
||||
#define SDIOWIFI_REGISTER_BLOCK 0x0B
|
||||
#define SDIOWIFI_BYTEMODE_ENABLE_REG 0x11
|
||||
#define SDIOWIFI_BLOCK_CNT_REG 0x12
|
||||
#define SDIOWIFI_FLOWCTRL_MASK_REG 0x7F
|
||||
#define SDIOWIFI_WR_FIFO_ADDR 0x07
|
||||
#define SDIOWIFI_RD_FIFO_ADDR 0x08
|
||||
|
||||
#define SDIOWIFI_INTR_ENABLE_REG_V3 0x00
|
||||
#define SDIOWIFI_INTR_PENDING_REG_V3 0x01
|
||||
#define SDIOWIFI_INTR_TO_DEVICE_REG_V3 0x02
|
||||
#define SDIOWIFI_FLOW_CTRL_Q1_REG_V3 0x03
|
||||
#define SDIOWIFI_MISC_INT_STATUS_REG_V3 0x04
|
||||
#define SDIOWIFI_BYTEMODE_LEN_REG_V3 0x05
|
||||
#define SDIOWIFI_BYTEMODE_LEN_MSB_REG_V3 0x06
|
||||
#define SDIOWIFI_BYTEMODE_ENABLE_REG_V3 0x07
|
||||
#define SDIOWIFI_MISC_CTRL_REG_V3 0x08
|
||||
#define SDIOWIFI_FLOW_CTRL_Q2_REG_V3 0x09
|
||||
#define SDIOWIFI_CLK_TEST_RESULT_REG_V3 0x0A
|
||||
#define SDIOWIFI_RD_FIFO_ADDR_V3 0x0F
|
||||
#define SDIOWIFI_WR_FIFO_ADDR_V3 0x10
|
||||
|
||||
#define SDIOCLK_FREE_RUNNING_BIT (1 << 6)
|
||||
|
||||
#define SDIOWIFI_PWR_CTRL_INTERVAL 30
|
||||
#define FLOW_CTRL_RETRY_COUNT 50
|
||||
#define BUFFER_SIZE 1536
|
||||
#define TAIL_LEN 4
|
||||
#define TXQLEN (2048*4)
|
||||
|
||||
#define SDIO_SLEEP_ST 0
|
||||
#define SDIO_ACTIVE_ST 1
|
||||
|
||||
typedef enum {
|
||||
SDIO_TYPE_DATA = 0X00,
|
||||
SDIO_TYPE_CFG = 0X10,
|
||||
SDIO_TYPE_CFG_CMD_RSP = 0X11,
|
||||
SDIO_TYPE_CFG_DATA_CFM = 0X12
|
||||
} sdio_type;
|
||||
|
||||
enum AICWF_IC{
|
||||
PRODUCT_ID_AIC8801 = 0,
|
||||
PRODUCT_ID_AIC8800DC,
|
||||
PRODUCT_ID_AIC8800DW,
|
||||
PRODUCT_ID_AIC8800D80
|
||||
};
|
||||
|
||||
struct aic_sdio_reg {
|
||||
u8 bytemode_len_reg;
|
||||
u8 intr_config_reg;
|
||||
u8 sleep_reg;
|
||||
u8 wakeup_reg;
|
||||
u8 flow_ctrl_reg;
|
||||
u8 flowctrl_mask_reg;
|
||||
u8 register_block;
|
||||
u8 bytemode_enable_reg;
|
||||
u8 block_cnt_reg;
|
||||
u8 misc_int_status_reg;
|
||||
u8 rd_fifo_addr;
|
||||
u8 wr_fifo_addr;
|
||||
};
|
||||
|
||||
struct aic_sdio_dev {
|
||||
struct rwnx_cmd_mgr cmd_mgr;
|
||||
struct sdio_func *func;
|
||||
struct sdio_func *func_msg;
|
||||
struct device *dev;
|
||||
struct aicwf_bus *bus_if;
|
||||
|
||||
struct aicwf_rx_priv *rx_priv;
|
||||
struct aicwf_tx_priv *tx_priv;
|
||||
u32 state;
|
||||
|
||||
#if defined(CONFIG_SDIO_PWRCTRL)
|
||||
//for sdio pwr ctrl
|
||||
struct timer_list timer;
|
||||
uint active_duration;
|
||||
struct completion pwrctrl_trgg;
|
||||
struct task_struct *pwrctl_tsk;
|
||||
spinlock_t pwrctl_lock;
|
||||
struct semaphore pwrctl_wakeup_sema;
|
||||
#endif
|
||||
u16 chipid;
|
||||
struct aic_sdio_reg sdio_reg;
|
||||
void (*sdio_hal_irqhandler) (struct sdio_func *func);
|
||||
};
|
||||
|
||||
void *aicbsp_get_drvdata(void *args);
|
||||
int aicwf_sdio_writeb(struct aic_sdio_dev *sdiodev, uint regaddr, u8 val);
|
||||
void aicwf_sdio_hal_irqhandler(struct sdio_func *func);
|
||||
void aicwf_sdio_hal_irqhandler_func2(struct sdio_func *func);
|
||||
#if defined(CONFIG_SDIO_PWRCTRL)
|
||||
void aicwf_sdio_pwrctl_timer(struct aic_sdio_dev *sdiodev, uint duration);
|
||||
int aicwf_sdio_pwr_stctl(struct aic_sdio_dev *sdiodev, uint target);
|
||||
#endif
|
||||
void aicwf_sdio_reg_init(struct aic_sdio_dev *sdiodev);
|
||||
int aicwf_sdio_func_init(struct aic_sdio_dev *sdiodev);
|
||||
int aicwf_sdiov3_func_init(struct aic_sdio_dev *sdiodev);
|
||||
void aicwf_sdio_func_deinit(struct aic_sdio_dev *sdiodev);
|
||||
int aicwf_sdio_flow_ctrl(struct aic_sdio_dev *sdiodev);
|
||||
int aicwf_sdio_recv_pkt(struct aic_sdio_dev *sdiodev, struct sk_buff *skbbuf, u32 size, u8 msg);
|
||||
int aicwf_sdio_send_pkt(struct aic_sdio_dev *sdiodev, u8 *buf, uint count);
|
||||
void *aicwf_sdio_bus_init(struct aic_sdio_dev *sdiodev);
|
||||
void aicwf_sdio_release(struct aic_sdio_dev *sdiodev);
|
||||
void aicbsp_sdio_exit(void);
|
||||
int aicbsp_sdio_init(void);
|
||||
void aicbsp_sdio_release(struct aic_sdio_dev *sdiodev);
|
||||
int aicwf_sdio_txpkt(struct aic_sdio_dev *sdiodev, struct sk_buff *pkt);
|
||||
int aicwf_sdio_bustx_thread(void *data);
|
||||
int aicwf_sdio_busrx_thread(void *data);
|
||||
int aicwf_sdio_aggr(struct aicwf_tx_priv *tx_priv, struct sk_buff *pkt);
|
||||
int aicwf_sdio_send(struct aicwf_tx_priv *tx_priv);
|
||||
void aicwf_sdio_aggr_send(struct aicwf_tx_priv *tx_priv);
|
||||
void aicwf_sdio_aggrbuf_reset(struct aicwf_tx_priv *tx_priv);
|
||||
extern void aicwf_hostif_ready(void);
|
||||
int aicwf_process_rxframes(struct aicwf_rx_priv *rx_priv);
|
||||
uint8_t crc8_ponl_107(uint8_t *p_buffer, uint16_t cal_size);
|
||||
#endif /* AICWF_SDIO_SUPPORT */
|
||||
|
||||
#endif /*_AICWF_SDMMC_H_*/
|
||||
463
drivers/net/wireless/aic8800/aic8800_bsp/aicsdio_txrxif.c
Normal file
463
drivers/net/wireless/aic8800/aic8800_bsp/aicsdio_txrxif.c
Normal file
@@ -0,0 +1,463 @@
|
||||
/**
|
||||
* aicwf_bus.c
|
||||
*
|
||||
* bus function declarations
|
||||
*
|
||||
* Copyright (C) AICSemi 2018-2020
|
||||
*/
|
||||
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/semaphore.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include "aicsdio_txrxif.h"
|
||||
#include "aic_bsp_driver.h"
|
||||
|
||||
int aicwf_bus_init(uint bus_hdrlen, struct device *dev)
|
||||
{
|
||||
int ret = 0;
|
||||
struct aicwf_bus *bus_if;
|
||||
|
||||
if (!dev) {
|
||||
txrx_err("device not found\n");
|
||||
return -1;
|
||||
}
|
||||
bus_if = dev_get_drvdata(dev);
|
||||
bus_if->cmd_buf = kzalloc(CMD_BUF_MAX, GFP_KERNEL);
|
||||
if (!bus_if->cmd_buf) {
|
||||
ret = -ENOMEM;
|
||||
txrx_err("proto_attach failed\n");
|
||||
goto fail;
|
||||
}
|
||||
memset(bus_if->cmd_buf, '\0', CMD_BUF_MAX);
|
||||
|
||||
init_completion(&bus_if->bustx_trgg);
|
||||
init_completion(&bus_if->busrx_trgg);
|
||||
#ifdef AICWF_SDIO_SUPPORT
|
||||
bus_if->bustx_thread = kthread_run(aicwf_sdio_bustx_thread, (void *)bus_if, "aicwf_bustx_thread");
|
||||
bus_if->busrx_thread = kthread_run(aicwf_sdio_busrx_thread, (void *)bus_if->bus_priv.sdio->rx_priv, "aicwf_busrx_thread");
|
||||
#endif
|
||||
|
||||
if (IS_ERR(bus_if->bustx_thread)) {
|
||||
bus_if->bustx_thread = NULL;
|
||||
txrx_err("aicwf_bustx_thread run fail\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (IS_ERR(bus_if->busrx_thread)) {
|
||||
bus_if->busrx_thread = NULL;
|
||||
txrx_err("aicwf_bustx_thread run fail\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return ret;
|
||||
fail:
|
||||
aicwf_bus_deinit(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void aicwf_bus_deinit(struct device *dev)
|
||||
{
|
||||
struct aicwf_bus *bus_if;
|
||||
struct aic_sdio_dev *sdiodev;
|
||||
|
||||
if (!dev) {
|
||||
txrx_err("device not found\n");
|
||||
return;
|
||||
}
|
||||
sdio_dbg("%s", __func__);
|
||||
bus_if = aicbsp_get_drvdata(dev);
|
||||
aicwf_bus_stop(bus_if);
|
||||
|
||||
sdiodev = bus_if->bus_priv.sdio;
|
||||
|
||||
if (bus_if->cmd_buf) {
|
||||
kfree(bus_if->cmd_buf);
|
||||
bus_if->cmd_buf = NULL;
|
||||
}
|
||||
|
||||
if (bus_if->bustx_thread) {
|
||||
complete_all(&bus_if->bustx_trgg);
|
||||
kthread_stop(bus_if->bustx_thread);
|
||||
bus_if->bustx_thread = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void aicwf_frame_tx(void *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct aic_sdio_dev *sdiodev = (struct aic_sdio_dev *)dev;
|
||||
aicwf_bus_txdata(sdiodev->bus_if, skb);
|
||||
}
|
||||
|
||||
struct aicwf_tx_priv *aicwf_tx_init(void *arg)
|
||||
{
|
||||
struct aicwf_tx_priv *tx_priv;
|
||||
|
||||
tx_priv = kzalloc(sizeof(struct aicwf_tx_priv), GFP_KERNEL);
|
||||
if (!tx_priv)
|
||||
return NULL;
|
||||
|
||||
tx_priv->sdiodev = (struct aic_sdio_dev *)arg;
|
||||
|
||||
atomic_set(&tx_priv->aggr_count, 0);
|
||||
tx_priv->aggr_buf = dev_alloc_skb(MAX_AGGR_TXPKT_LEN);
|
||||
if (!tx_priv->aggr_buf) {
|
||||
txrx_err("Alloc bus->txdata_buf failed!\n");
|
||||
kfree(tx_priv);
|
||||
return NULL;
|
||||
}
|
||||
tx_priv->head = tx_priv->aggr_buf->data;
|
||||
tx_priv->tail = tx_priv->aggr_buf->data;
|
||||
|
||||
return tx_priv;
|
||||
}
|
||||
|
||||
void aicwf_tx_deinit(struct aicwf_tx_priv *tx_priv)
|
||||
{
|
||||
if (tx_priv && tx_priv->aggr_buf)
|
||||
dev_kfree_skb(tx_priv->aggr_buf);
|
||||
|
||||
kfree(tx_priv);
|
||||
//tx_priv = NULL;
|
||||
}
|
||||
|
||||
static bool aicwf_another_ptk(struct sk_buff *skb)
|
||||
{
|
||||
u8 *data;
|
||||
u16 aggr_len = 0;
|
||||
|
||||
if (skb->data == NULL || skb->len == 0) {
|
||||
return false;
|
||||
}
|
||||
data = skb->data;
|
||||
aggr_len = (*skb->data | (*(skb->data + 1) << 8));
|
||||
if (aggr_len == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int aicwf_process_rxframes(struct aicwf_rx_priv *rx_priv)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long flags = 0;
|
||||
struct sk_buff *skb = NULL;
|
||||
u16 pkt_len = 0;
|
||||
struct sk_buff *skb_inblock = NULL;
|
||||
u16 aggr_len = 0, adjust_len = 0;
|
||||
u8 *data = NULL;
|
||||
|
||||
while (1) {
|
||||
spin_lock_irqsave(&rx_priv->rxqlock, flags);
|
||||
if (aicwf_is_framequeue_empty(&rx_priv->rxq)) {
|
||||
spin_unlock_irqrestore(&rx_priv->rxqlock, flags);
|
||||
break;
|
||||
}
|
||||
skb = aicwf_frame_dequeue(&rx_priv->rxq);
|
||||
spin_unlock_irqrestore(&rx_priv->rxqlock, flags);
|
||||
if (skb == NULL) {
|
||||
txrx_err("skb_error\r\n");
|
||||
break;
|
||||
}
|
||||
while (aicwf_another_ptk(skb)) {
|
||||
data = skb->data;
|
||||
pkt_len = (*skb->data | (*(skb->data + 1) << 8));
|
||||
|
||||
if ((skb->data[2] & SDIO_TYPE_CFG) != SDIO_TYPE_CFG) { // type : data
|
||||
aggr_len = pkt_len + RX_HWHRD_LEN;
|
||||
|
||||
if (aggr_len & (RX_ALIGNMENT - 1))
|
||||
adjust_len = roundup(aggr_len, RX_ALIGNMENT);
|
||||
else
|
||||
adjust_len = aggr_len;
|
||||
|
||||
skb_inblock = __dev_alloc_skb(aggr_len + CCMP_OR_WEP_INFO, GFP_KERNEL);//8 is for ccmp mic or wep icv
|
||||
if (skb_inblock == NULL) {
|
||||
txrx_err("no more space!\n");
|
||||
aicwf_dev_skb_free(skb);
|
||||
return -EBADE;
|
||||
}
|
||||
|
||||
skb_put(skb_inblock, aggr_len);
|
||||
memcpy(skb_inblock->data, data, aggr_len);
|
||||
#if 0
|
||||
rwnx_rxdataind_aicwf(rx_priv->sdiodev->rwnx_hw, skb_inblock, (void *)rx_priv);
|
||||
#endif
|
||||
skb_pull(skb, adjust_len);
|
||||
} else { // type : config
|
||||
aggr_len = pkt_len;
|
||||
|
||||
if (aggr_len & (RX_ALIGNMENT - 1))
|
||||
adjust_len = roundup(aggr_len, RX_ALIGNMENT);
|
||||
else
|
||||
adjust_len = aggr_len;
|
||||
|
||||
skb_inblock = __dev_alloc_skb(aggr_len+4, GFP_KERNEL);
|
||||
if (skb_inblock == NULL) {
|
||||
txrx_err("no more space!\n");
|
||||
aicwf_dev_skb_free(skb);
|
||||
return -EBADE;
|
||||
}
|
||||
|
||||
skb_put(skb_inblock, aggr_len+4);
|
||||
memcpy(skb_inblock->data, data, aggr_len+4);
|
||||
if ((*(skb_inblock->data + 2) & 0x7f) == SDIO_TYPE_CFG_CMD_RSP)
|
||||
rwnx_rx_handle_msg(rx_priv->sdiodev, (struct ipc_e2a_msg *)(skb_inblock->data + 4));
|
||||
#if 0
|
||||
if ((*(skb_inblock->data + 2) & 0x7f) == SDIO_TYPE_CFG_DATA_CFM)
|
||||
aicwf_sdio_host_tx_cfm_handler(&(rx_priv->sdiodev->rwnx_hw->sdio_env), (u32 *)(skb_inblock->data + 4));
|
||||
#endif
|
||||
skb_pull(skb, adjust_len+4);
|
||||
}
|
||||
}
|
||||
|
||||
/* skb_inblock no used currently, just free it! */
|
||||
dev_kfree_skb(skb_inblock);
|
||||
dev_kfree_skb(skb);
|
||||
atomic_dec(&rx_priv->rx_cnt);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_SDIO_PWRCTRL)
|
||||
aicwf_sdio_pwr_stctl(rx_priv->sdiodev, SDIO_ACTIVE_ST);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct recv_msdu *aicwf_rxframe_queue_init(struct list_head *q, int qsize)
|
||||
{
|
||||
int i;
|
||||
struct recv_msdu *req, *reqs;
|
||||
|
||||
reqs = vmalloc(qsize*sizeof(struct recv_msdu));
|
||||
if (reqs == NULL)
|
||||
return NULL;
|
||||
|
||||
req = reqs;
|
||||
for (i = 0; i < qsize; i++) {
|
||||
INIT_LIST_HEAD(&req->rxframe_list);
|
||||
list_add(&req->rxframe_list, q);
|
||||
req->len = 0;
|
||||
req++;
|
||||
}
|
||||
|
||||
return reqs;
|
||||
}
|
||||
|
||||
struct aicwf_rx_priv *aicwf_rx_init(void *arg)
|
||||
{
|
||||
struct aicwf_rx_priv *rx_priv;
|
||||
rx_priv = kzalloc(sizeof(struct aicwf_rx_priv), GFP_KERNEL);
|
||||
if (!rx_priv)
|
||||
return NULL;
|
||||
|
||||
rx_priv->sdiodev = (struct aic_sdio_dev *)arg;
|
||||
aicwf_frame_queue_init(&rx_priv->rxq, 1, MAX_RXQLEN);
|
||||
spin_lock_init(&rx_priv->rxqlock);
|
||||
atomic_set(&rx_priv->rx_cnt, 0);
|
||||
|
||||
INIT_LIST_HEAD(&rx_priv->rxframes_freequeue);
|
||||
spin_lock_init(&rx_priv->freeq_lock);
|
||||
rx_priv->recv_frames = aicwf_rxframe_queue_init(&rx_priv->rxframes_freequeue, MAX_REORD_RXFRAME);
|
||||
if (!rx_priv->recv_frames) {
|
||||
txrx_err("no enough buffer for free recv frame queue!\n");
|
||||
kfree(rx_priv);
|
||||
return NULL;
|
||||
}
|
||||
spin_lock_init(&rx_priv->stas_reord_lock);
|
||||
INIT_LIST_HEAD(&rx_priv->stas_reord_list);
|
||||
|
||||
return rx_priv;
|
||||
}
|
||||
|
||||
|
||||
static void aicwf_recvframe_queue_deinit(struct list_head *q)
|
||||
{
|
||||
struct recv_msdu *req, *next;
|
||||
|
||||
list_for_each_entry_safe(req, next, q, rxframe_list) {
|
||||
list_del_init(&req->rxframe_list);
|
||||
}
|
||||
}
|
||||
|
||||
void aicwf_rx_deinit(struct aicwf_rx_priv *rx_priv)
|
||||
{
|
||||
if (rx_priv->sdiodev->bus_if->busrx_thread) {
|
||||
complete_all(&rx_priv->sdiodev->bus_if->busrx_trgg);
|
||||
kthread_stop(rx_priv->sdiodev->bus_if->busrx_thread);
|
||||
rx_priv->sdiodev->bus_if->busrx_thread = NULL;
|
||||
}
|
||||
|
||||
aicwf_frame_queue_flush(&rx_priv->rxq);
|
||||
aicwf_recvframe_queue_deinit(&rx_priv->rxframes_freequeue);
|
||||
if (rx_priv->recv_frames)
|
||||
vfree(rx_priv->recv_frames);
|
||||
|
||||
kfree(rx_priv);
|
||||
//rx_priv = NULL;
|
||||
}
|
||||
|
||||
bool aicwf_rxframe_enqueue(struct device *dev, struct frame_queue *q, struct sk_buff *pkt)
|
||||
{
|
||||
return aicwf_frame_enq(dev, q, pkt, 0);
|
||||
}
|
||||
|
||||
|
||||
void aicwf_dev_skb_free(struct sk_buff *skb)
|
||||
{
|
||||
if (!skb)
|
||||
return;
|
||||
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
|
||||
static struct sk_buff *aicwf_frame_queue_penq(struct frame_queue *pq, int prio, struct sk_buff *p)
|
||||
{
|
||||
struct sk_buff_head *q;
|
||||
|
||||
if (pq->queuelist[prio].qlen >= pq->qmax)
|
||||
return NULL;
|
||||
|
||||
q = &pq->queuelist[prio];
|
||||
__skb_queue_tail(q, p);
|
||||
pq->qcnt++;
|
||||
if (pq->hi_prio < prio)
|
||||
pq->hi_prio = (u16)prio;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void aicwf_frame_queue_flush(struct frame_queue *pq)
|
||||
{
|
||||
int prio;
|
||||
struct sk_buff_head *q;
|
||||
struct sk_buff *p, *next;
|
||||
|
||||
for (prio = 0; prio < pq->num_prio; prio++) {
|
||||
q = &pq->queuelist[prio];
|
||||
skb_queue_walk_safe(q, p, next) {
|
||||
skb_unlink(p, q);
|
||||
aicwf_dev_skb_free(p);
|
||||
pq->qcnt--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void aicwf_frame_queue_init(struct frame_queue *pq, int num_prio, int max_len)
|
||||
{
|
||||
int prio;
|
||||
|
||||
memset(pq, 0, offsetof(struct frame_queue, queuelist) + (sizeof(struct sk_buff_head) * num_prio));
|
||||
pq->num_prio = (u16)num_prio;
|
||||
pq->qmax = (u16)max_len;
|
||||
|
||||
for (prio = 0; prio < num_prio; prio++) {
|
||||
skb_queue_head_init(&pq->queuelist[prio]);
|
||||
}
|
||||
}
|
||||
|
||||
struct sk_buff *aicwf_frame_queue_peek_tail(struct frame_queue *pq, int *prio_out)
|
||||
{
|
||||
int prio;
|
||||
|
||||
if (pq->qcnt == 0)
|
||||
return NULL;
|
||||
|
||||
for (prio = 0; prio < pq->hi_prio; prio++)
|
||||
if (!skb_queue_empty(&pq->queuelist[prio]))
|
||||
break;
|
||||
|
||||
if (prio_out)
|
||||
*prio_out = prio;
|
||||
|
||||
return skb_peek_tail(&pq->queuelist[prio]);
|
||||
}
|
||||
|
||||
bool aicwf_is_framequeue_empty(struct frame_queue *pq)
|
||||
{
|
||||
int prio, len = 0;
|
||||
|
||||
for (prio = 0; prio <= pq->hi_prio; prio++)
|
||||
len += pq->queuelist[prio].qlen;
|
||||
|
||||
if (len > 0)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
struct sk_buff *aicwf_frame_dequeue(struct frame_queue *pq)
|
||||
{
|
||||
struct sk_buff_head *q;
|
||||
struct sk_buff *p;
|
||||
int prio;
|
||||
|
||||
if (pq->qcnt == 0)
|
||||
return NULL;
|
||||
|
||||
while ((prio = pq->hi_prio) > 0 && skb_queue_empty(&pq->queuelist[prio]))
|
||||
pq->hi_prio--;
|
||||
|
||||
q = &pq->queuelist[prio];
|
||||
p = __skb_dequeue(q);
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
|
||||
pq->qcnt--;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static struct sk_buff *aicwf_skb_dequeue_tail(struct frame_queue *pq, int prio)
|
||||
{
|
||||
struct sk_buff_head *q = &pq->queuelist[prio];
|
||||
struct sk_buff *p = skb_dequeue_tail(q);
|
||||
|
||||
if (!p)
|
||||
return NULL;
|
||||
|
||||
pq->qcnt--;
|
||||
return p;
|
||||
}
|
||||
|
||||
bool aicwf_frame_enq(struct device *dev, struct frame_queue *q, struct sk_buff *pkt, int prio)
|
||||
{
|
||||
struct sk_buff *p = NULL;
|
||||
int prio_modified = -1;
|
||||
|
||||
if (q->queuelist[prio].qlen < q->qmax && q->qcnt < q->qmax) {
|
||||
aicwf_frame_queue_penq(q, prio, pkt);
|
||||
return true;
|
||||
}
|
||||
if (q->queuelist[prio].qlen >= q->qmax) {
|
||||
prio_modified = prio;
|
||||
} else if (q->qcnt >= q->qmax) {
|
||||
p = aicwf_frame_queue_peek_tail(q, &prio_modified);
|
||||
if (prio_modified > prio)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (prio_modified >= 0) {
|
||||
if (prio_modified == prio)
|
||||
return false;
|
||||
|
||||
p = aicwf_skb_dequeue_tail(q, prio_modified);
|
||||
aicwf_dev_skb_free(p);
|
||||
|
||||
p = aicwf_frame_queue_penq(q, prio_modified, pkt);
|
||||
if (p == NULL)
|
||||
txrx_err("failed\n");
|
||||
}
|
||||
|
||||
return p != NULL;
|
||||
}
|
||||
|
||||
|
||||
214
drivers/net/wireless/aic8800/aic8800_bsp/aicsdio_txrxif.h
Normal file
214
drivers/net/wireless/aic8800/aic8800_bsp/aicsdio_txrxif.h
Normal file
@@ -0,0 +1,214 @@
|
||||
/**
|
||||
* aicwf_txrxif.h
|
||||
*
|
||||
* bus function declarations
|
||||
*
|
||||
* Copyright (C) AICSemi 2018-2020
|
||||
*/
|
||||
|
||||
#ifndef _AICWF_TXRXIF_H_
|
||||
#define _AICWF_TXRXIF_H_
|
||||
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/sched.h>
|
||||
#include "aicsdio.h"
|
||||
|
||||
#define CMD_BUF_MAX 1536
|
||||
#define TXPKT_BLOCKSIZE 512
|
||||
#define MAX_AGGR_TXPKT_LEN (1536*4)
|
||||
#define CMD_TX_TIMEOUT 5000
|
||||
#define TX_ALIGNMENT 4
|
||||
|
||||
#define RX_HWHRD_LEN 60 //58->60 word allined
|
||||
#define CCMP_OR_WEP_INFO 8
|
||||
#define MAX_RXQLEN 2000
|
||||
#define RX_ALIGNMENT 4
|
||||
|
||||
#define DEBUG_ERROR_LEVEL 0
|
||||
#define DEBUG_DEBUG_LEVEL 1
|
||||
#define DEBUG_INFO_LEVEL 2
|
||||
|
||||
#define DBG_LEVEL DEBUG_DEBUG_LEVEL
|
||||
|
||||
#define txrx_err(fmt, ...) pr_err("aicbsp: txrx_err:<%s,%d>: " fmt, __func__, __LINE__, ##__VA_ARGS__)
|
||||
#define sdio_err(fmt, ...) pr_err("aicbsp: sdio_err:<%s,%d>: " fmt, __func__, __LINE__, ##__VA_ARGS__)
|
||||
#define usb_err(fmt, ...) pr_err("aicbsp: usb_err:<%s,%d>: " fmt, __func__, __LINE__, ##__VA_ARGS__)
|
||||
#if DBG_LEVEL >= DEBUG_DEBUG_LEVEL
|
||||
#define sdio_dbg(fmt, ...) printk("aicbsp: " fmt, ##__VA_ARGS__)
|
||||
#define usb_dbg(fmt, ...) printk("aicbsp: " fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define sdio_dbg(fmt, ...)
|
||||
#define usb_dbg(fmt, ...)
|
||||
#endif
|
||||
#if DBG_LEVEL >= DEBUG_INFO_LEVEL
|
||||
#define sdio_info(fmt, ...) printk("aicbsp: " fmt, ##__VA_ARGS__)
|
||||
#define usb_info(fmt, ...) printk("aicbsp: " fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define sdio_info(fmt, ...)
|
||||
#define usb_info(fmt, ...)
|
||||
#endif
|
||||
|
||||
enum aicwf_bus_state {
|
||||
BUS_DOWN_ST,
|
||||
BUS_UP_ST
|
||||
};
|
||||
|
||||
struct aicwf_bus_ops {
|
||||
int (*start) (struct device *dev);
|
||||
void (*stop) (struct device *dev);
|
||||
int (*txdata) (struct device *dev, struct sk_buff *skb);
|
||||
int (*txmsg) (struct device *dev, u8 *msg, uint len);
|
||||
};
|
||||
|
||||
struct frame_queue {
|
||||
u16 num_prio;
|
||||
u16 hi_prio;
|
||||
u16 qmax; /* max number of queued frames */
|
||||
u16 qcnt;
|
||||
struct sk_buff_head queuelist[8];
|
||||
};
|
||||
|
||||
struct aicwf_bus {
|
||||
union {
|
||||
struct aic_sdio_dev *sdio;
|
||||
struct aic_usb_dev *usb;
|
||||
} bus_priv;
|
||||
struct device *dev;
|
||||
struct aicwf_bus_ops *ops;
|
||||
enum aicwf_bus_state state;
|
||||
u8 *cmd_buf;
|
||||
struct completion bustx_trgg;
|
||||
struct completion busrx_trgg;
|
||||
struct task_struct *bustx_thread;
|
||||
struct task_struct *busrx_thread;
|
||||
};
|
||||
|
||||
struct aicwf_tx_priv {
|
||||
#ifdef AICWF_SDIO_SUPPORT
|
||||
struct aic_sdio_dev *sdiodev;
|
||||
int fw_avail_bufcnt;
|
||||
//for cmd tx
|
||||
u8 *cmd_buf;
|
||||
uint cmd_len;
|
||||
bool cmd_txstate;
|
||||
bool cmd_tx_succ;
|
||||
struct semaphore cmd_txsema;
|
||||
wait_queue_head_t cmd_txdone_wait;
|
||||
//for data tx
|
||||
atomic_t tx_pktcnt;
|
||||
|
||||
struct frame_queue txq;
|
||||
spinlock_t txqlock;
|
||||
struct semaphore txctl_sema;
|
||||
#endif
|
||||
#ifdef AICWF_USB_SUPPORT
|
||||
struct aic_usb_dev *usbdev;
|
||||
#endif
|
||||
struct sk_buff *aggr_buf;
|
||||
atomic_t aggr_count;
|
||||
u8 *head;
|
||||
u8 *tail;
|
||||
};
|
||||
|
||||
|
||||
#define MAX_REORD_RXFRAME 250
|
||||
#define REORDER_UPDATE_TIME 50
|
||||
#define AICWF_REORDER_WINSIZE 64
|
||||
#define SN_LESS(a, b) (((a-b)&0x800) != 0)
|
||||
#define SN_EQUAL(a, b) (a == b)
|
||||
|
||||
struct reord_ctrl {
|
||||
struct aicwf_rx_priv *rx_priv;
|
||||
u8 enable;
|
||||
u16 ind_sn;
|
||||
u8 wsize_b;
|
||||
spinlock_t reord_list_lock;
|
||||
struct list_head reord_list;
|
||||
struct timer_list reord_timer;
|
||||
struct work_struct reord_timer_work;
|
||||
};
|
||||
|
||||
struct reord_ctrl_info {
|
||||
u8 mac_addr[6];
|
||||
struct reord_ctrl preorder_ctrl[8];
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
struct recv_msdu {
|
||||
struct sk_buff *pkt;
|
||||
u8 tid;
|
||||
u16 seq_num;
|
||||
uint len;
|
||||
u8 *rx_data;
|
||||
//for pending rx reorder list
|
||||
struct list_head reord_pending_list;
|
||||
//for total frame list, when rxframe from busif, dequeue, when submit frame to net, enqueue
|
||||
struct list_head rxframe_list;
|
||||
struct reord_ctrl *preorder_ctrl;
|
||||
};
|
||||
|
||||
struct aicwf_rx_priv {
|
||||
struct aic_sdio_dev *sdiodev;
|
||||
void *rwnx_vif;
|
||||
atomic_t rx_cnt;
|
||||
u32 data_len;
|
||||
spinlock_t rxqlock;
|
||||
struct frame_queue rxq;
|
||||
|
||||
spinlock_t freeq_lock;
|
||||
struct list_head rxframes_freequeue;
|
||||
struct list_head stas_reord_list;
|
||||
spinlock_t stas_reord_lock;
|
||||
struct recv_msdu *recv_frames;
|
||||
};
|
||||
|
||||
static inline int aicwf_bus_start(struct aicwf_bus *bus)
|
||||
{
|
||||
return bus->ops->start(bus->dev);
|
||||
}
|
||||
|
||||
static inline void aicwf_bus_stop(struct aicwf_bus *bus)
|
||||
{
|
||||
bus->ops->stop(bus->dev);
|
||||
}
|
||||
|
||||
static inline int aicwf_bus_txdata(struct aicwf_bus *bus, struct sk_buff *skb)
|
||||
{
|
||||
return bus->ops->txdata(bus->dev, skb);
|
||||
}
|
||||
|
||||
static inline int aicwf_bus_txmsg(struct aicwf_bus *bus, u8 *msg, uint len)
|
||||
{
|
||||
return bus->ops->txmsg(bus->dev, msg, len);
|
||||
}
|
||||
|
||||
static inline void aicwf_sched_timeout(u32 millisec)
|
||||
{
|
||||
ulong timeout = 0, expires = 0;
|
||||
expires = jiffies + msecs_to_jiffies(millisec);
|
||||
timeout = millisec;
|
||||
|
||||
while (timeout) {
|
||||
timeout = schedule_timeout(timeout);
|
||||
if (time_after(jiffies, expires))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int aicwf_bus_init(uint bus_hdrlen, struct device *dev);
|
||||
void aicwf_bus_deinit(struct device *dev);
|
||||
void aicwf_tx_deinit(struct aicwf_tx_priv *tx_priv);
|
||||
void aicwf_rx_deinit(struct aicwf_rx_priv *rx_priv);
|
||||
struct aicwf_tx_priv *aicwf_tx_init(void *arg);
|
||||
struct aicwf_rx_priv *aicwf_rx_init(void *arg);
|
||||
void aicwf_frame_queue_init(struct frame_queue *pq, int num_prio, int max_len);
|
||||
void aicwf_frame_queue_flush(struct frame_queue *pq);
|
||||
bool aicwf_frame_enq(struct device *dev, struct frame_queue *q, struct sk_buff *pkt, int prio);
|
||||
bool aicwf_rxframe_enqueue(struct device *dev, struct frame_queue *q, struct sk_buff *pkt);
|
||||
bool aicwf_is_framequeue_empty(struct frame_queue *pq);
|
||||
void aicwf_frame_tx(void *dev, struct sk_buff *skb);
|
||||
void aicwf_dev_skb_free(struct sk_buff *skb);
|
||||
struct sk_buff *aicwf_frame_dequeue(struct frame_queue *pq);
|
||||
struct sk_buff *aicwf_frame_queue_peek_tail(struct frame_queue *pq, int *prio_out);
|
||||
|
||||
#endif /* _AICWF_TXRXIF_H_ */
|
||||
16138
drivers/net/wireless/aic8800/aic8800_bsp/aicwf_firmware_array.c
Normal file
16138
drivers/net/wireless/aic8800/aic8800_bsp/aicwf_firmware_array.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,3 @@
|
||||
int aicwf_get_firmware_array(char* fw_name, u32 **fw_buf);
|
||||
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
#include <linux/slab.h>
|
||||
#include "aicsdio_txrxif.h"
|
||||
#include "aic_bsp_driver.h"
|
||||
|
||||
struct prealloc_txq{
|
||||
int prealloced;
|
||||
void *txq;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
struct prealloc_txq prealloc_txq;
|
||||
#define MAX_TXQ_SIZE 30 * 1024
|
||||
|
||||
void *aicwf_prealloc_txq_alloc(size_t size)
|
||||
{
|
||||
|
||||
BUG_ON(size > MAX_TXQ_SIZE);
|
||||
|
||||
//check prealloc_txq.size
|
||||
if((int)prealloc_txq.size != (int)size)
|
||||
{
|
||||
AICWFDBG(LOGINFO, "%s size is diff will to be kzalloc \r\n", __func__);
|
||||
|
||||
if(prealloc_txq.txq != NULL)
|
||||
{
|
||||
AICWFDBG(LOGINFO, "%s txq to kfree \r\n", __func__);
|
||||
kfree(prealloc_txq.txq);
|
||||
prealloc_txq.txq = NULL;
|
||||
}
|
||||
|
||||
prealloc_txq.size = size;
|
||||
prealloc_txq.prealloced = 0;
|
||||
}
|
||||
|
||||
//check prealloc or not
|
||||
if(!prealloc_txq.prealloced)
|
||||
{
|
||||
prealloc_txq.txq = kzalloc(size, GFP_KERNEL);
|
||||
if(!prealloc_txq.txq){
|
||||
AICWFDBG(LOGERROR, "%s txq kzalloc fail \r\n", __func__);
|
||||
}else{
|
||||
AICWFDBG(LOGINFO, "%s txq kzalloc successful \r\n", __func__);
|
||||
prealloc_txq.prealloced = 1;
|
||||
}
|
||||
}else{
|
||||
AICWFDBG(LOGINFO, "%s txq not need to kzalloc \r\n", __func__);
|
||||
}
|
||||
|
||||
return prealloc_txq.txq;
|
||||
}
|
||||
void aicwf_prealloc_txq_free(void)
|
||||
{
|
||||
if(prealloc_txq.txq != NULL)
|
||||
{
|
||||
AICWFDBG(LOGINFO, "%s txq to kfree \r\n", __func__);
|
||||
kfree(prealloc_txq.txq);
|
||||
prealloc_txq.txq = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(aicwf_prealloc_txq_alloc);
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
|
||||
|
||||
void aicwf_prealloc_txq_free(void);
|
||||
|
||||
161
drivers/net/wireless/aic8800/aic8800_bsp/md5.c
Normal file
161
drivers/net/wireless/aic8800/aic8800_bsp/md5.c
Normal file
@@ -0,0 +1,161 @@
|
||||
#include <linux/memory.h>
|
||||
#include "md5.h"
|
||||
|
||||
unsigned char PADDING[]={0x80,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,0,0,0};
|
||||
|
||||
void MD5Init(MD5_CTX *context)
|
||||
{
|
||||
context->count[0] = 0;
|
||||
context->count[1] = 0;
|
||||
context->state[0] = 0x67452301;
|
||||
context->state[1] = 0xEFCDAB89;
|
||||
context->state[2] = 0x98BADCFE;
|
||||
context->state[3] = 0x10325476;
|
||||
}
|
||||
void MD5Update(MD5_CTX *context,unsigned char *input,unsigned int inputlen)
|
||||
{
|
||||
unsigned int i = 0,index = 0,partlen = 0;
|
||||
index = (context->count[0] >> 3) & 0x3F;
|
||||
partlen = 64 - index;
|
||||
context->count[0] += inputlen << 3;
|
||||
if(context->count[0] < (inputlen << 3))
|
||||
context->count[1]++;
|
||||
context->count[1] += inputlen >> 29;
|
||||
|
||||
if(inputlen >= partlen)
|
||||
{
|
||||
memcpy(&context->buffer[index],input,partlen);
|
||||
MD5Transform(context->state,context->buffer);
|
||||
for(i = partlen;i+64 <= inputlen;i+=64)
|
||||
MD5Transform(context->state,&input[i]);
|
||||
index = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
i = 0;
|
||||
}
|
||||
memcpy(&context->buffer[index],&input[i],inputlen-i);
|
||||
}
|
||||
void MD5Final(MD5_CTX *context,unsigned char digest[16])
|
||||
{
|
||||
unsigned int index = 0,padlen = 0;
|
||||
unsigned char bits[8];
|
||||
index = (context->count[0] >> 3) & 0x3F;
|
||||
padlen = (index < 56)?(56-index):(120-index);
|
||||
MD5Encode(bits,context->count,8);
|
||||
MD5Update(context,PADDING,padlen);
|
||||
MD5Update(context,bits,8);
|
||||
MD5Encode(digest,context->state,16);
|
||||
}
|
||||
void MD5Encode(unsigned char *output,unsigned int *input,unsigned int len)
|
||||
{
|
||||
unsigned int i = 0,j = 0;
|
||||
while(j < len)
|
||||
{
|
||||
output[j] = input[i] & 0xFF;
|
||||
output[j+1] = (input[i] >> 8) & 0xFF;
|
||||
output[j+2] = (input[i] >> 16) & 0xFF;
|
||||
output[j+3] = (input[i] >> 24) & 0xFF;
|
||||
i++;
|
||||
j+=4;
|
||||
}
|
||||
}
|
||||
void MD5Decode(unsigned int *output,unsigned char *input,unsigned int len)
|
||||
{
|
||||
unsigned int i = 0,j = 0;
|
||||
while(j < len)
|
||||
{
|
||||
output[i] = (input[j]) |
|
||||
(input[j+1] << 8) |
|
||||
(input[j+2] << 16) |
|
||||
(input[j+3] << 24);
|
||||
i++;
|
||||
j+=4;
|
||||
}
|
||||
}
|
||||
void MD5Transform(unsigned int state[4],unsigned char block[64])
|
||||
{
|
||||
unsigned int a = state[0];
|
||||
unsigned int b = state[1];
|
||||
unsigned int c = state[2];
|
||||
unsigned int d = state[3];
|
||||
unsigned int x[64];
|
||||
MD5Decode(x,block,64);
|
||||
FF(a, b, c, d, x[ 0], 7, 0xd76aa478); /* 1 */
|
||||
FF(d, a, b, c, x[ 1], 12, 0xe8c7b756); /* 2 */
|
||||
FF(c, d, a, b, x[ 2], 17, 0x242070db); /* 3 */
|
||||
FF(b, c, d, a, x[ 3], 22, 0xc1bdceee); /* 4 */
|
||||
FF(a, b, c, d, x[ 4], 7, 0xf57c0faf); /* 5 */
|
||||
FF(d, a, b, c, x[ 5], 12, 0x4787c62a); /* 6 */
|
||||
FF(c, d, a, b, x[ 6], 17, 0xa8304613); /* 7 */
|
||||
FF(b, c, d, a, x[ 7], 22, 0xfd469501); /* 8 */
|
||||
FF(a, b, c, d, x[ 8], 7, 0x698098d8); /* 9 */
|
||||
FF(d, a, b, c, x[ 9], 12, 0x8b44f7af); /* 10 */
|
||||
FF(c, d, a, b, x[10], 17, 0xffff5bb1); /* 11 */
|
||||
FF(b, c, d, a, x[11], 22, 0x895cd7be); /* 12 */
|
||||
FF(a, b, c, d, x[12], 7, 0x6b901122); /* 13 */
|
||||
FF(d, a, b, c, x[13], 12, 0xfd987193); /* 14 */
|
||||
FF(c, d, a, b, x[14], 17, 0xa679438e); /* 15 */
|
||||
FF(b, c, d, a, x[15], 22, 0x49b40821); /* 16 */
|
||||
|
||||
/* Round 2 */
|
||||
GG(a, b, c, d, x[ 1], 5, 0xf61e2562); /* 17 */
|
||||
GG(d, a, b, c, x[ 6], 9, 0xc040b340); /* 18 */
|
||||
GG(c, d, a, b, x[11], 14, 0x265e5a51); /* 19 */
|
||||
GG(b, c, d, a, x[ 0], 20, 0xe9b6c7aa); /* 20 */
|
||||
GG(a, b, c, d, x[ 5], 5, 0xd62f105d); /* 21 */
|
||||
GG(d, a, b, c, x[10], 9, 0x2441453); /* 22 */
|
||||
GG(c, d, a, b, x[15], 14, 0xd8a1e681); /* 23 */
|
||||
GG(b, c, d, a, x[ 4], 20, 0xe7d3fbc8); /* 24 */
|
||||
GG(a, b, c, d, x[ 9], 5, 0x21e1cde6); /* 25 */
|
||||
GG(d, a, b, c, x[14], 9, 0xc33707d6); /* 26 */
|
||||
GG(c, d, a, b, x[ 3], 14, 0xf4d50d87); /* 27 */
|
||||
GG(b, c, d, a, x[ 8], 20, 0x455a14ed); /* 28 */
|
||||
GG(a, b, c, d, x[13], 5, 0xa9e3e905); /* 29 */
|
||||
GG(d, a, b, c, x[ 2], 9, 0xfcefa3f8); /* 30 */
|
||||
GG(c, d, a, b, x[ 7], 14, 0x676f02d9); /* 31 */
|
||||
GG(b, c, d, a, x[12], 20, 0x8d2a4c8a); /* 32 */
|
||||
|
||||
/* Round 3 */
|
||||
HH(a, b, c, d, x[ 5], 4, 0xfffa3942); /* 33 */
|
||||
HH(d, a, b, c, x[ 8], 11, 0x8771f681); /* 34 */
|
||||
HH(c, d, a, b, x[11], 16, 0x6d9d6122); /* 35 */
|
||||
HH(b, c, d, a, x[14], 23, 0xfde5380c); /* 36 */
|
||||
HH(a, b, c, d, x[ 1], 4, 0xa4beea44); /* 37 */
|
||||
HH(d, a, b, c, x[ 4], 11, 0x4bdecfa9); /* 38 */
|
||||
HH(c, d, a, b, x[ 7], 16, 0xf6bb4b60); /* 39 */
|
||||
HH(b, c, d, a, x[10], 23, 0xbebfbc70); /* 40 */
|
||||
HH(a, b, c, d, x[13], 4, 0x289b7ec6); /* 41 */
|
||||
HH(d, a, b, c, x[ 0], 11, 0xeaa127fa); /* 42 */
|
||||
HH(c, d, a, b, x[ 3], 16, 0xd4ef3085); /* 43 */
|
||||
HH(b, c, d, a, x[ 6], 23, 0x4881d05); /* 44 */
|
||||
HH(a, b, c, d, x[ 9], 4, 0xd9d4d039); /* 45 */
|
||||
HH(d, a, b, c, x[12], 11, 0xe6db99e5); /* 46 */
|
||||
HH(c, d, a, b, x[15], 16, 0x1fa27cf8); /* 47 */
|
||||
HH(b, c, d, a, x[ 2], 23, 0xc4ac5665); /* 48 */
|
||||
|
||||
/* Round 4 */
|
||||
II(a, b, c, d, x[ 0], 6, 0xf4292244); /* 49 */
|
||||
II(d, a, b, c, x[ 7], 10, 0x432aff97); /* 50 */
|
||||
II(c, d, a, b, x[14], 15, 0xab9423a7); /* 51 */
|
||||
II(b, c, d, a, x[ 5], 21, 0xfc93a039); /* 52 */
|
||||
II(a, b, c, d, x[12], 6, 0x655b59c3); /* 53 */
|
||||
II(d, a, b, c, x[ 3], 10, 0x8f0ccc92); /* 54 */
|
||||
II(c, d, a, b, x[10], 15, 0xffeff47d); /* 55 */
|
||||
II(b, c, d, a, x[ 1], 21, 0x85845dd1); /* 56 */
|
||||
II(a, b, c, d, x[ 8], 6, 0x6fa87e4f); /* 57 */
|
||||
II(d, a, b, c, x[15], 10, 0xfe2ce6e0); /* 58 */
|
||||
II(c, d, a, b, x[ 6], 15, 0xa3014314); /* 59 */
|
||||
II(b, c, d, a, x[13], 21, 0x4e0811a1); /* 60 */
|
||||
II(a, b, c, d, x[ 4], 6, 0xf7537e82); /* 61 */
|
||||
II(d, a, b, c, x[11], 10, 0xbd3af235); /* 62 */
|
||||
II(c, d, a, b, x[ 2], 15, 0x2ad7d2bb); /* 63 */
|
||||
II(b, c, d, a, x[ 9], 21, 0xeb86d391); /* 64 */
|
||||
state[0] += a;
|
||||
state[1] += b;
|
||||
state[2] += c;
|
||||
state[3] += d;
|
||||
}
|
||||
48
drivers/net/wireless/aic8800/aic8800_bsp/md5.h
Normal file
48
drivers/net/wireless/aic8800/aic8800_bsp/md5.h
Normal file
@@ -0,0 +1,48 @@
|
||||
#ifndef MD5_H
|
||||
#define MD5_H
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int count[2];
|
||||
unsigned int state[4];
|
||||
unsigned char buffer[64];
|
||||
}MD5_CTX;
|
||||
|
||||
|
||||
#define F(x,y,z) ((x & y) | (~x & z))
|
||||
#define G(x,y,z) ((x & z) | (y & ~z))
|
||||
#define H(x,y,z) (x^y^z)
|
||||
#define I(x,y,z) (y ^ (x | ~z))
|
||||
#define ROTATE_LEFT(x,n) ((x << n) | (x >> (32-n)))
|
||||
#define FF(a,b,c,d,x,s,ac) \
|
||||
{ \
|
||||
a += F(b,c,d) + x + ac; \
|
||||
a = ROTATE_LEFT(a,s); \
|
||||
a += b; \
|
||||
}
|
||||
#define GG(a,b,c,d,x,s,ac) \
|
||||
{ \
|
||||
a += G(b,c,d) + x + ac; \
|
||||
a = ROTATE_LEFT(a,s); \
|
||||
a += b; \
|
||||
}
|
||||
#define HH(a,b,c,d,x,s,ac) \
|
||||
{ \
|
||||
a += H(b,c,d) + x + ac; \
|
||||
a = ROTATE_LEFT(a,s); \
|
||||
a += b; \
|
||||
}
|
||||
#define II(a,b,c,d,x,s,ac) \
|
||||
{ \
|
||||
a += I(b,c,d) + x + ac; \
|
||||
a = ROTATE_LEFT(a,s); \
|
||||
a += b; \
|
||||
}
|
||||
void MD5Init(MD5_CTX *context);
|
||||
void MD5Update(MD5_CTX *context,unsigned char *input,unsigned int inputlen);
|
||||
void MD5Final(MD5_CTX *context,unsigned char digest[16]);
|
||||
void MD5Transform(unsigned int state[4],unsigned char block[64]);
|
||||
void MD5Encode(unsigned char *output,unsigned int *input,unsigned int len);
|
||||
void MD5Decode(unsigned int *output,unsigned char *input,unsigned int len);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,4 @@
|
||||
#define RWNX_VERS_REV "241c091M (master)"
|
||||
#define RWNX_VERS_MOD "6.4.3.0"
|
||||
#define RWNX_VERS_BANNER "rwnx v6.4.3.0 - - 241c091M (master)"
|
||||
#define RELEASE_DATE "2023_0904_1726"
|
||||
5
drivers/net/wireless/aic8800/aic8800_btlpm/Kconfig
Normal file
5
drivers/net/wireless/aic8800/aic8800_btlpm/Kconfig
Normal file
@@ -0,0 +1,5 @@
|
||||
config AIC8800_BTLPM_SUPPORT
|
||||
tristate "AIC8800 bluetooth Support"
|
||||
help
|
||||
This is support for aic bluetooh driver.
|
||||
|
||||
80
drivers/net/wireless/aic8800/aic8800_btlpm/Makefile
Normal file
80
drivers/net/wireless/aic8800/aic8800_btlpm/Makefile
Normal file
@@ -0,0 +1,80 @@
|
||||
CONFIG_AIC8800_BTLPM_SUPPORT = m
|
||||
|
||||
obj-$(CONFIG_AIC8800_BTLPM_SUPPORT) := aic8800_btlpm.o
|
||||
|
||||
ccflags-y += -I$(srctree)/$(src)/../aic8800_bsp
|
||||
|
||||
aic8800_btlpm-y := \
|
||||
aic_bluetooth_main.o \
|
||||
rfkill.o \
|
||||
lpm.o
|
||||
|
||||
# Platform support list
|
||||
CONFIG_PLATFORM_ROCKCHIP ?= n
|
||||
CONFIG_PLATFORM_ALLWINNER ?= n
|
||||
CONFIG_PLATFORM_AMLOGIC ?= n
|
||||
CONFIG_PLATFORM_UBUNTU ?= y
|
||||
|
||||
ccflags-y += -DAIC_TRACE_INCLUDE_PATH=$(src)
|
||||
|
||||
ifeq ($(CONFIG_PLATFORM_ROCKCHIP), y)
|
||||
KDIR ?= /home/yaya/E/Rockchip/3229/Android9/rk3229_android9.0_box/kernel
|
||||
ARCH ?= arm
|
||||
CROSS_COMPILE ?= /home/yaya/E/Rockchip/3229/Android9/rk3229_android9.0_box/prebuilts/gcc/linux-x86/arm/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-
|
||||
#KDIR ?= /home/yaya/E/Rockchip/3229/Android10/SDK/kernel/
|
||||
#ARCH ?= arm
|
||||
#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3229/Android10/SDK/prebuilts/gcc/linux-x86/arm/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-
|
||||
#KDIR ?= /home/yaya/E/Rockchip/3288/Android10/kernel/kernel/
|
||||
#ARCH ?= arm
|
||||
#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3288/Android10/tool/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux#-gnueabihf-
|
||||
#KDIR ?= /home/yaya/E/Rockchip/3229/Android7/RK3229_ANDROID7.1_v1.01_20170914/rk3229_Android7.1_v1.01_xml0914/kernel
|
||||
#ARCH ?= arm
|
||||
#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3229/Android7/RK3229_ANDROID7.1_v1.01_20170914/rk3229_Android7.1_v1.01_xml0914/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-
|
||||
#KDIR ?= /home/yaya/E/Rockchip/3328/Android9/SDK/SDK/kernel
|
||||
#ARCH ?= arm64
|
||||
#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3328/Android9/SDK/SDK/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
|
||||
|
||||
ccflags-$(CONFIG_PLATFORM_ROCKCHIP) += -DCONFIG_PLATFORM_ROCKCHIP
|
||||
ccflags-y += -DANDROID_PLATFORM
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_PLATFORM_ALLWINNER), y)
|
||||
ccflags-$(CONFIG_PLATFORM_ALLWINNER) += -DCONFIG_PLATFORM_ALLWINNER
|
||||
KDIR ?= /home/yaya/E/Allwinner/R818/R818/AndroidQ/lichee/kernel/linux-4.9/
|
||||
ARCH ?= arm64
|
||||
CROSS_COMPILE ?= /home/yaya/E/Allwinner/R818/R818/AndroidQ/android/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android-
|
||||
ccflags-y += -DANDROID_PLATFORM
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_PLATFORM_AMLOGIC), y)
|
||||
ccflags-$(CONFIG_PLATFORM_NANOPI) += -DCONFIG_PLATFORM_NANOPI
|
||||
ccflags-y += -DANDROID_PLATFORM
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_PLATFORM_UBUNTU), y)
|
||||
KDIR ?= /lib/modules/$(shell uname -r)/build
|
||||
PWD ?= $(shell pwd)
|
||||
KVER ?= $(shell uname -r)
|
||||
MODDESTDIR ?= /lib/modules/$(KVER)/kernel/drivers/net/wireless/
|
||||
ARCH ?= x86_64
|
||||
CROSS_COMPILE ?=
|
||||
endif
|
||||
|
||||
|
||||
all: modules
|
||||
modules:
|
||||
make -C $(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
|
||||
|
||||
install:
|
||||
mkdir -p $(MODDESTDIR)
|
||||
install -p -m 644 $(MODULE_NAME).ko $(MODDESTDIR)
|
||||
/sbin/depmod -a ${KVER}
|
||||
|
||||
uninstall:
|
||||
rm -rfv $(MODDESTDIR)/$(MODULE_NAME).ko
|
||||
/sbin/depmod -a ${KVER}
|
||||
|
||||
clean:
|
||||
rm -rf *.o *.ko *.o.* *.mod.* modules.* Module.* .a* .o* .*.o.* *.mod .tmp* .cache.mk
|
||||
|
||||
|
||||
1109
drivers/net/wireless/aic8800/aic8800_btlpm/aic8800_btlpm.c
Normal file
1109
drivers/net/wireless/aic8800/aic8800_btlpm/aic8800_btlpm.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,84 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/inetdevice.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/platform_device.h>
|
||||
//#include "lpm.h"
|
||||
#include "rfkill.h"
|
||||
|
||||
#define DRV_CONFIG_FW_NAME "fw.bin"
|
||||
#define DRV_DESCRIPTION "AIC BLUETOOTH"
|
||||
#define DRV_COPYRIGHT "Copyright(c) 2015-2020 AICSemi"
|
||||
#define DRV_AUTHOR "AICSemi"
|
||||
#define DRV_VERS_MOD "1.0"
|
||||
|
||||
static struct platform_device *aicbt_pdev;
|
||||
|
||||
static struct platform_driver aicbt_driver = {
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "aic_bt",
|
||||
},
|
||||
//.probe = aicbt_probe,
|
||||
//.remove = aicbt_remove,
|
||||
};
|
||||
|
||||
static int __init aic_bluetooth_mod_init(void)
|
||||
{
|
||||
int ret;
|
||||
printk("%s\n", __func__);
|
||||
ret = platform_driver_register(&aicbt_driver);
|
||||
if (ret) {
|
||||
pr_err("register platform driver failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
aicbt_pdev = platform_device_alloc("aic-bt", -1);
|
||||
ret = platform_device_add(aicbt_pdev);
|
||||
if (ret) {
|
||||
pr_err("register platform device failed: %d\n", ret);
|
||||
goto err0;
|
||||
}
|
||||
|
||||
ret = rfkill_bluetooth_init(aicbt_pdev);
|
||||
if (ret) {
|
||||
pr_err("rfkill init fail\n");
|
||||
goto err1;
|
||||
}
|
||||
#if 0
|
||||
ret = bluesleep_init(aicbt_pdev);
|
||||
if (ret) {
|
||||
pr_err("bluesleep init fail\n");
|
||||
goto err2;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
//err2:
|
||||
rfkill_bluetooth_remove(aicbt_pdev);
|
||||
err1:
|
||||
platform_device_del(aicbt_pdev);
|
||||
err0:
|
||||
platform_driver_unregister(&aicbt_driver);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit aic_bluetooth_mod_exit(void)
|
||||
{
|
||||
printk("%s\n", __func__);
|
||||
//bluesleep_exit(aicbt_pdev);
|
||||
rfkill_bluetooth_remove(aicbt_pdev);
|
||||
platform_device_del(aicbt_pdev);
|
||||
platform_driver_unregister(&aicbt_driver);
|
||||
}
|
||||
|
||||
module_init(aic_bluetooth_mod_init);
|
||||
module_exit(aic_bluetooth_mod_exit);
|
||||
|
||||
MODULE_DESCRIPTION(DRV_DESCRIPTION);
|
||||
MODULE_VERSION(DRV_VERS_MOD);
|
||||
MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
|
||||
MODULE_LICENSE("GPL");
|
||||
18
drivers/net/wireless/aic8800/aic8800_btlpm/aic_bsp_export.h
Normal file
18
drivers/net/wireless/aic8800/aic8800_btlpm/aic_bsp_export.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef __AIC_BSP_EXPORT_H
|
||||
#define __AIC_BSP_EXPORT_H
|
||||
|
||||
#define AIC_BLUETOOTH 0
|
||||
#define AIC_WIFI 1
|
||||
#define AIC_PWR_OFF 0
|
||||
#define AIC_PWR_ON 1
|
||||
|
||||
struct aicbsp_feature_t {
|
||||
bool band_5g_support;
|
||||
uint32_t sdio_clock;
|
||||
uint8_t sdio_phase;
|
||||
};
|
||||
|
||||
int aicbsp_set_subsys(int, int);
|
||||
int aicbsp_get_feature(struct aicbsp_feature_t *feature);
|
||||
|
||||
#endif
|
||||
1105
drivers/net/wireless/aic8800/aic8800_btlpm/lpm.c
Normal file
1105
drivers/net/wireless/aic8800/aic8800_btlpm/lpm.c
Normal file
File diff suppressed because it is too large
Load Diff
21
drivers/net/wireless/aic8800/aic8800_btlpm/lpm.h
Normal file
21
drivers/net/wireless/aic8800/aic8800_btlpm/lpm.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Spreadtrum Communications Inc.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* 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 __LPM_H
|
||||
#define __LPM_H
|
||||
|
||||
int bluesleep_init(struct platform_device *pdev);
|
||||
int bluesleep_exit(struct platform_device *dev);
|
||||
|
||||
#endif
|
||||
|
||||
81
drivers/net/wireless/aic8800/aic8800_btlpm/rfkill.c
Normal file
81
drivers/net/wireless/aic8800/aic8800_btlpm/rfkill.c
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* 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/kernel.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/rfkill.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/version.h>
|
||||
#include "aic_bsp_export.h"
|
||||
|
||||
static struct rfkill *bt_rfk;
|
||||
static const char bt_name[] = "bluetooth";
|
||||
|
||||
static int bluetooth_set_power(void *data, bool blocked)
|
||||
{
|
||||
pr_info("%s: start_block=%d\n", __func__, blocked);
|
||||
if (!blocked) {
|
||||
aicbsp_set_subsys(AIC_BLUETOOTH, AIC_PWR_ON);
|
||||
} else {
|
||||
aicbsp_set_subsys(AIC_BLUETOOTH, AIC_PWR_OFF);
|
||||
}
|
||||
|
||||
pr_info("%s: end_block=%d\n", __func__, blocked);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct rfkill_ops rfkill_bluetooth_ops = {
|
||||
.set_block = bluetooth_set_power,
|
||||
};
|
||||
|
||||
int rfkill_bluetooth_init(struct platform_device *pdev)
|
||||
{
|
||||
|
||||
int rc = 0;
|
||||
|
||||
pr_info("-->%s\n", __func__);
|
||||
bt_rfk = rfkill_alloc(bt_name, &pdev->dev, RFKILL_TYPE_BLUETOOTH,
|
||||
&rfkill_bluetooth_ops, NULL);
|
||||
if (!bt_rfk) {
|
||||
rc = -ENOMEM;
|
||||
goto err_rfkill_alloc;
|
||||
}
|
||||
/* userspace cannot take exclusive control */
|
||||
rfkill_init_sw_state(bt_rfk, true);
|
||||
rc = rfkill_register(bt_rfk);
|
||||
if (rc)
|
||||
goto err_rfkill_reg;
|
||||
|
||||
pr_info("<--%s\n", __func__);
|
||||
|
||||
return 0;
|
||||
|
||||
err_rfkill_reg:
|
||||
rfkill_destroy(bt_rfk);
|
||||
err_rfkill_alloc:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int rfkill_bluetooth_remove(struct platform_device *dev)
|
||||
{
|
||||
pr_info("-->%s\n", __func__);
|
||||
rfkill_unregister(bt_rfk);
|
||||
rfkill_destroy(bt_rfk);
|
||||
pr_info("<--%s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
17
drivers/net/wireless/aic8800/aic8800_btlpm/rfkill.h
Normal file
17
drivers/net/wireless/aic8800/aic8800_btlpm/rfkill.h
Normal file
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
|
||||
* 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 __RFKILL_H__
|
||||
#define __RFKILL_H__
|
||||
|
||||
int rfkill_bluetooth_init(struct platform_device *pdev);
|
||||
int rfkill_bluetooth_remove(struct platform_device *pdev);
|
||||
|
||||
#endif
|
||||
5
drivers/net/wireless/aic8800/aic8800_fdrv/Kconfig
Normal file
5
drivers/net/wireless/aic8800/aic8800_fdrv/Kconfig
Normal file
@@ -0,0 +1,5 @@
|
||||
config AIC8800_WLAN_SUPPORT
|
||||
tristate "AIC8800 wlan Support"
|
||||
help
|
||||
This is support for aic wifi driver.
|
||||
|
||||
355
drivers/net/wireless/aic8800/aic8800_fdrv/Makefile
Normal file
355
drivers/net/wireless/aic8800/aic8800_fdrv/Makefile
Normal file
@@ -0,0 +1,355 @@
|
||||
RWNX_VERS_NUM := 6.4.3.0
|
||||
|
||||
CONFIG_COUNTRY_CODE = "00"
|
||||
|
||||
MODULE_NAME = aic8800_fdrv
|
||||
|
||||
# Support of bootrom start
|
||||
CONFIG_START_FROM_BOOTROM = y
|
||||
|
||||
# Support of pmic setting, new version bootrom avaliable
|
||||
CONFIG_PMIC_SETTING ?=y
|
||||
|
||||
# Select 8800DC/DW DCDC_VRF mode, check your board
|
||||
CONFIG_VRF_DCDC_MODE = y
|
||||
|
||||
|
||||
# ROM patch enabled option
|
||||
CONFIG_ROM_PATCH_EN ?=y
|
||||
# Support chip with mcu
|
||||
CONFIG_MCU_INTEGRATED ?= n
|
||||
CONFIG_MCU_MESSAGE ?= n
|
||||
ifeq ($(CONFIG_MCU_INTEGRATED), y)
|
||||
CONFIG_PMIC_SETTING = n
|
||||
else
|
||||
CONFIG_MCU_MESSAGE ?= n
|
||||
endif
|
||||
|
||||
#
|
||||
# WAITING FOR KCONFIG {
|
||||
#
|
||||
CONFIG_RWNX_FULLMAC ?= y
|
||||
CONFIG_RWNX_FHOST ?= n
|
||||
|
||||
#
|
||||
# DEBUG OPTIONS
|
||||
CONFIG_RWNX_UM_HELPER_DFLT ?= "/dini/dini_bin/rwnx_umh.sh"
|
||||
|
||||
#
|
||||
# FW ARCH:
|
||||
CONFIG_RWNX_SDM ?= n
|
||||
CONFIG_RWNX_TL4 ?= n
|
||||
|
||||
# IPC version
|
||||
CONFIG_RWNX_OLD_IPC ?= n
|
||||
|
||||
# Support of P2P DebugFS for enabling/disabling NoA and OppPS
|
||||
CONFIG_RWNX_P2P_DEBUGFS := n
|
||||
#
|
||||
# } // WAITING FOR KCONFIG
|
||||
#
|
||||
|
||||
# Enable A-MSDU support (need FW support)
|
||||
## Select this if FW is compiled with AMSDU support
|
||||
CONFIG_RWNX_SPLIT_TX_BUF ?= n
|
||||
## Select this TO send AMSDU
|
||||
CONFIG_RWNX_AMSDUS_TX ?= n
|
||||
|
||||
# Enable BFMER support (need FW support)
|
||||
CONFIG_RWNX_BFMER ?= n
|
||||
|
||||
CONFIG_SDIO_SUPPORT =y
|
||||
CONFIG_USB_SUPPORT =n
|
||||
CONFIG_RX_REORDER ?=y
|
||||
CONFIG_ARP_OFFLOAD =y
|
||||
CONFIG_RADAR_OR_IR_DETECT =n
|
||||
CONFIG_DOWNLOAD_FW =n
|
||||
CONFIG_RFTEST=y
|
||||
CONFIG_USB_BT =y
|
||||
CONFIG_USE_5G ?= y
|
||||
CONFIG_SDIO_PWRCTRL ?= y
|
||||
CONFIG_CREATE_TRACE_POINTS = n
|
||||
CONFIG_TXRX_THREAD_PRIO = n
|
||||
# CONFIG_COEX = n for BT_ONLY, CONFIG_COEX =y for combo and sw
|
||||
CONFIG_COEX = y
|
||||
CONFIG_RX_NETIF_RECV_SKB = y
|
||||
CONFIG_GPIO_WAKEUP = n
|
||||
CONFIG_SET_VENDOR_EXTENSION_IE = n
|
||||
CONFIG_SUPPORT_REALTIME_CHANGE_MAC = y
|
||||
CONFIG_WPA3_FOR_OLD_KERNEL ?= n
|
||||
CONFIG_VHT_FOR_OLD_KERNEL ?= n
|
||||
CONFIG_HE_FOR_OLD_KERNEL ?= n
|
||||
CONFIG_PREALLOC_RX_SKB = n
|
||||
CONFIG_WIFI_SUSPEND_FOR_LINUX = n
|
||||
# Need to set fw path in BOARD_KERNEL_CMDLINE
|
||||
CONFIG_USE_FW_REQUEST = n
|
||||
CONFIG_USE_P2P0=n
|
||||
CONFIG_BR_SUPPORT =n
|
||||
BR_NAME = br0
|
||||
CONFIG_FDRV_NO_REG_SDIO=n
|
||||
CONFIG_SCHED_SCAN = y
|
||||
CONFIG_OOB = n
|
||||
CONFIG_USE_CUSTOMER_MAC = n
|
||||
CONFIG_PREALLOC_TXQ = y
|
||||
CONFIG_DPD = n
|
||||
CONFIG_FORCE_DPD_CALIB = n
|
||||
|
||||
# Support of MU-MIMO transmission (need FW support)
|
||||
ifeq ($(CONFIG_RWNX_BFMER), y)
|
||||
CONFIG_RWNX_MUMIMO_TX ?= n
|
||||
else
|
||||
CONFIG_RWNX_MUMIMO_TX = n
|
||||
endif
|
||||
|
||||
# Enable handling of radar event
|
||||
CONFIG_RWNX_RADAR ?= y
|
||||
|
||||
# Enable HW queue for Broadcast/Multicast traffic (need FW support)
|
||||
CONFIG_RWNX_BCMC ?= y
|
||||
|
||||
# Enable Monitor+Data interface support (need FW support)
|
||||
CONFIG_RWNX_MON_DATA =y
|
||||
|
||||
# extra DEBUG config
|
||||
CONFIG_RWNX_SW_PROFILING ?= n
|
||||
CONFIG_RWNX_DBG ?= y
|
||||
CONFIG_DEBUG_FS ?= n
|
||||
|
||||
obj-$(CONFIG_AIC8800_WLAN_SUPPORT) := $(MODULE_NAME).o
|
||||
$(MODULE_NAME)-y := \
|
||||
rwnx_gki.o \
|
||||
rwnx_msg_tx.o \
|
||||
rwnx_msg_rx.o \
|
||||
rwnx_utils.o \
|
||||
rwnx_cmds.o \
|
||||
rwnx_irqs.o \
|
||||
rwnx_cfgfile.o \
|
||||
rwnx_strs.o \
|
||||
rwnx_rx.o \
|
||||
rwnx_tx.o \
|
||||
rwnx_txq.o \
|
||||
rwnx_main.o \
|
||||
rwnx_mod_params.o \
|
||||
rwnx_mesh.o \
|
||||
rwnx_platform.o \
|
||||
rwnx_pci.o \
|
||||
rwnx_dini.o \
|
||||
rwnx_v7.o \
|
||||
ipc_host.o \
|
||||
rwnx_tdls.o \
|
||||
aic_vendor.o \
|
||||
md5.o \
|
||||
aicwf_compat_8800dc.o \
|
||||
aicwf_compat_8800d80.o \
|
||||
rwnx_wakelock.o \
|
||||
regdb.o \
|
||||
aicwf_rx_prealloc.o
|
||||
|
||||
$(MODULE_NAME)-$(CONFIG_BR_SUPPORT) += aic_br_ext.o
|
||||
$(MODULE_NAME)-$(CONFIG_RWNX_RADAR) += rwnx_radar.o
|
||||
$(MODULE_NAME)-$(CONFIG_DEBUG_FS) += rwnx_debugfs.o
|
||||
$(MODULE_NAME)-$(CONFIG_DEBUG_FS) += rwnx_fw_trace.o
|
||||
$(MODULE_NAME)-$(CONFIG_NL80211_TESTMODE) += rwnx_testmode.o
|
||||
$(MODULE_NAME)-$(CONFIG_RWNX_BFMER) += rwnx_bfmer.o
|
||||
$(MODULE_NAME)-$(CONFIG_RWNX_MUMIMO_TX) += rwnx_mu_group.o
|
||||
$(MODULE_NAME)-$(CONFIG_SDIO_SUPPORT) += sdio_host.o
|
||||
$(MODULE_NAME)-$(CONFIG_SDIO_SUPPORT) += aicwf_txrxif.o
|
||||
$(MODULE_NAME)-$(CONFIG_SDIO_SUPPORT) += aicwf_sdio.o
|
||||
|
||||
$(MODULE_NAME)-$(CONFIG_USB_SUPPORT) += usb_host.o
|
||||
$(MODULE_NAME)-$(CONFIG_USB_SUPPORT) += aicwf_txrxif.o
|
||||
$(MODULE_NAME)-$(CONFIG_USB_SUPPORT) += aicwf_usb.o
|
||||
|
||||
ccflags-$(CONFIG_DEBUG_FS) += -DCONFIG_RWNX_DEBUGFS
|
||||
ccflags-$(CONFIG_DEBUG_FS) += -DCONFIG_RWNX_UM_HELPER_DFLT=\"$(CONFIG_RWNX_UM_HELPER_DFLT)\"
|
||||
ccflags-$(CONFIG_RWNX_P2P_DEBUGFS) += -DCONFIG_RWNX_P2P_DEBUGFS
|
||||
|
||||
# FW VARS
|
||||
ccflags-y += -DNX_VIRT_DEV_MAX=4
|
||||
|
||||
#for 8800D and DCDW u01
|
||||
#ccflags-y += -DNX_REMOTE_STA_MAX=10
|
||||
|
||||
#for 8800DCDW u02
|
||||
ccflags-y += -DNX_REMOTE_STA_MAX_FOR_OLD_IC=10
|
||||
ccflags-y += -DNX_REMOTE_STA_MAX=32
|
||||
|
||||
ccflags-y += -DNX_MU_GROUP_MAX=62
|
||||
ccflags-y += -DNX_TXDESC_CNT=64
|
||||
ccflags-y += -DNX_TX_MAX_RATES=4
|
||||
ccflags-y += -DNX_CHAN_CTXT_CNT=3
|
||||
|
||||
# FW ARCH:
|
||||
ccflags-$(CONFIG_RWNX_SDM) += -DCONFIG_RWNX_SDM
|
||||
ccflags-$(CONFIG_RWNX_TL4) += -DCONFIG_RWNX_TL4
|
||||
ccflags-$(CONFIG_RWNX_OLD_IPC) += -DCONFIG_RWNX_OLD_IPC
|
||||
ccflags-$(CONFIG_PLATFORM_NANOPI_M4) += -DCONFIG_NANOPI_M4
|
||||
ccflags-$(CONFIG_PLATFORM_INGENIC_T20) += -DCONFIG_INGENIC_T20
|
||||
ccflags-$(CONFIG_PLATFORM_ALLWINNER) += -DCONFIG_PLATFORM_ALLWINNER
|
||||
ccflags-$(CONFIG_START_FROM_BOOTROM) += -DCONFIG_START_FROM_BOOTROM
|
||||
ccflags-$(CONFIG_PMIC_SETTING) += -DCONFIG_PMIC_SETTING
|
||||
ccflags-$(CONFIG_VRF_DCDC_MODE) += -DCONFIG_VRF_DCDC_MODE
|
||||
ccflags-$(CONFIG_ROM_PATCH_EN) += -DCONFIG_ROM_PATCH_EN
|
||||
ccflags-$(CONFIG_HE_FOR_OLD_KERNEL) += -DCONFIG_HE_FOR_OLD_KERNEL
|
||||
ccflags-$(CONFIG_MCU_INTEGRATED) += -DCONFIG_MCU_INTEGRATED
|
||||
ccflags-$(CONFIG_MCU_MESSAGE) += -DCONFIG_MCU_MESSAGE
|
||||
ccflags-$(CONFIG_COEX) += -DCONFIG_COEX
|
||||
|
||||
ccflags-y += -DCONFIG_RWNX_FULLMAC
|
||||
ccflags-y += -I$(srctree)
|
||||
ccflags-y += -I$(srctree)/$(src)
|
||||
ccflags-y += -I$(srctree)/$(src)/../aic8800_bsp
|
||||
ccflags-y += -DCONFIG_AIC_FW_PATH=\"$(CONFIG_AIC_FW_PATH)\"
|
||||
ccflags-$(CONFIG_RWNX_RADAR) += -DCONFIG_RWNX_RADAR
|
||||
ccflags-$(CONFIG_RWNX_MON_DATA) += -DCONFIG_RWNX_MON_DATA
|
||||
ccflags-$(CONFIG_RWNX_BFMER) += -DCONFIG_RWNX_BFMER
|
||||
ccflags-$(CONFIG_RWNX_SPLIT_TX_BUF) += -DCONFIG_RWNX_SPLIT_TX_BUF
|
||||
ifeq ($(CONFIG_RWNX_SPLIT_TX_BUF), y)
|
||||
ccflags-$(CONFIG_RWNX_AMSDUS_TX) += -DCONFIG_RWNX_AMSDUS_TX
|
||||
endif
|
||||
ccflags-$(CONFIG_RWNX_DBG) += -DCONFIG_RWNX_DBG
|
||||
ccflags-$(CONFIG_RWNX_SW_PROFILING) += -DCONFIG_RWNX_SW_PROFILING
|
||||
ccflags-$(CONFIG_RWNX_MUMIMO_TX) += -DCONFIG_RWNX_MUMIMO_TX
|
||||
ccflags-$(CONFIG_RFTEST) += -DCONFIG_RFTEST
|
||||
ccflags-y += -DDEFAULT_COUNTRY_CODE=""\$(CONFIG_COUNTRY_CODE)"\"
|
||||
ccflags-$(CONFIG_USE_5G) += -DUSE_5G
|
||||
ccflags-$(CONFIG_CREATE_TRACE_POINTS) += -DCREATE_TRACE_POINTS
|
||||
ccflags-$(CONFIG_TXRX_THREAD_PRIO) += -DCONFIG_TXRX_THREAD_PRIO
|
||||
ccflags-$(CONFIG_GPIO_WAKEUP) += -DCONFIG_GPIO_WAKEUP
|
||||
ccflags-$(CONFIG_SET_VENDOR_EXTENSION_IE) += -DCONFIG_SET_VENDOR_EXTENSION_IE
|
||||
ccflags-$(CONFIG_SUPPORT_REALTIME_CHANGE_MAC) += -DCONFIG_SUPPORT_REALTIME_CHANGE_MAC
|
||||
ccflags-$(CONFIG_WPA3_FOR_OLD_KERNEL) += -DCONFIG_WPA3_FOR_OLD_KERNEL
|
||||
ccflags-$(CONFIG_VHT_FOR_OLD_KERNEL) += -DCONFIG_VHT_FOR_OLD_KERNEL
|
||||
ccflags-$(CONFIG_PREALLOC_RX_SKB) += -DCONFIG_PREALLOC_RX_SKB
|
||||
ccflags-$(CONFIG_WIFI_SUSPEND_FOR_LINUX) += -DCONFIG_WIFI_SUSPEND_FOR_LINUX
|
||||
ccflags-$(CONFIG_USE_FW_REQUEST) += -DCONFIG_USE_FW_REQUEST
|
||||
ccflags-$(CONFIG_USE_P2P0) += -DCONFIG_USE_P2P0
|
||||
ccflags-$(CONFIG_FDRV_NO_REG_SDIO) += -DCONFIG_FDRV_NO_REG_SDIO
|
||||
ccflags-$(CONFIG_SCHED_SCAN) += -DCONFIG_SCHED_SCAN
|
||||
ccflags-$(CONFIG_OOB) += -DCONFIG_OOB
|
||||
ccflags-$(CONFIG_USE_CUSTOMER_MAC) += -DCONFIG_USE_CUSTOMER_MAC
|
||||
ccflags-$(CONFIG_PREALLOC_TXQ) += -DCONFIG_PREALLOC_TXQ
|
||||
ccflags-$(CONFIG_DPD) += -DCONFIG_DPD
|
||||
ccflags-$(CONFIG_FORCE_DPD_CALIB) += -DCONFIG_FORCE_DPD_CALIB -DCONFIG_DPD
|
||||
|
||||
|
||||
ifeq ($(CONFIG_SDIO_SUPPORT), y)
|
||||
ccflags-y += -DAICWF_SDIO_SUPPORT
|
||||
ccflags-$(CONFIG_SDIO_PWRCTRL) += -DCONFIG_SDIO_PWRCTRL
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_USB_SUPPORT), y)
|
||||
ccflags-y += -DAICWF_USB_SUPPORT
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BR_SUPPORT), y)
|
||||
ccflags-y += -DCONFIG_BR_SUPPORT
|
||||
ccflags-y += '-DCONFIG_BR_SUPPORT_BRNAME="'$(BR_NAME)'"'
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_RWNX_MUMIMO_TX), y)
|
||||
ccflags-y += -DCONFIG_USER_MAX=2
|
||||
else
|
||||
ccflags-y += -DCONFIG_USER_MAX=1
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_RWNX_BCMC), y)
|
||||
ccflags-y += -DNX_TXQ_CNT=5
|
||||
else
|
||||
ccflags-y += -DNX_TXQ_CNT=4
|
||||
endif
|
||||
|
||||
# For old kernel (<=3.19)
|
||||
ifeq ($(shell test $(VERSION) -lt 4 -a "$(CONFIG_VENDOR_RWNX)" = y ; echo $$?),0)
|
||||
ccflags-y += -DCONFIG_VENDOR_RWNX_VHT_NO80
|
||||
endif
|
||||
|
||||
ccflags-$(CONFIG_RX_REORDER) += -DAICWF_RX_REORDER
|
||||
ccflags-$(CONFIG_ARP_OFFLOAD) += -DAICWF_ARP_OFFLOAD
|
||||
ccflags-$(CONFIG_RADAR_DETECT) += -DRADAR_OR_IR_DETECT
|
||||
ccflags-$(CONFIG_DOWNLOAD_FW) += -DCONFIG_DOWNLOAD_FW
|
||||
ccflags-$(CONFIG_RX_NETIF_RECV_SKB) += -DCONFIG_RX_NETIF_RECV_SKB
|
||||
|
||||
# Platform support list
|
||||
CONFIG_PLATFORM_ROCKCHIP ?= n
|
||||
CONFIG_PLATFORM_ALLWINNER ?= n
|
||||
CONFIG_PLATFORM_INGENIC_T20 ?= n
|
||||
CONFIG_PLATFORM_AMLOGIC ?= n
|
||||
CONFIG_PLATFORM_UBUNTU ?= y
|
||||
|
||||
ccflags-y += -DAIC_TRACE_INCLUDE_PATH=$(src)
|
||||
|
||||
ifeq ($(CONFIG_PLATFORM_ROCKCHIP), y)
|
||||
#KDIR ?= /home/yaya/E/Rockchip/3229/Android7/RK3229_ANDROID7.1_v1.01_20170914/rk3229_Android7.1_v1.01_xml0914/kernel
|
||||
#ARCH ?= arm
|
||||
#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3229/Android7/RK3229_ANDROID7.1_v1.01_20170914/rk3229_Android7.1_v1.01_xml0914/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-
|
||||
#KDIR ?= /home/yaya/E/Rockchip/3399/rk3399-android-10/kernel
|
||||
#ARCH ?= arm64
|
||||
#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3399/rk3399-android-10/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
|
||||
#KDIR ?= /home/yaya/E/Rockchip/3288/Android10/kernel/kernel/
|
||||
#ARCH ?= arm
|
||||
#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3288/Android10/tool/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-
|
||||
#KDIR ?= /home/yaya/E/Rockchip/3229/Android9/rk3229_android9.0_box/kernel
|
||||
#ARCH ?= arm
|
||||
#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3229/Android9/rk3229_android9.0_box/prebuilts/gcc/linux-x86/arm/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-
|
||||
#KDIR ?= /home/yaya/E/Rockchip/3566/Android/kernel
|
||||
#ARCH ?= arm64
|
||||
#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3566/Android/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
|
||||
#KDIR ?= /home/yaya/E/Rockchip/3328/Android9/SDK/kernel/
|
||||
#ARCH ?= arm64
|
||||
#CROSS_COMPILE ?= /home/yaya/E/Rockchip/3328/Android9/SDK/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
|
||||
#KDIR ?= /home/yaya/E/Rockchip/3566/oudu/kernel
|
||||
KDIR ?= ~/E/Rockchip/3566/Android11/rk3566_rk3568_android11_oranth/kernel
|
||||
#KDIR ?= /home/yaya/E/Rockchip/3566/shengteng/kernel
|
||||
ARCH ?= arm64
|
||||
CROSS_COMPILE ?= ~/E/Rockchip/3566/Android11/rk3566_rk3568_android11_oranth/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
|
||||
ccflags-$(CONFIG_PLATFORM_ROCKCHIP) += -DCONFIG_PLATFORM_ROCKCHIP
|
||||
ccflags-y += -DANDROID_PLATFORM
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_PLATFORM_ALLWINNER), y)
|
||||
ccflags-$(CONFIG_PLATFORM_ALLWINNER) += -DCONFIG_PLATFORM_ALLWINNER
|
||||
ccflags-y += -DANDROID_PLATFORM
|
||||
KDIR ?= /home/yaya/E/Allwinner/r818/Android10/lichee/kernel/linux-4.9/
|
||||
ARCH ?= arm64
|
||||
CROSS_COMPILE ?= /home/yaya/E/Allwinner/r818/Android10/android/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android-
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_PLATFORM_INGENIC_T20), y)
|
||||
KDIR ?= /home/yaya/E/T40/kernel
|
||||
ARCH ?= mips
|
||||
CROSS_COMPILE ?= /home/yaya/E/T40/mips-linux-gnu-ingenic-gcc7.2.0-glibc2.29-fp64/bin/mips-linux-gnu-
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_PLATFORM_AMLOGIC), y)
|
||||
ccflags-$(CONFIG_PLATFORM_AMLOGIC) += -DCONFIG_PLATFORM_AMLOGIC
|
||||
ccflags-y += -DANDROID_PLATFORM
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_PLATFORM_UBUNTU), y)
|
||||
KDIR ?= /lib/modules/$(shell uname -r)/build
|
||||
PWD ?= $(shell pwd)
|
||||
KVER ?= $(shell uname -r)
|
||||
MODDESTDIR ?= /lib/modules/$(KVER)/kernel/drivers/net/wireless/
|
||||
ARCH ?= x86_64
|
||||
CROSS_COMPILE ?=
|
||||
endif
|
||||
|
||||
|
||||
all: modules
|
||||
modules:
|
||||
make -C $(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules
|
||||
|
||||
install:
|
||||
mkdir -p $(MODDESTDIR)
|
||||
install -p -m 644 $(MODULE_NAME).ko $(MODDESTDIR)
|
||||
/sbin/depmod -a ${KVER}
|
||||
|
||||
uninstall:
|
||||
rm -rfv $(MODDESTDIR)/$(MODULE_NAME).ko
|
||||
/sbin/depmod -a ${KVER}
|
||||
|
||||
clean:
|
||||
rm -rf *.o *.ko *.o.* *.mod.* modules.* Module.* .a* .o* .*.o.* *.mod .tmp* .cache.mk
|
||||
|
||||
|
||||
1569
drivers/net/wireless/aic8800/aic8800_fdrv/aic_br_ext.c
Normal file
1569
drivers/net/wireless/aic8800/aic8800_fdrv/aic_br_ext.c
Normal file
File diff suppressed because it is too large
Load Diff
73
drivers/net/wireless/aic8800/aic8800_fdrv/aic_br_ext.h
Normal file
73
drivers/net/wireless/aic8800/aic8800_fdrv/aic_br_ext.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2007 - 2017 Realtek Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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 _AIC_BR_EXT_H_
|
||||
#define _AIC_BR_EXT_H_
|
||||
|
||||
#define CL_IPV6_PASS 1
|
||||
#define MACADDRLEN 6
|
||||
#define WLAN_ETHHDR_LEN 14
|
||||
|
||||
#define NAT25_HASH_BITS 4
|
||||
#define NAT25_HASH_SIZE (1 << NAT25_HASH_BITS)
|
||||
#define NAT25_AGEING_TIME 300
|
||||
|
||||
#define NDEV_FMT "%s"
|
||||
#define NDEV_ARG(ndev) ndev->name
|
||||
#define ADPT_FMT "%s"
|
||||
//#define ADPT_ARG(adapter) (adapter->pnetdev ? adapter->pnetdev->name : NULL)
|
||||
#define FUNC_NDEV_FMT "%s(%s)"
|
||||
#define FUNC_NDEV_ARG(ndev) __func__, ndev->name
|
||||
#define FUNC_ADPT_FMT "%s(%s)"
|
||||
//#define FUNC_ADPT_ARG(adapter) __func__, (adapter->pnetdev ? adapter->pnetdev->name : NULL)
|
||||
#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
|
||||
#define MAC_ARG(x) ((u8 *)(x))[0], ((u8 *)(x))[1], ((u8 *)(x))[2], ((u8 *)(x))[3], ((u8 *)(x))[4], ((u8 *)(x))[5]
|
||||
|
||||
|
||||
#ifdef CL_IPV6_PASS
|
||||
#define MAX_NETWORK_ADDR_LEN 17
|
||||
#else
|
||||
#define MAX_NETWORK_ADDR_LEN 11
|
||||
#endif
|
||||
|
||||
struct nat25_network_db_entry {
|
||||
struct nat25_network_db_entry *next_hash;
|
||||
struct nat25_network_db_entry **pprev_hash;
|
||||
atomic_t use_count;
|
||||
unsigned char macAddr[6];
|
||||
unsigned long ageing_timer;
|
||||
unsigned char networkAddr[MAX_NETWORK_ADDR_LEN];
|
||||
};
|
||||
|
||||
enum NAT25_METHOD {
|
||||
NAT25_MIN,
|
||||
NAT25_CHECK,
|
||||
NAT25_INSERT,
|
||||
NAT25_LOOKUP,
|
||||
NAT25_PARSE,
|
||||
NAT25_MAX
|
||||
};
|
||||
|
||||
struct br_ext_info {
|
||||
unsigned int nat25_disable;
|
||||
unsigned int macclone_enable;
|
||||
unsigned int dhcp_bcst_disable;
|
||||
int addPPPoETag; /* 1: Add PPPoE relay-SID, 0: disable */
|
||||
unsigned char nat25_dmzMac[MACADDRLEN];
|
||||
unsigned int nat25sc_disable;
|
||||
};
|
||||
|
||||
void nat25_db_cleanup(struct rwnx_vif *vif);
|
||||
|
||||
#endif /* _AIC_BR_EXT_H_ */
|
||||
33
drivers/net/wireless/aic8800/aic8800_fdrv/aic_bsp_export.h
Normal file
33
drivers/net/wireless/aic8800/aic8800_fdrv/aic_bsp_export.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef __AIC_BSP_EXPORT_H
|
||||
#define __AIC_BSP_EXPORT_H
|
||||
|
||||
#define AICBSP_RESV_MEM_SUPPORT 0
|
||||
|
||||
enum aicbsp_subsys {
|
||||
AIC_BLUETOOTH,
|
||||
AIC_WIFI,
|
||||
};
|
||||
|
||||
enum aicbsp_pwr_state {
|
||||
AIC_PWR_OFF,
|
||||
AIC_PWR_ON,
|
||||
};
|
||||
|
||||
struct aicbsp_feature_t {
|
||||
int hwinfo;
|
||||
uint32_t sdio_clock;
|
||||
uint8_t sdio_phase;
|
||||
int fwlog_en;
|
||||
};
|
||||
|
||||
enum skb_buff_id {
|
||||
AIC_RESV_MEM_TXDATA,
|
||||
};
|
||||
|
||||
int aicbsp_set_subsys(int, int);
|
||||
int aicbsp_get_feature(struct aicbsp_feature_t *feature, char *fw_path);
|
||||
bool aicbsp_get_load_fw_in_fdrv(void);
|
||||
struct sk_buff *aicbsp_resv_mem_alloc_skb(unsigned int length, uint32_t id);
|
||||
void aicbsp_resv_mem_kfree_skb(struct sk_buff *skb, uint32_t id);
|
||||
|
||||
#endif
|
||||
877
drivers/net/wireless/aic8800/aic8800_fdrv/aic_vendor.c
Normal file
877
drivers/net/wireless/aic8800/aic8800_fdrv/aic_vendor.c
Normal file
@@ -0,0 +1,877 @@
|
||||
#include "aic_vendor.h"
|
||||
#include "rwnx_defs.h"
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/inetdevice.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <net/netlink.h>
|
||||
#include "rwnx_version_gen.h"
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
|
||||
|
||||
static struct wifi_ring_buffer_status ring_buffer[] = {
|
||||
{
|
||||
.name = "aicwf_ring_buffer0",
|
||||
.flags = 0,
|
||||
.ring_id = 0,
|
||||
.verbose_level = 0,
|
||||
.written_bytes = 0,
|
||||
.read_bytes = 0,
|
||||
.written_records = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct wlan_driver_wake_reason_cnt_t wake_reason_cnt = {
|
||||
.total_cmd_event_wake = 10,
|
||||
};
|
||||
#endif
|
||||
|
||||
int aic_dev_start_mkeep_alive(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif,
|
||||
u8 mkeep_alive_id, u8 *ip_pkt, u16 ip_pkt_len, u8 *src_mac, u8 *dst_mac, u32 period_msec)
|
||||
{
|
||||
u8 *data, *pos;
|
||||
|
||||
data = kzalloc(ip_pkt_len + 14, GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
pos = data;
|
||||
memcpy(pos, dst_mac, 6);
|
||||
pos += 6;
|
||||
memcpy(pos, src_mac, 6);
|
||||
pos += 6;
|
||||
/* Mapping Ethernet type (ETHERTYPE_IP: 0x0800) */
|
||||
*(pos++) = 0x08;
|
||||
*(pos++) = 0x00;
|
||||
|
||||
/* Mapping IP pkt */
|
||||
memcpy(pos, ip_pkt, ip_pkt_len);
|
||||
pos += ip_pkt_len;
|
||||
|
||||
//add send 802.3 pkt(raw data)
|
||||
kfree(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int aic_dev_stop_mkeep_alive(struct rwnx_hw *rwnx_hw, struct rwnx_vif *rwnx_vif, u8 mkeep_alive_id)
|
||||
{
|
||||
int res = -1;
|
||||
|
||||
/*
|
||||
* The mkeep_alive packet is for STA interface only; if the bss is configured as AP,
|
||||
* dongle shall reject a mkeep_alive request.
|
||||
*/
|
||||
if (rwnx_vif->wdev.iftype != NL80211_IFTYPE_STATION)
|
||||
return res;
|
||||
|
||||
printk("%s execution\n", __func__);
|
||||
|
||||
//add send stop keep alive
|
||||
res = 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
|
||||
static int aicwf_vendor_start_mkeep_alive(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
const void *data, int len)
|
||||
{
|
||||
/* max size of IP packet for keep alive */
|
||||
const int MKEEP_ALIVE_IP_PKT_MAX = 256;
|
||||
|
||||
int ret = 0, rem, type;
|
||||
u8 mkeep_alive_id = 0;
|
||||
u8 *ip_pkt = NULL;
|
||||
u16 ip_pkt_len = 0;
|
||||
u8 src_mac[6];
|
||||
u8 dst_mac[6];
|
||||
u32 period_msec = 0;
|
||||
const struct nlattr *iter;
|
||||
struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy);
|
||||
struct rwnx_vif *rwnx_vif = container_of(wdev, struct rwnx_vif, wdev);
|
||||
gfp_t kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
|
||||
printk("%s\n", __func__);
|
||||
|
||||
nla_for_each_attr(iter, data, len, rem) {
|
||||
type = nla_type(iter);
|
||||
switch (type) {
|
||||
case MKEEP_ALIVE_ATTRIBUTE_ID:
|
||||
mkeep_alive_id = nla_get_u8(iter);
|
||||
break;
|
||||
case MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN:
|
||||
ip_pkt_len = nla_get_u16(iter);
|
||||
if (ip_pkt_len > MKEEP_ALIVE_IP_PKT_MAX) {
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
break;
|
||||
case MKEEP_ALIVE_ATTRIBUTE_IP_PKT:
|
||||
if (!ip_pkt_len) {
|
||||
ret = -EINVAL;
|
||||
printk("ip packet length is 0\n");
|
||||
goto exit;
|
||||
}
|
||||
ip_pkt = (u8 *)kzalloc(ip_pkt_len, kflags);
|
||||
if (ip_pkt == NULL) {
|
||||
ret = -ENOMEM;
|
||||
printk("Failed to allocate mem for ip packet\n");
|
||||
goto exit;
|
||||
}
|
||||
memcpy(ip_pkt, (u8 *)nla_data(iter), ip_pkt_len);
|
||||
break;
|
||||
case MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR:
|
||||
memcpy(src_mac, nla_data(iter), 6);
|
||||
break;
|
||||
case MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR:
|
||||
memcpy(dst_mac, nla_data(iter), 6);
|
||||
break;
|
||||
case MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC:
|
||||
period_msec = nla_get_u32(iter);
|
||||
break;
|
||||
default:
|
||||
pr_err("%s(%d), Unknown type: %d\n", __func__, __LINE__, type);
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (ip_pkt == NULL) {
|
||||
ret = -EINVAL;
|
||||
printk("ip packet is NULL\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = aic_dev_start_mkeep_alive(rwnx_hw, rwnx_vif, mkeep_alive_id, ip_pkt, ip_pkt_len, src_mac,
|
||||
dst_mac, period_msec);
|
||||
if (ret < 0) {
|
||||
printk("start_mkeep_alive is failed ret: %d\n", ret);
|
||||
}
|
||||
|
||||
exit:
|
||||
if (ip_pkt) {
|
||||
kfree(ip_pkt);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int aicwf_vendor_stop_mkeep_alive(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
const void *data, int len)
|
||||
{
|
||||
int ret = 0, rem, type;
|
||||
u8 mkeep_alive_id = 0;
|
||||
const struct nlattr *iter;
|
||||
struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy);
|
||||
struct rwnx_vif *rwnx_vif = container_of(wdev, struct rwnx_vif, wdev);
|
||||
|
||||
printk("%s\n", __func__);
|
||||
nla_for_each_attr(iter, data, len, rem) {
|
||||
type = nla_type(iter);
|
||||
switch (type) {
|
||||
case MKEEP_ALIVE_ATTRIBUTE_ID:
|
||||
mkeep_alive_id = nla_get_u8(iter);
|
||||
break;
|
||||
default:
|
||||
pr_err("%s(%d), Unknown type: %d\n", __func__, __LINE__, type);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ret = aic_dev_stop_mkeep_alive(rwnx_hw, rwnx_vif, mkeep_alive_id);
|
||||
if (ret < 0) {
|
||||
printk("stop_mkeep_alive is failed ret: %d\n", ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int aicwf_vendor_get_ver(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
const void *data, int len)
|
||||
{
|
||||
int ret = 0, rem, type;
|
||||
const struct nlattr *iter;
|
||||
int payload = 0;
|
||||
char version[128];
|
||||
int attr = -1;
|
||||
struct sk_buff *reply;
|
||||
|
||||
nla_for_each_attr(iter, data, len, rem) {
|
||||
type = nla_type(iter);
|
||||
switch (type) {
|
||||
case LOGGER_ATTRIBUTE_DRIVER_VER:
|
||||
memcpy(version, RWNX_VERS_BANNER, sizeof(RWNX_VERS_BANNER));
|
||||
payload = strlen(version);
|
||||
attr = LOGGER_ATTRIBUTE_DRIVER_VER;
|
||||
break;
|
||||
case LOGGER_ATTRIBUTE_FW_VER:
|
||||
memcpy(version, wiphy->fw_version, sizeof(wiphy->fw_version));
|
||||
payload = strlen(version);
|
||||
attr = LOGGER_ATTRIBUTE_FW_VER;
|
||||
break;
|
||||
default:
|
||||
AICWFDBG(LOGERROR, "%s(%d), Unknown type: %d\n", __func__, __LINE__, type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (attr < 0)
|
||||
return -EINVAL;
|
||||
|
||||
reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload);
|
||||
|
||||
if (!reply)
|
||||
return -ENOMEM;
|
||||
|
||||
if (nla_put(reply, attr,
|
||||
payload, version)) {
|
||||
wiphy_err(wiphy, "%s put version error\n", __func__);
|
||||
goto out_put_fail;
|
||||
}
|
||||
|
||||
ret = cfg80211_vendor_cmd_reply(reply);
|
||||
if (ret)
|
||||
wiphy_err(wiphy, "%s reply cmd error\n", __func__);
|
||||
return ret;
|
||||
|
||||
out_put_fail:
|
||||
kfree_skb(reply);
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static int aicwf_vendor_subcmd_get_channel_list(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
const void *data, int len)
|
||||
{
|
||||
int ret = 0, rem, type;
|
||||
const struct nlattr *iter;
|
||||
struct sk_buff *reply;
|
||||
int num_channels = 0;
|
||||
int *channel_list = NULL;
|
||||
int payload;
|
||||
int i = 0;
|
||||
struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy);
|
||||
struct ieee80211_supported_band *rwnx_band_2GHz = rwnx_hw->wiphy->bands[NL80211_BAND_2GHZ];
|
||||
struct ieee80211_supported_band *rwnx_band_5GHz = rwnx_hw->wiphy->bands[NL80211_BAND_5GHZ];
|
||||
|
||||
num_channels += rwnx_band_2GHz->n_channels;
|
||||
num_channels += (rwnx_hw->band_5g_support) ? rwnx_band_5GHz->n_channels : 0;
|
||||
|
||||
channel_list = (int *)kzalloc(sizeof(int) * num_channels, GFP_KERNEL);
|
||||
if (!channel_list)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < rwnx_band_2GHz->n_channels; i++)
|
||||
channel_list[i] = rwnx_band_2GHz->channels[i].center_freq;
|
||||
|
||||
for (; rwnx_hw->band_5g_support && i < num_channels; i++)
|
||||
channel_list[i] = rwnx_band_5GHz->channels[i].center_freq;
|
||||
|
||||
payload = sizeof(num_channels) + sizeof(int) * num_channels + 4;
|
||||
|
||||
nla_for_each_attr(iter, data, len, rem) {
|
||||
type = nla_type(iter);
|
||||
switch (type) {
|
||||
case GSCAN_ATTRIBUTE_BAND:
|
||||
reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload);
|
||||
|
||||
if (!reply)
|
||||
return -ENOMEM;
|
||||
|
||||
if (nla_put_u32(reply, GSCAN_ATTRIBUTE_NUM_CHANNELS, num_channels))
|
||||
goto out_put_fail;
|
||||
|
||||
if (nla_put(reply, GSCAN_ATTRIBUTE_CHANNEL_LIST, sizeof(int) * num_channels, channel_list))
|
||||
goto out_put_fail;
|
||||
|
||||
ret = cfg80211_vendor_cmd_reply(reply);
|
||||
if (ret)
|
||||
wiphy_err(wiphy, "%s reply cmd error\n", __func__);
|
||||
break;
|
||||
default:
|
||||
pr_err("%s(%d), Unknown type: %d\n", __func__, __LINE__, type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
kfree(channel_list);
|
||||
return ret;
|
||||
|
||||
out_put_fail:
|
||||
kfree(channel_list);
|
||||
kfree_skb(reply);
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static int aicwf_vendor_subcmd_set_country_code(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
const void *data, int len)
|
||||
{
|
||||
int ret = 0, rem, type;
|
||||
const struct nlattr *iter;
|
||||
|
||||
nla_for_each_attr(iter, data, len, rem) {
|
||||
type = nla_type(iter);
|
||||
switch (type) {
|
||||
case ANDR_WIFI_ATTRIBUTE_COUNTRY:
|
||||
printk("%s(%d), ANDR_WIFI_ATTRIBUTE_COUNTRY: %s\n", __func__, __LINE__, (char *)nla_data(iter));
|
||||
break;
|
||||
default:
|
||||
pr_err("%s(%d), Unknown type: %d\n", __func__, __LINE__, type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO
|
||||
* Add handle in the future!
|
||||
*/
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int aicwf_vendor_logger_trigger_memory_dump(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
const void *data, int len)
|
||||
{
|
||||
/* TODO
|
||||
* Add handle in the future!
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aicwf_vendor_subcmd_get_feature_set(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
const void *data, int len)
|
||||
{
|
||||
int ret;
|
||||
struct sk_buff *reply;
|
||||
uint32_t feature = 0, payload;
|
||||
struct rwnx_hw *rwnx_hw = wiphy_priv(wiphy);
|
||||
|
||||
payload = sizeof(feature);
|
||||
reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload);
|
||||
|
||||
if (!reply)
|
||||
return -ENOMEM;
|
||||
|
||||
/* TODO
|
||||
* Add handle in the future!
|
||||
*/
|
||||
/*bit 1:Basic infrastructure mode*/
|
||||
if (wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION))
|
||||
feature |= WIFI_FEATURE_INFRA;
|
||||
|
||||
/*bit 2:Support for 5 GHz Band*/
|
||||
if (rwnx_hw->band_5g_support)
|
||||
feature |= WIFI_FEATURE_INFRA_5G;
|
||||
|
||||
/*bit3:HOTSPOT is a supplicant feature, enable it by default*/
|
||||
feature |= WIFI_FEATURE_HOTSPOT;
|
||||
|
||||
/*bit 4:P2P*/
|
||||
if ((wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)) &&
|
||||
(wiphy->interface_modes & BIT(NL80211_IFTYPE_P2P_GO)))
|
||||
feature |= WIFI_FEATURE_P2P;
|
||||
|
||||
/*bit 5:soft AP feature supported*/
|
||||
if (wiphy->interface_modes & BIT(NL80211_IFTYPE_AP))
|
||||
feature |= WIFI_FEATURE_SOFT_AP;
|
||||
|
||||
/*bit 18:WiFi Logger*/
|
||||
feature |= WIFI_FEATURE_LOGGER;
|
||||
|
||||
/*bit 21:WiFi mkeep_alive*/
|
||||
feature |= WIFI_FEATURE_MKEEP_ALIVE;
|
||||
|
||||
if (nla_put_u32(reply, ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET, feature)) {
|
||||
wiphy_err(wiphy, "%s put u32 error\n", __func__);
|
||||
goto out_put_fail;
|
||||
}
|
||||
|
||||
ret = cfg80211_vendor_cmd_reply(reply);
|
||||
if (ret)
|
||||
wiphy_err(wiphy, "%s reply cmd error\n", __func__);
|
||||
|
||||
return ret;
|
||||
|
||||
out_put_fail:
|
||||
kfree_skb(reply);
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static int aicwf_vendor_logger_get_feature(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
const void *data, int len)
|
||||
{
|
||||
int ret;
|
||||
struct sk_buff *reply;
|
||||
uint32_t feature = 0, payload;
|
||||
|
||||
payload = sizeof(feature);
|
||||
reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload);
|
||||
|
||||
if (!reply)
|
||||
return -ENOMEM;
|
||||
|
||||
feature |= WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
|
||||
feature |= WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
|
||||
|
||||
/*vts will test wake reason state function*/
|
||||
feature |= WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
|
||||
|
||||
if (nla_put_u32(reply, ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET, feature)) {
|
||||
wiphy_err(wiphy, "put skb u32 failed\n");
|
||||
goto out_put_fail;
|
||||
}
|
||||
|
||||
ret = cfg80211_vendor_cmd_reply(reply);
|
||||
if (ret)
|
||||
wiphy_err(wiphy, "reply cmd error\n");
|
||||
|
||||
return ret;
|
||||
|
||||
out_put_fail:
|
||||
kfree_skb(reply);
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static int aicwf_vendor_logger_get_ring_status(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
const void *data, int len)
|
||||
{
|
||||
int ret;
|
||||
struct sk_buff *reply;
|
||||
uint32_t payload;
|
||||
uint32_t ring_buffer_nums = sizeof(ring_buffer) / sizeof(ring_buffer[0]);
|
||||
|
||||
payload = sizeof(ring_buffer_nums) + sizeof(ring_buffer);
|
||||
reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload);
|
||||
|
||||
if (!reply)
|
||||
return -ENOMEM;
|
||||
|
||||
if (nla_put_u32(reply, LOGGER_ATTRIBUTE_RING_NUM, ring_buffer_nums)) {
|
||||
wiphy_err(wiphy, "put skb u32 failed\n");
|
||||
goto out_put_fail;
|
||||
}
|
||||
|
||||
if (nla_put(reply, LOGGER_ATTRIBUTE_RING_STATUS, sizeof(ring_buffer), ring_buffer)) {
|
||||
wiphy_err(wiphy, "put skb failed\n");
|
||||
goto out_put_fail;
|
||||
}
|
||||
|
||||
ret = cfg80211_vendor_cmd_reply(reply);
|
||||
if (ret)
|
||||
wiphy_err(wiphy, "reply cmd error\n");
|
||||
|
||||
return ret;
|
||||
|
||||
out_put_fail:
|
||||
kfree_skb(reply);
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static int aicwf_vendor_logger_start_logging(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
const void *data, int len)
|
||||
{
|
||||
int ret = 0, rem, type, intval, size, i;
|
||||
const struct nlattr *iter;
|
||||
struct wifi_ring_buffer_status rb;
|
||||
|
||||
nla_for_each_attr(iter, data, len, rem) {
|
||||
type = nla_type(iter);
|
||||
switch (type) {
|
||||
case LOGGER_ATTRIBUTE_LOG_LEVEL:
|
||||
rb.verbose_level = nla_get_u32(iter);
|
||||
break;
|
||||
case LOGGER_ATTRIBUTE_RING_FLAGS:
|
||||
rb.flags = nla_get_u32(iter);
|
||||
break;
|
||||
case LOGGER_ATTRIBUTE_LOG_TIME_INTVAL:
|
||||
intval = nla_get_u32(iter);
|
||||
break;
|
||||
case LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE:
|
||||
size = nla_get_u32(iter);
|
||||
break;
|
||||
case LOGGER_ATTRIBUTE_RING_NAME:
|
||||
strcpy(rb.name, nla_data(iter));
|
||||
break;
|
||||
default:
|
||||
AICWFDBG(LOGERROR, "%s(%d), Unknown type: %d\n", __func__, __LINE__, type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
ret = -EINVAL;
|
||||
for (i = 0; i < sizeof(ring_buffer) / sizeof(ring_buffer[0]); i++) {
|
||||
if (strcmp(rb.name, ring_buffer[i].name) == 0) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO
|
||||
* Add handle in the future
|
||||
*/
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int aicwf_vendor_logger_get_ring_data(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
const void *data, int len)
|
||||
{
|
||||
int ret = 0, rem, type, i;
|
||||
const struct nlattr *iter;
|
||||
struct wifi_ring_buffer_status rb;
|
||||
|
||||
nla_for_each_attr(iter, data, len, rem) {
|
||||
type = nla_type(iter);
|
||||
switch (type) {
|
||||
case LOGGER_ATTRIBUTE_RING_NAME:
|
||||
strcpy(rb.name, nla_data(iter));
|
||||
break;
|
||||
default:
|
||||
pr_err("%s(%d), Unknown type: %d\n", __func__, __LINE__, type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
ret = -EINVAL;
|
||||
for (i = 0; i < sizeof(ring_buffer) / sizeof(ring_buffer[0]); i++) {
|
||||
if (strcmp(rb.name, ring_buffer[i].name) == 0) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO
|
||||
* Add handle in the future
|
||||
*/
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int aicwf_vendor_logger_get_wake_reason_stats(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
const void *data, int len)
|
||||
{
|
||||
int ret;
|
||||
struct sk_buff *reply;
|
||||
uint32_t payload;
|
||||
|
||||
payload = sizeof(wake_reason_cnt.total_cmd_event_wake);
|
||||
reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload);
|
||||
|
||||
if (!reply)
|
||||
return -ENOMEM;
|
||||
|
||||
/* TODO
|
||||
* Add handle in the future
|
||||
*/
|
||||
if (nla_put_u32(reply, WAKE_STAT_ATTRIBUTE_TOTAL_CMD_EVENT, wake_reason_cnt.total_cmd_event_wake))
|
||||
goto out_put_fail;
|
||||
|
||||
ret = cfg80211_vendor_cmd_reply(reply);
|
||||
if (ret)
|
||||
wiphy_err(wiphy, "reply cmd error\n");
|
||||
|
||||
return ret;
|
||||
|
||||
out_put_fail:
|
||||
kfree_skb(reply);
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static int aicwf_vendor_apf_subcmd_get_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
const void *data, int len)
|
||||
{
|
||||
/* TODO
|
||||
* Add handle in the future
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aicwf_vendor_sub_cmd_set_mac(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
const void *data, int len)
|
||||
{
|
||||
int ret = 0, rem, type;
|
||||
const struct nlattr *iter;
|
||||
u8 mac[ETH_ALEN];
|
||||
|
||||
nla_for_each_attr(iter, data, len, rem) {
|
||||
type = nla_type(iter);
|
||||
switch (type) {
|
||||
case WIFI_VENDOR_ATTR_DRIVER_MAC_ADDR:
|
||||
memcpy(mac, nla_data(iter), ETH_ALEN);
|
||||
printk("%s, %02X:%02X:%02X:%02X:%02X:%02X\n", __func__,
|
||||
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
break;
|
||||
default:
|
||||
pr_err("%s(%d), Unknown type: %d\n", __func__, __LINE__, type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO
|
||||
* Add handle in the future
|
||||
*/
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct nla_policy
|
||||
aicwf_cfg80211_mkeep_alive_policy[MKEEP_ALIVE_ATTRIBUTE_MAX+1] = {
|
||||
[0] = {.type = NLA_UNSPEC },
|
||||
[MKEEP_ALIVE_ATTRIBUTE_ID] = { .type = NLA_U8 },
|
||||
[MKEEP_ALIVE_ATTRIBUTE_IP_PKT] = { .type = NLA_MSECS },
|
||||
[MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN] = { .type = NLA_U16 },
|
||||
[MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR] = { .type = NLA_MSECS,
|
||||
.len = ETH_ALEN },
|
||||
[MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR] = { .type = NLA_MSECS,
|
||||
.len = ETH_ALEN },
|
||||
[MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static const struct nla_policy
|
||||
aicwf_cfg80211_logger_policy[LOGGER_ATTRIBUTE_MAX + 1] = {
|
||||
[0] = {.type = NLA_UNSPEC },
|
||||
[LOGGER_ATTRIBUTE_DRIVER_VER] = { .type = NLA_BINARY },
|
||||
[LOGGER_ATTRIBUTE_FW_VER] = { .type = NLA_BINARY },
|
||||
[LOGGER_ATTRIBUTE_LOG_LEVEL] = { .type = NLA_U32 },
|
||||
[LOGGER_ATTRIBUTE_RING_FLAGS] = { .type = NLA_U32 },
|
||||
[LOGGER_ATTRIBUTE_LOG_TIME_INTVAL] = { .type = NLA_U32 },
|
||||
[LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE] = { .type = NLA_U32 },
|
||||
[LOGGER_ATTRIBUTE_RING_NAME] = { .type = NLA_STRING },
|
||||
};
|
||||
|
||||
static const struct nla_policy
|
||||
aicwf_cfg80211_subcmd_policy[GSCAN_ATTRIBUTE_MAX + 1] = {
|
||||
[0] = {.type = NLA_UNSPEC },
|
||||
[GSCAN_ATTRIBUTE_BAND] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static const struct nla_policy
|
||||
aicwf_cfg80211_andr_wifi_policy[ANDR_WIFI_ATTRIBUTE_MAX + 1] = {
|
||||
[0] = {.type = NLA_UNSPEC },
|
||||
[ANDR_WIFI_ATTRIBUTE_COUNTRY] = { .type = NLA_STRING },
|
||||
};
|
||||
|
||||
static const struct nla_policy
|
||||
aicwf_cfg80211_subcmd_set_mac_policy[WIFI_VENDOR_ATTR_DRIVER_MAX + 1] = {
|
||||
[0] = {.type = NLA_UNSPEC },
|
||||
[WIFI_VENDOR_ATTR_DRIVER_MAC_ADDR] = { .type = NLA_MSECS, .len = ETH_ALEN },
|
||||
};
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
|
||||
static int aicwf_dump_interface(struct wiphy *wiphy,
|
||||
struct wireless_dev *wdev, struct sk_buff *skb,
|
||||
const void *data, int data_len,
|
||||
unsigned long *storage)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct wiphy_vendor_command aicwf_vendor_cmd[] = {
|
||||
{
|
||||
{
|
||||
.vendor_id = GOOGLE_OUI,
|
||||
.subcmd = WIFI_OFFLOAD_SUBCMD_START_MKEEP_ALIVE
|
||||
},
|
||||
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
|
||||
.doit = aicwf_vendor_start_mkeep_alive,
|
||||
.dumpit = aicwf_dump_interface,
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
|
||||
.policy = aicwf_cfg80211_mkeep_alive_policy,
|
||||
.maxattr = MKEEP_ALIVE_ATTRIBUTE_MAX
|
||||
#endif
|
||||
},
|
||||
{
|
||||
{
|
||||
.vendor_id = GOOGLE_OUI,
|
||||
.subcmd = WIFI_OFFLOAD_SUBCMD_STOP_MKEEP_ALIVE
|
||||
},
|
||||
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
|
||||
.doit = aicwf_vendor_stop_mkeep_alive,
|
||||
.dumpit = aicwf_dump_interface,
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
|
||||
.policy = aicwf_cfg80211_mkeep_alive_policy,
|
||||
.maxattr = MKEEP_ALIVE_ATTRIBUTE_MAX
|
||||
#endif
|
||||
},
|
||||
{
|
||||
{
|
||||
.vendor_id = GOOGLE_OUI,
|
||||
.subcmd = LOGGER_GET_VER
|
||||
},
|
||||
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
|
||||
.doit = aicwf_vendor_get_ver,
|
||||
.dumpit = aicwf_dump_interface,
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
|
||||
.policy = aicwf_cfg80211_logger_policy,
|
||||
.maxattr = LOGGER_ATTRIBUTE_MAX
|
||||
#endif
|
||||
},
|
||||
{
|
||||
{
|
||||
.vendor_id = GOOGLE_OUI,
|
||||
.subcmd = GSCAN_SUBCMD_GET_CHANNEL_LIST
|
||||
},
|
||||
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
|
||||
.doit = aicwf_vendor_subcmd_get_channel_list,
|
||||
.dumpit = aicwf_dump_interface,
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
|
||||
.policy = aicwf_cfg80211_subcmd_policy,
|
||||
.maxattr = GSCAN_ATTRIBUTE_MAX
|
||||
#endif
|
||||
},
|
||||
{
|
||||
{
|
||||
.vendor_id = GOOGLE_OUI,
|
||||
.subcmd = WIFI_SUBCMD_SET_COUNTRY_CODE
|
||||
},
|
||||
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
|
||||
.doit = aicwf_vendor_subcmd_set_country_code,
|
||||
.dumpit = aicwf_dump_interface,
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
|
||||
.policy = aicwf_cfg80211_andr_wifi_policy,
|
||||
.maxattr = ANDR_WIFI_ATTRIBUTE_MAX
|
||||
#endif
|
||||
},
|
||||
{
|
||||
{
|
||||
.vendor_id = GOOGLE_OUI,
|
||||
.subcmd = LOGGER_TRIGGER_MEM_DUMP
|
||||
},
|
||||
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
|
||||
.doit = aicwf_vendor_logger_trigger_memory_dump,
|
||||
.dumpit = aicwf_dump_interface,
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
|
||||
.policy = VENDOR_CMD_RAW_DATA,
|
||||
#endif
|
||||
},
|
||||
{
|
||||
{
|
||||
.vendor_id = GOOGLE_OUI,
|
||||
.subcmd = WIFI_SUBCMD_GET_FEATURE_SET
|
||||
},
|
||||
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
|
||||
.doit = aicwf_vendor_subcmd_get_feature_set,
|
||||
.dumpit = aicwf_dump_interface,
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
|
||||
.policy = VENDOR_CMD_RAW_DATA,
|
||||
#endif
|
||||
},
|
||||
{
|
||||
{
|
||||
.vendor_id = GOOGLE_OUI,
|
||||
.subcmd = LOGGER_GET_FEATURE
|
||||
},
|
||||
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
|
||||
.doit = aicwf_vendor_logger_get_feature,
|
||||
.dumpit = aicwf_dump_interface,
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
|
||||
.policy = VENDOR_CMD_RAW_DATA,
|
||||
#endif
|
||||
},
|
||||
{
|
||||
{
|
||||
.vendor_id = GOOGLE_OUI,
|
||||
.subcmd = LOGGER_GET_RING_STATUS
|
||||
},
|
||||
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
|
||||
.doit = aicwf_vendor_logger_get_ring_status,
|
||||
.dumpit = aicwf_dump_interface,
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
|
||||
.policy = VENDOR_CMD_RAW_DATA,
|
||||
#endif
|
||||
},
|
||||
{
|
||||
{
|
||||
.vendor_id = GOOGLE_OUI,
|
||||
.subcmd = LOGGER_START_LOGGING
|
||||
},
|
||||
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
|
||||
.doit = aicwf_vendor_logger_start_logging,
|
||||
.dumpit = aicwf_dump_interface,
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
|
||||
.policy = aicwf_cfg80211_logger_policy,
|
||||
.maxattr = LOGGER_ATTRIBUTE_MAX
|
||||
#endif
|
||||
},
|
||||
{
|
||||
{
|
||||
.vendor_id = GOOGLE_OUI,
|
||||
.subcmd = LOGGER_GET_RING_DATA
|
||||
},
|
||||
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
|
||||
.doit = aicwf_vendor_logger_get_ring_data,
|
||||
.dumpit = aicwf_dump_interface,
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
|
||||
.policy = aicwf_cfg80211_logger_policy,
|
||||
.maxattr = LOGGER_ATTRIBUTE_MAX
|
||||
#endif
|
||||
},
|
||||
{
|
||||
{
|
||||
.vendor_id = GOOGLE_OUI,
|
||||
.subcmd = LOGGER_GET_WAKE_REASON_STATS
|
||||
},
|
||||
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
|
||||
.doit = aicwf_vendor_logger_get_wake_reason_stats,
|
||||
.dumpit = aicwf_dump_interface,
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
|
||||
.policy = VENDOR_CMD_RAW_DATA,
|
||||
#endif
|
||||
},
|
||||
{
|
||||
{
|
||||
.vendor_id = GOOGLE_OUI,
|
||||
.subcmd = APF_SUBCMD_GET_CAPABILITIES
|
||||
},
|
||||
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
|
||||
.doit = aicwf_vendor_apf_subcmd_get_capabilities,
|
||||
.dumpit = aicwf_dump_interface,
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
|
||||
.policy = VENDOR_CMD_RAW_DATA,
|
||||
#endif
|
||||
},
|
||||
{
|
||||
{
|
||||
.vendor_id = GOOGLE_OUI,
|
||||
.subcmd = VENDOR_NL80211_SUBCMD_SET_MAC
|
||||
},
|
||||
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
|
||||
.doit = aicwf_vendor_sub_cmd_set_mac,
|
||||
.dumpit = aicwf_dump_interface,
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
|
||||
.policy = aicwf_cfg80211_subcmd_set_mac_policy,
|
||||
.maxattr = WIFI_VENDOR_ATTR_DRIVER_MAX,
|
||||
#endif
|
||||
},
|
||||
{
|
||||
{
|
||||
.vendor_id = BRCM_OUI,
|
||||
.subcmd = VENDOR_NL80211_SUBCMD_SET_MAC
|
||||
},
|
||||
.flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_RUNNING,
|
||||
.doit = aicwf_vendor_sub_cmd_set_mac,
|
||||
.dumpit = aicwf_dump_interface,
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
|
||||
.policy = aicwf_cfg80211_subcmd_set_mac_policy,
|
||||
.maxattr = WIFI_VENDOR_ATTR_DRIVER_MAX,
|
||||
#endif
|
||||
},
|
||||
};
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
|
||||
static const struct nl80211_vendor_cmd_info aicwf_vendor_events[] = {
|
||||
};
|
||||
#endif
|
||||
|
||||
int aicwf_vendor_init(struct wiphy *wiphy)
|
||||
{
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
|
||||
wiphy->vendor_commands = aicwf_vendor_cmd;
|
||||
wiphy->n_vendor_commands = ARRAY_SIZE(aicwf_vendor_cmd);
|
||||
wiphy->vendor_events = aicwf_vendor_events;
|
||||
wiphy->n_vendor_events = ARRAY_SIZE(aicwf_vendor_events);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
346
drivers/net/wireless/aic8800/aic8800_fdrv/aic_vendor.h
Normal file
346
drivers/net/wireless/aic8800/aic8800_fdrv/aic_vendor.h
Normal file
@@ -0,0 +1,346 @@
|
||||
#ifndef _AIC_VENDOR_H
|
||||
#define _AIC_VENDOR_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#define GOOGLE_OUI 0x001A11
|
||||
#define BRCM_OUI 0x001018
|
||||
|
||||
typedef enum {
|
||||
START_MKEEP_ALIVE,
|
||||
STOP_MKEEP_ALIVE,
|
||||
} GetCmdType;
|
||||
|
||||
typedef enum {
|
||||
/* don't use 0 as a valid subcommand */
|
||||
VENDOR_NL80211_SUBCMD_UNSPECIFIED,
|
||||
|
||||
/* define all vendor startup commands between 0x0 and 0x0FFF */
|
||||
VENDOR_NL80211_SUBCMD_RANGE_START = 0x0001,
|
||||
VENDOR_NL80211_SUBCMD_RANGE_END = 0x0FFF,
|
||||
|
||||
/* define all GScan related commands between 0x1000 and 0x10FF */
|
||||
ANDROID_NL80211_SUBCMD_GSCAN_RANGE_START = 0x1000,
|
||||
ANDROID_NL80211_SUBCMD_GSCAN_RANGE_END = 0x10FF,
|
||||
|
||||
/* define all NearbyDiscovery related commands between 0x1100 and 0x11FF */
|
||||
ANDROID_NL80211_SUBCMD_NBD_RANGE_START = 0x1100,
|
||||
ANDROID_NL80211_SUBCMD_NBD_RANGE_END = 0x11FF,
|
||||
|
||||
/* define all RTT related commands between 0x1100 and 0x11FF */
|
||||
ANDROID_NL80211_SUBCMD_RTT_RANGE_START = 0x1100,
|
||||
ANDROID_NL80211_SUBCMD_RTT_RANGE_END = 0x11FF,
|
||||
|
||||
ANDROID_NL80211_SUBCMD_LSTATS_RANGE_START = 0x1200,
|
||||
ANDROID_NL80211_SUBCMD_LSTATS_RANGE_END = 0x12FF,
|
||||
|
||||
/* define all Logger related commands between 0x1400 and 0x14FF */
|
||||
ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START = 0x1400,
|
||||
ANDROID_NL80211_SUBCMD_DEBUG_RANGE_END = 0x14FF,
|
||||
|
||||
/* define all wifi offload related commands between 0x1600 and 0x16FF */
|
||||
ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_START = 0x1600,
|
||||
ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_END = 0x16FF,
|
||||
|
||||
/* define all NAN related commands between 0x1700 and 0x17FF */
|
||||
ANDROID_NL80211_SUBCMD_NAN_RANGE_START = 0x1700,
|
||||
ANDROID_NL80211_SUBCMD_NAN_RANGE_END = 0x17FF,
|
||||
|
||||
/* define all Android Packet Filter related commands between 0x1800 and 0x18FF */
|
||||
ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_START = 0x1800,
|
||||
ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_END = 0x18FF,
|
||||
|
||||
/* This is reserved for future usage */
|
||||
|
||||
} ANDROID_VENDOR_SUB_COMMAND;
|
||||
|
||||
typedef enum {
|
||||
WIFI_OFFLOAD_SUBCMD_START_MKEEP_ALIVE = ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_START,
|
||||
WIFI_OFFLOAD_SUBCMD_STOP_MKEEP_ALIVE,
|
||||
} WIFI_OFFLOAD_SUB_COMMAND;
|
||||
|
||||
|
||||
enum mkeep_alive_attributes {
|
||||
MKEEP_ALIVE_ATTRIBUTE_ID = 0x1,
|
||||
MKEEP_ALIVE_ATTRIBUTE_IP_PKT,
|
||||
MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN,
|
||||
MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR,
|
||||
MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR,
|
||||
MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC,
|
||||
MKEEP_ALIVE_ATTRIBUTE_AFTER_LAST,
|
||||
MKEEP_ALIVE_ATTRIBUTE_MAX = MKEEP_ALIVE_ATTRIBUTE_AFTER_LAST - 1
|
||||
};
|
||||
|
||||
enum debug_sub_command {
|
||||
LOGGER_START_LOGGING = ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START,
|
||||
LOGGER_TRIGGER_MEM_DUMP,
|
||||
LOGGER_GET_MEM_DUMP,
|
||||
LOGGER_GET_VER,
|
||||
LOGGER_GET_RING_STATUS,
|
||||
LOGGER_GET_RING_DATA,
|
||||
LOGGER_GET_FEATURE,
|
||||
LOGGER_RESET_LOGGING,
|
||||
LOGGER_TRIGGER_DRIVER_MEM_DUMP,
|
||||
LOGGER_GET_DRIVER_MEM_DUMP,
|
||||
LOGGER_START_PKT_FATE_MONITORING,
|
||||
LOGGER_GET_TX_PKT_FATES,
|
||||
LOGGER_GET_RX_PKT_FATES,
|
||||
LOGGER_GET_WAKE_REASON_STATS,
|
||||
LOGGER_DEBUG_GET_DUMP,
|
||||
LOGGER_FILE_DUMP_DONE_IND,
|
||||
LOGGER_SET_HAL_START,
|
||||
LOGGER_HAL_STOP,
|
||||
LOGGER_SET_HAL_PID,
|
||||
};
|
||||
|
||||
enum logger_attributes {
|
||||
LOGGER_ATTRIBUTE_INVALID = 0,
|
||||
LOGGER_ATTRIBUTE_DRIVER_VER,
|
||||
LOGGER_ATTRIBUTE_FW_VER,
|
||||
LOGGER_ATTRIBUTE_RING_ID,
|
||||
LOGGER_ATTRIBUTE_RING_NAME,
|
||||
LOGGER_ATTRIBUTE_RING_FLAGS,
|
||||
LOGGER_ATTRIBUTE_LOG_LEVEL,
|
||||
LOGGER_ATTRIBUTE_LOG_TIME_INTVAL,
|
||||
LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE,
|
||||
LOGGER_ATTRIBUTE_FW_DUMP_LEN,
|
||||
LOGGER_ATTRIBUTE_FW_DUMP_DATA,
|
||||
// LOGGER_ATTRIBUTE_FW_ERR_CODE,
|
||||
LOGGER_ATTRIBUTE_RING_DATA,
|
||||
LOGGER_ATTRIBUTE_RING_STATUS,
|
||||
LOGGER_ATTRIBUTE_RING_NUM,
|
||||
LOGGER_ATTRIBUTE_DRIVER_DUMP_LEN,
|
||||
LOGGER_ATTRIBUTE_DRIVER_DUMP_DATA,
|
||||
LOGGER_ATTRIBUTE_PKT_FATE_NUM,
|
||||
LOGGER_ATTRIBUTE_PKT_FATE_DATA,
|
||||
LOGGER_ATTRIBUTE_AFTER_LAST,
|
||||
LOGGER_ATTRIBUTE_MAX = LOGGER_ATTRIBUTE_AFTER_LAST - 1,
|
||||
};
|
||||
|
||||
enum wifi_sub_command {
|
||||
GSCAN_SUBCMD_GET_CAPABILITIES = ANDROID_NL80211_SUBCMD_GSCAN_RANGE_START,
|
||||
GSCAN_SUBCMD_SET_CONFIG, /* 0x1001 */
|
||||
GSCAN_SUBCMD_SET_SCAN_CONFIG, /* 0x1002 */
|
||||
GSCAN_SUBCMD_ENABLE_GSCAN, /* 0x1003 */
|
||||
GSCAN_SUBCMD_GET_SCAN_RESULTS, /* 0x1004 */
|
||||
GSCAN_SUBCMD_SCAN_RESULTS, /* 0x1005 */
|
||||
GSCAN_SUBCMD_SET_HOTLIST, /* 0x1006 */
|
||||
GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG, /* 0x1007 */
|
||||
GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS, /* 0x1008 */
|
||||
GSCAN_SUBCMD_GET_CHANNEL_LIST, /* 0x1009 */
|
||||
WIFI_SUBCMD_GET_FEATURE_SET, /* 0x100A */
|
||||
WIFI_SUBCMD_GET_FEATURE_SET_MATRIX, /* 0x100B */
|
||||
WIFI_SUBCMD_SET_PNO_RANDOM_MAC_OUI, /* 0x100C */
|
||||
WIFI_SUBCMD_NODFS_SET, /* 0x100D */
|
||||
WIFI_SUBCMD_SET_COUNTRY_CODE, /* 0x100E */
|
||||
/* Add more sub commands here */
|
||||
GSCAN_SUBCMD_SET_EPNO_SSID, /* 0x100F */
|
||||
WIFI_SUBCMD_SET_SSID_WHITE_LIST, /* 0x1010 */
|
||||
WIFI_SUBCMD_SET_ROAM_PARAMS, /* 0x1011 */
|
||||
WIFI_SUBCMD_ENABLE_LAZY_ROAM, /* 0x1012 */
|
||||
WIFI_SUBCMD_SET_BSSID_PREF, /* 0x1013 */
|
||||
WIFI_SUBCMD_SET_BSSID_BLACKLIST, /* 0x1014 */
|
||||
GSCAN_SUBCMD_ANQPO_CONFIG, /* 0x1015 */
|
||||
WIFI_SUBCMD_SET_RSSI_MONITOR, /* 0x1016 */
|
||||
WIFI_SUBCMD_CONFIG_ND_OFFLOAD, /* 0x1017 */
|
||||
/* Add more sub commands here */
|
||||
GSCAN_SUBCMD_MAX,
|
||||
APF_SUBCMD_GET_CAPABILITIES = ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_START,
|
||||
APF_SUBCMD_SET_FILTER,
|
||||
};
|
||||
|
||||
enum gscan_attributes {
|
||||
GSCAN_ATTRIBUTE_NUM_BUCKETS = 10,
|
||||
GSCAN_ATTRIBUTE_BASE_PERIOD,
|
||||
GSCAN_ATTRIBUTE_BUCKETS_BAND,
|
||||
GSCAN_ATTRIBUTE_BUCKET_ID,
|
||||
GSCAN_ATTRIBUTE_BUCKET_PERIOD,
|
||||
GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS,
|
||||
GSCAN_ATTRIBUTE_BUCKET_CHANNELS,
|
||||
GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN,
|
||||
GSCAN_ATTRIBUTE_REPORT_THRESHOLD,
|
||||
GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE,
|
||||
GSCAN_ATTRIBUTE_BAND = GSCAN_ATTRIBUTE_BUCKETS_BAND,
|
||||
|
||||
GSCAN_ATTRIBUTE_ENABLE_FEATURE = 20,
|
||||
GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE, /* indicates no more results */
|
||||
GSCAN_ATTRIBUTE_FLUSH_FEATURE, /* Flush all the configs */
|
||||
GSCAN_ENABLE_FULL_SCAN_RESULTS,
|
||||
GSCAN_ATTRIBUTE_REPORT_EVENTS,
|
||||
|
||||
/* remaining reserved for additional attributes */
|
||||
GSCAN_ATTRIBUTE_NUM_OF_RESULTS = 30,
|
||||
GSCAN_ATTRIBUTE_FLUSH_RESULTS,
|
||||
GSCAN_ATTRIBUTE_SCAN_RESULTS, /* flat array of wifi_scan_result */
|
||||
GSCAN_ATTRIBUTE_SCAN_ID, /* indicates scan number */
|
||||
GSCAN_ATTRIBUTE_SCAN_FLAGS, /* indicates if scan was aborted */
|
||||
GSCAN_ATTRIBUTE_AP_FLAGS, /* flags on significant change event */
|
||||
GSCAN_ATTRIBUTE_NUM_CHANNELS,
|
||||
GSCAN_ATTRIBUTE_CHANNEL_LIST,
|
||||
GSCAN_ATTRIBUTE_CH_BUCKET_BITMASK,
|
||||
|
||||
GSCAN_ATTRIBUTE_AFTER_LAST,
|
||||
GSCAN_ATTRIBUTE_MAX = GSCAN_ATTRIBUTE_AFTER_LAST - 1,
|
||||
};
|
||||
|
||||
enum andr_wifi_attributes {
|
||||
ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET,
|
||||
ANDR_WIFI_ATTRIBUTE_FEATURE_SET,
|
||||
ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI,
|
||||
ANDR_WIFI_ATTRIBUTE_NODFS_SET,
|
||||
ANDR_WIFI_ATTRIBUTE_COUNTRY,
|
||||
ANDR_WIFI_ATTRIBUTE_ND_OFFLOAD_VALUE,
|
||||
// Add more attribute here
|
||||
ANDR_WIFI_ATTRIBUTE_AFTER_LAST,
|
||||
ANDR_WIFI_ATTRIBUTE_MAX = ANDR_WIFI_ATTRIBUTE_AFTER_LAST - 1,
|
||||
};
|
||||
|
||||
enum wifi_support_feature {
|
||||
/* Feature enums */
|
||||
WIFI_FEATURE_INFRA = 0x0001, /* Basic infrastructure mode */
|
||||
WIFI_FEATURE_INFRA_5G = 0x0002, /* Support for 5, GHz Band */
|
||||
WIFI_FEATURE_HOTSPOT = 0x0004, /* Support for GAS/ANQP */
|
||||
WIFI_FEATURE_P2P = 0x0008, /* Wifi-Direct */
|
||||
WIFI_FEATURE_SOFT_AP = 0x0010, /* Soft AP */
|
||||
WIFI_FEATURE_GSCAN = 0x0020, /* Google-Scan APIs */
|
||||
WIFI_FEATURE_NAN = 0x0040, /* Neighbor Awareness Networking */
|
||||
WIFI_FEATURE_D2D_RTT = 0x0080, /* Device-to-device RTT */
|
||||
WIFI_FEATURE_D2AP_RTT = 0x0100, /* Device-to-AP RTT */
|
||||
WIFI_FEATURE_BATCH_SCAN = 0x0200, /* Batched Scan (legacy) */
|
||||
WIFI_FEATURE_PNO = 0x0400, /* Preferred network offload */
|
||||
WIFI_FEATURE_ADDITIONAL_STA = 0x0800, /* Support for two STAs */
|
||||
WIFI_FEATURE_TDLS = 0x1000, /* Tunnel directed link setup */
|
||||
WIFI_FEATURE_TDLS_OFFCHANNEL = 0x2000, /* Support for TDLS off channel */
|
||||
WIFI_FEATURE_EPR = 0x4000, /* Enhanced power reporting */
|
||||
WIFI_FEATURE_AP_STA = 0x8000, /* Support for AP STA Concurrency */
|
||||
WIFI_FEATURE_LINK_LAYER_STATS = 0x10000, /* Support for Linkstats */
|
||||
WIFI_FEATURE_LOGGER = 0x20000, /* WiFi Logger */
|
||||
WIFI_FEATURE_HAL_EPNO = 0x40000, /* WiFi PNO enhanced */
|
||||
WIFI_FEATURE_RSSI_MONITOR = 0x80000, /* RSSI Monitor */
|
||||
WIFI_FEATURE_MKEEP_ALIVE = 0x100000, /* WiFi mkeep_alive */
|
||||
WIFI_FEATURE_CONFIG_NDO = 0x200000, /* ND offload configure */
|
||||
WIFI_FEATURE_TX_TRANSMIT_POWER = 0x400000, /* Capture Tx transmit power levels */
|
||||
WIFI_FEATURE_CONTROL_ROAMING = 0x800000, /* Enable/Disable firmware roaming */
|
||||
WIFI_FEATURE_IE_WHITELIST = 0x1000000, /* Support Probe IE white listing */
|
||||
WIFI_FEATURE_SCAN_RAND = 0x2000000, /* Support MAC & Probe Sequence Number randomization */
|
||||
WIFI_FEATURE_INVALID = 0xFFFFFFFF, /* Invalid Feature */
|
||||
};
|
||||
|
||||
enum wifi_logger_feature {
|
||||
WIFI_LOGGER_MEMORY_DUMP_SUPPORTED = (1 << (0)), // Memory dump of FW
|
||||
WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_SUPPORTED = (1 << (1)), // PKT status
|
||||
WIFI_LOGGER_CONNECT_EVENT_SUPPORTED = (1 << (2)), // Connectivity event
|
||||
WIFI_LOGGER_POWER_EVENT_SUPPORTED = (1 << (3)), // POWER of Driver
|
||||
WIFI_LOGGER_WAKE_LOCK_SUPPORTED = (1 << (4)), // WAKE LOCK of Driver
|
||||
WIFI_LOGGER_VERBOSE_SUPPORTED = (1 << (5)), // verbose log of FW
|
||||
WIFI_LOGGER_WATCHDOG_TIMER_SUPPORTED = (1 << (6)), // monitor the health of FW
|
||||
WIFI_LOGGER_DRIVER_DUMP_SUPPORTED = (1 << (7)), // dumps driver state
|
||||
WIFI_LOGGER_PACKET_FATE_SUPPORTED = (1 << (8)), // tracks connection packets' fate
|
||||
};
|
||||
|
||||
enum wake_stats_attributes {
|
||||
WAKE_STAT_ATTRIBUTE_TOTAL_CMD_EVENT,
|
||||
WAKE_STAT_ATTRIBUTE_CMD_EVENT_WAKE,
|
||||
WAKE_STAT_ATTRIBUTE_CMD_EVENT_COUNT,
|
||||
WAKE_STAT_ATTRIBUTE_CMD_COUNT_USED,
|
||||
WAKE_STAT_ATTRIBUTE_TOTAL_DRIVER_FW,
|
||||
WAKE_STAT_ATTRIBUTE_DRIVER_FW_WAKE,
|
||||
WAKE_STAT_ATTRIBUTE_DRIVER_FW_COUNT,
|
||||
WAKE_STAT_ATTRIBUTE_DRIVER_FW_COUNT_USED,
|
||||
WAKE_STAT_ATTRIBUTE_TOTAL_RX_DATA_WAKE,
|
||||
WAKE_STAT_ATTRIBUTE_RX_UNICAST_COUNT,
|
||||
WAKE_STAT_ATTRIBUTE_RX_MULTICAST_COUNT,
|
||||
WAKE_STAT_ATTRIBUTE_RX_BROADCAST_COUNT,
|
||||
WAKE_STAT_ATTRIBUTE_RX_ICMP_PKT,
|
||||
WAKE_STAT_ATTRIBUTE_RX_ICMP6_PKT,
|
||||
WAKE_STAT_ATTRIBUTE_RX_ICMP6_RA,
|
||||
WAKE_STAT_ATTRIBUTE_RX_ICMP6_NA,
|
||||
WAKE_STAT_ATTRIBUTE_RX_ICMP6_NS,
|
||||
WAKE_STAT_ATTRIBUTE_IPV4_RX_MULTICAST_ADD_CNT,
|
||||
WAKE_STAT_ATTRIBUTE_IPV6_RX_MULTICAST_ADD_CNT,
|
||||
WAKE_STAT_ATTRIBUTE_OTHER__RX_MULTICAST_ADD_CNT,
|
||||
WAKE_STAT_ATTRIBUTE_RX_MULTICAST_PKT_INFO,
|
||||
WAKE_STAT_ATTRIBUTE_AFTER_LAST,
|
||||
WAKE_STAT_ATTRIBUTE_MAX = WAKE_STAT_ATTRIBUTE_AFTER_LAST - 1,
|
||||
};
|
||||
|
||||
enum vendor_nl80211_subcmd {
|
||||
/* copied from wpa_supplicant brcm definations */
|
||||
VENDOR_NL80211_SUBCMD_UNSPEC = 0,
|
||||
VENDOR_NL80211_SUBCMD_SET_PMK = 4,
|
||||
VENDOR_NL80211_SUBCMD_SET_MAC = 6,
|
||||
VENDOR_NL80211_SCMD_ACS = 9,
|
||||
VENDOR_NL80211_SCMD_MAX = 10,
|
||||
};
|
||||
|
||||
enum nl80211_vendor_subcmd_attributes {
|
||||
WIFI_VENDOR_ATTR_DRIVER_CMD = 0,
|
||||
WIFI_VENDOR_ATTR_DRIVER_KEY_PMK = 1,
|
||||
WIFI_VENDOR_ATTR_DRIVER_MAC_ADDR = 3,
|
||||
WIFI_VENDOR_ATTR_DRIVER_AFTER_LAST = 5,
|
||||
WIFI_VENDOR_ATTR_DRIVER_MAX =
|
||||
WIFI_VENDOR_ATTR_DRIVER_AFTER_LAST - 1,
|
||||
};
|
||||
|
||||
typedef int wifi_ring_buffer_id;
|
||||
|
||||
struct wifi_ring_buffer_status {
|
||||
u8 name[32];
|
||||
u32 flags;
|
||||
wifi_ring_buffer_id ring_id;
|
||||
u32 ring_buffer_byte_size;
|
||||
u32 verbose_level;
|
||||
u32 written_bytes;
|
||||
u32 read_bytes;
|
||||
u32 written_records;
|
||||
};
|
||||
|
||||
struct rx_data_cnt_details_t {
|
||||
int rx_unicast_cnt; /*Total rx unicast packet which woke up host */
|
||||
int rx_multicast_cnt; /*Total rx multicast packet which woke up host */
|
||||
int rx_broadcast_cnt; /*Total rx broadcast packet which woke up host */
|
||||
};
|
||||
|
||||
struct rx_wake_pkt_type_classification_t {
|
||||
int icmp_pkt; /*wake icmp packet count */
|
||||
int icmp6_pkt; /*wake icmp6 packet count */
|
||||
int icmp6_ra; /*wake icmp6 RA packet count */
|
||||
int icmp6_na; /*wake icmp6 NA packet count */
|
||||
int icmp6_ns; /*wake icmp6 NS packet count */
|
||||
//ToDo: Any more interesting classification to add?
|
||||
};
|
||||
|
||||
struct rx_multicast_cnt_t{
|
||||
int ipv4_rx_multicast_addr_cnt; /*Rx wake packet was ipv4 multicast */
|
||||
int ipv6_rx_multicast_addr_cnt; /*Rx wake packet was ipv6 multicast */
|
||||
int other_rx_multicast_addr_cnt;/*Rx wake packet was non-ipv4 and non-ipv6*/
|
||||
};
|
||||
|
||||
struct wlan_driver_wake_reason_cnt_t {
|
||||
int total_cmd_event_wake; /* Total count of cmd event wakes */
|
||||
int *cmd_event_wake_cnt; /* Individual wake count array, each index a reason */
|
||||
int cmd_event_wake_cnt_sz; /* Max number of cmd event wake reasons */
|
||||
int cmd_event_wake_cnt_used; /* Number of cmd event wake reasons specific to the driver */
|
||||
|
||||
int total_driver_fw_local_wake; /* Total count of drive/fw wakes, for local reasons */
|
||||
int *driver_fw_local_wake_cnt; /* Individual wake count array, each index a reason */
|
||||
int driver_fw_local_wake_cnt_sz; /* Max number of local driver/fw wake reasons */
|
||||
int driver_fw_local_wake_cnt_used; /* Number of local driver/fw wake reasons specific to the driver */
|
||||
|
||||
int total_rx_data_wake; /* total data rx packets, that woke up host */
|
||||
struct rx_data_cnt_details_t rx_wake_details;
|
||||
struct rx_wake_pkt_type_classification_t rx_wake_pkt_classification_info;
|
||||
struct rx_multicast_cnt_t rx_multicast_wake_pkt_info;
|
||||
};
|
||||
|
||||
typedef struct wl_mkeep_alive_pkt {
|
||||
u16 version; /* Version for mkeep_alive */
|
||||
u16 length; /* length of fixed parameters in the structure */
|
||||
u32 period_msec; /* high bit on means immediate send */
|
||||
u16 len_bytes;
|
||||
u8 keep_alive_id; /* 0 - 3 for N = 4 */
|
||||
u8 data[1];
|
||||
} wl_mkeep_alive_pkt_t;
|
||||
|
||||
#endif /* _AIC_VENDOR_H */
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
#include "rwnx_main.h"
|
||||
#include "rwnx_msg_tx.h"
|
||||
#include "reg_access.h"
|
||||
#include "aicwf_compat_8800d80.h"
|
||||
|
||||
#define FW_USERCONFIG_NAME_8800D80 "aic_userconfig_8800d80.txt"
|
||||
|
||||
int rwnx_request_firmware_common(struct rwnx_hw *rwnx_hw,
|
||||
u32** buffer, const char *filename);
|
||||
void rwnx_plat_userconfig_parsing2(char *buffer, int size);
|
||||
void rwnx_plat_userconfig_parsing3(char *buffer, int size);
|
||||
|
||||
void rwnx_release_firmware_common(u32** buffer);
|
||||
|
||||
int aicwf_set_rf_config_8800d80(struct rwnx_hw *rwnx_hw, struct mm_set_rf_calib_cfm *cfm)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if ((ret = rwnx_send_txpwr_lvl_v3_req(rwnx_hw))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((ret = rwnx_send_txpwr_ofst2x_req(rwnx_hw))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (testmode == 0) {
|
||||
if ((ret = rwnx_send_rf_calib_req(rwnx_hw, cfm))) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
int rwnx_plat_userconfig_load_8800d80(struct rwnx_hw *rwnx_hw)
|
||||
{
|
||||
int size;
|
||||
u32 *dst=NULL;
|
||||
char *filename = FW_USERCONFIG_NAME_8800D80;
|
||||
|
||||
AICWFDBG(LOGINFO, "userconfig file path:%s \r\n", filename);
|
||||
|
||||
/* load file */
|
||||
size = rwnx_request_firmware_common(rwnx_hw, &dst, filename);
|
||||
if (size <= 0) {
|
||||
AICWFDBG(LOGERROR, "wrong size of firmware file\n");
|
||||
dst = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Copy the file on the Embedded side */
|
||||
AICWFDBG(LOGINFO, "### Load file done: %s, size=%d\n", filename, size);
|
||||
|
||||
rwnx_plat_userconfig_parsing3((char *)dst, size);
|
||||
|
||||
rwnx_release_firmware_common(&dst);
|
||||
|
||||
AICWFDBG(LOGINFO, "userconfig download complete\n\n");
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user