diff --git a/Makefile b/Makefile
|
index 4c06cbe89..3dbf9430a 100644
|
--- a/Makefile
|
+++ b/Makefile
|
@@ -383,6 +383,9 @@ include $(srctree)/scripts/subarch.include
|
# Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile
|
ARCH ?= $(SUBARCH)
|
|
+ARCH = arm64
|
+CROSS_COMPILE ?= aarch64-linux-gnu-
|
+
|
# Architecture as present in compile.h
|
UTS_MACHINE := $(ARCH)
|
SRCARCH := $(ARCH)
|
diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile
|
index 9a7319c6b..23cb09c85 100644
|
--- a/arch/arm64/boot/dts/freescale/Makefile
|
+++ b/arch/arm64/boot/dts/freescale/Makefile
|
@@ -119,6 +119,7 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mp-phyboard-pollux-rdk.dtb
|
dtb-$(CONFIG_ARCH_MXC) += imx8mq-evk.dtb imx8mq-evk-rpmsg.dtb imx8mp-ab2.dtb
|
dtb-$(CONFIG_ARCH_MXC) += imx8mp-ddr4-evk.dtb
|
dtb-$(CONFIG_ARCH_MXC) += imx8mp-evk-ndm.dtb
|
+dtb-$(CONFIG_ARCH_MXC) += gauguin-imx8mp.dtb
|
dtb-$(CONFIG_ARCH_MXC) += imx8mq-evk.dtb imx8mq-evk-rpmsg.dtb imx8mq-evk-pcie1-m2.dtb imx8mq-evk-usd-wifi.dtb \
|
imx8mq-evk-usdhc2-m2.dtb
|
dtb-$(CONFIG_ARCH_MXC) += imx8mq-evk-ak4497.dtb imx8mq-evk-audio-tdm.dtb imx8mq-evk-pdm.dtb
|
diff --git a/arch/arm64/boot/dts/freescale/gauguin-imx8mp.dts b/arch/arm64/boot/dts/freescale/gauguin-imx8mp.dts
|
new file mode 100644
|
index 000000000..f48c97c78
|
--- /dev/null
|
+++ b/arch/arm64/boot/dts/freescale/gauguin-imx8mp.dts
|
@@ -0,0 +1,1000 @@
|
+/*
|
+ * Device Tree Source for ZhiTu GauGuin Board - i.MX8MP
|
+ * Based on imx8mp-evk.dts/imx8mp-evk.dtsi
|
+ *
|
+ * Copyright (C) 2023 LingYun IoT System Studio.
|
+ * Author: Guo Wenxue<guowenxue@gmail.com>
|
+ */
|
+
|
+/dts-v1/;
|
+
|
+#include <dt-bindings/usb/pd.h>
|
+#include "imx8mp.dtsi"
|
+
|
+// #define SIMPLE_CARD /*simple_card support */
|
+
|
+/ {
|
+ model = "ZhiTu GauGuin Board - i.MX8MP";
|
+ compatible = "fsl,imx8mp-evk", "fsl,imx8mp";
|
+
|
+ chosen {
|
+ stdout-path = &uart2;
|
+ };
|
+
|
+ gpio-devs-ctrl {
|
+ compatible = "gpio-leds";
|
+ pinctrl-names = "devs-group";
|
+ pinctrl-0 = <&pinctrl_gpio_devs_group>;
|
+
|
+ uart-switch {
|
+ label = "uart-switch";
|
+ gpios = <&gpio4 27 GPIO_ACTIVE_HIGH>;
|
+ default-state = "on";
|
+ };
|
+
|
+ usb1-vbus {
|
+ label = "usb1-vbus-en";
|
+ gpios = <&gpio4 25 GPIO_ACTIVE_HIGH>;
|
+ default-state = "on";
|
+ };
|
+
|
+ wwan-power-on {
|
+ label = "wwan-power-on";
|
+ gpios = <&gpio2 16 GPIO_ACTIVE_LOW>;
|
+ default-state = "on";
|
+ };
|
+
|
+ wwan-reset {
|
+ label = "wwan-reset";
|
+ gpios = <&gpio2 1 GPIO_ACTIVE_HIGH>;
|
+ default-state = "on";
|
+ };
|
+ };
|
+
|
+ gpio-leds {
|
+ compatible = "gpio-leds";
|
+ pinctrl-names = "default";
|
+ pinctrl-0 = <&pinctrl_gpio_leds_group>;
|
+
|
+ sys-status {
|
+ label = "sys-status";
|
+ gpios = <&gpio3 16 GPIO_ACTIVE_HIGH>;
|
+ // linux,default-trigger = "heartbeat";
|
+ default-state = "on";
|
+ };
|
+
|
+ rgb-led-red {
|
+ label = "red";
|
+ gpios = <&gpio2 11 GPIO_ACTIVE_HIGH>;
|
+ default-state = "on";
|
+ };
|
+
|
+ rgb-led-green {
|
+ label = "green";
|
+ gpios = <&gpio2 10 GPIO_ACTIVE_HIGH>;
|
+ default-state = "off";
|
+ };
|
+
|
+ rgb-led-blue {
|
+ label = "blue";
|
+ gpios = <&gpio2 17 GPIO_ACTIVE_HIGH>;
|
+ default-state = "off";
|
+ };
|
+
|
+ rgb-led-ext-red {
|
+ label = "ext-red";
|
+ gpios = <&gpio3 25 GPIO_ACTIVE_HIGH>;
|
+ default-state = "on";
|
+ };
|
+
|
+ rgb-led-ext-green {
|
+ label = "ext-green";
|
+ gpios = <&gpio3 19 GPIO_ACTIVE_HIGH>;
|
+ default-state = "on";
|
+ };
|
+
|
+ rgb-led-ext-blue {
|
+ label = "ext-blue";
|
+ gpios = <&gpio3 20 GPIO_ACTIVE_HIGH>;
|
+ default-state = "on";
|
+ };
|
+ };
|
+
|
+ memory@40000000 {
|
+ device_type = "memory";
|
+ reg = <0x0 0x40000000 0 0xc0000000>,
|
+ <0x1 0x00000000 0 0xc0000000>;
|
+ };
|
+ /*+--------------+
|
+ | Regulator |
|
+ +--------------+*/
|
+ /*4G power_en # low-->en*/
|
+ regulator-wwan-prower-en {
|
+ compatible = "regulator-fixed";
|
+ regulator-name = "wwan-prower-en";
|
+ pinctrl-names = "default";
|
+ pinctrl-0 = <&pinctrl_wwan_reg>;
|
+ regulator-min-microvolt = <3300000>;
|
+ regulator-max-microvolt = <3300000>;
|
+ gpios = <&gpio5 10 GPIO_ACTIVE_LOW>;
|
+ enable-active-low;
|
+ regulator-always-on;
|
+ };
|
+
|
+ /*usb host vbus en # low-->en*/
|
+ regulator-usb-host-vbus-en {
|
+ compatible = "regulator-fixed";
|
+ regulator-name = "usb-host-vbus-en";
|
+ pinctrl-names = "default";
|
+ pinctrl-0 = <&pinctrl_usb_host_reg>;
|
+ regulator-min-microvolt = <3300000>;
|
+ regulator-max-microvolt = <3300000>;
|
+ gpios = <&gpio5 12 GPIO_ACTIVE_LOW>;
|
+ enable-active-low;
|
+ regulator-always-on;
|
+ };
|
+
|
+ /*lcd reset : 硬件已经拉高*/
|
+ regulator-lcd-reset {
|
+ compatible = "regulator-fixed";
|
+ regulator-name = "lcd-reset";
|
+ regulator-min-microvolt = <3300000>;
|
+ regulator-max-microvolt = <3300000>;
|
+ gpios = <&gpio5 7 GPIO_ACTIVE_HIGH>;
|
+ enable-active-high;
|
+ regulator-boot-on;
|
+ regulator-always-on;
|
+ };
|
+ /delete-node/ regulator-lcd-reset;
|
+
|
+ /*audio ap shotdown low-->en*/
|
+ reg_audio_pwr: regulator-audio-pwr {
|
+ compatible = "regulator-fixed";
|
+ regulator-name = "audio-pwr";
|
+ regulator-min-microvolt = <3300000>;
|
+ regulator-max-microvolt = <3300000>;
|
+ gpios = <&gpio4 28 GPIO_ACTIVE_LOW>;
|
+ enable-active-low;
|
+ regulator-always-on;
|
+ };
|
+
|
+ /*+---------------+
|
+ | Sound Card |
|
+ +--------------+*/
|
+#ifndef SIMPLE_CARD
|
+ sound-nau8822 {
|
+ compatible = "fsl,imx-audio-nau8822";
|
+ model = "nau8822-audio";/*声卡名字*/
|
+ audio-cpu = <&sai3>; /*cpu-dai*/
|
+ audio-codec = <&codec>;/*codec-dai*/
|
+ audio-asrc = <&easrc>; /*增强型异步采样器*/
|
+ audio-routing = //sink + source 需使用 源码已有的组件
|
+ "Headphone Jack", "LHP",
|
+ "Headphone Jack", "RHP",
|
+ "Ext Spk", "LSPK",
|
+ "Ext Spk", "RSPK",
|
+ "Line Out Jack", "AUXOUT1",
|
+ "Line Out Jack", "AUXOUT2",
|
+ "LAUX", "Line In Jack",
|
+ "RAUX", "Line In Jack",
|
+ "LMICN", "Mic Jack",
|
+ "LMICP", "Mic Jack",
|
+ "RMICN", "Mic Jack",
|
+ "RMICP", "Mic Jack";
|
+ };
|
+#else
|
+ sound_card: sound-card
|
+ {
|
+ compatible = "simple-audio-card";
|
+ simple-audio-card,bitclock-master = <&dailink_master>;/*master 时钟 */
|
+ simple-audio-card,format = "i2s";/*传输格式*/
|
+ simple-audio-card,frame-master = <&dailink_master>;/*master 帧*/
|
+ simple-audio-card,name = "imx8mp-nau8822"; /*aplay -l 出现的声卡名字*/
|
+ simple-audio-card,widgets = /*声卡组件 board组件*/
|
+ "Headphones", "Headphones",
|
+ "Line Out", "Line Out",
|
+ "Speaker", "Speaker",
|
+ "Microphone", "Mic In",
|
+ "Line", "Line In";
|
+ simple-audio-card,routing = /*音频路由 sink + source*/
|
+ "Headphones", "LHP",
|
+ "Headphones", "RHP",
|
+ "Speaker", "LSPK",
|
+ "Speaker", "RSPK",
|
+ "Line Out", "AUXOUT1",
|
+ "Line Out", "AUXOUT2",
|
+ "LAUX", "Line In",
|
+ "RAUX", "Line In",
|
+ "LMICP", "Mic In",
|
+ "RMICP", "Mic In";
|
+ dailink_master: simple-audio-card,codec {/* 确定codec-dai */
|
+ sound-dai = <&codec>;
|
+ clocks = <&audio_blk_ctrl IMX8MP_CLK_AUDIO_BLK_CTRL_SAI3_MCLK1>; /*mclk 时钟*/
|
+ };
|
+
|
+ simple-audio-card,cpu {/* 确定cpu-dai */
|
+ sound-dai = <&sai3>; /*cpu dai*/
|
+ };
|
+ };
|
+#endif
|
+
|
+ // sound-xcvr { //音频收发器
|
+ // compatible = "fsl,imx-audio-card";
|
+ // model = "imx-audio-xcvr";
|
+ // pri-dai-link {
|
+ // link-name = "XCVR PCM";
|
+ // cpu {
|
+ // sound-dai = <&xcvr>;
|
+ // };
|
+ // };
|
+ // };
|
+
|
+ /*+---------------+
|
+ | Lvds Panel |
|
+ +--------------+*/
|
+ lvds0_panel {
|
+ compatible = "auo,g101ean02";
|
+ backlight = <&lvds_backlight>;
|
+ status = "okay";
|
+
|
+ port {
|
+ panel_lvds_in: endpoint {
|
+ remote-endpoint = <&lvds_out>;
|
+ };
|
+ };
|
+ };
|
+
|
+ lvds_backlight: lvds_backlight {
|
+ compatible = "pwm-backlight";
|
+ pwms = <&pwm2 0 100000>;
|
+ pinctrl-names = "default";
|
+ pinctrl-0 = <&pinctrl_backlight>;
|
+ enable-gpios = <&gpio5 6 GPIO_ACTIVE_LOW>;
|
+ status = "okay";
|
+
|
+ brightness-levels = < 0 1 2 3 4 5 6 7 8 9
|
+ 10 11 12 13 14 15 16 17 18 19
|
+ 20 21 22 23 24 25 26 27 28 29
|
+ 30 31 32 33 34 35 36 37 38 39
|
+ 40 41 42 43 44 45 46 47 48 49
|
+ 50 51 52 53 54 55 56 57 58 59
|
+ 60 61 62 63 64 65 66 67 68 69
|
+ 70 71 72 73 74 75 76 77 78 79
|
+ 80 81 82 83 84 85 86 87 88 89
|
+ 90 91 92 93 94 95 96 97 98 99
|
+ 100 >;
|
+ default-brightness-level = <20>;
|
+ };
|
+
|
+ /*+---------------+
|
+ | Extcon gpio |
|
+ +--------------+*/
|
+ extcon_dwc3: extcon_dwc3 {
|
+ compatible = "linux,extcon-usb-gpio";
|
+ pinctrl-names = "default";
|
+ pinctrl-0 = <&pinctrl_usb0_id_grp>;
|
+ id-gpio = <&gpio4 26 GPIO_ACTIVE_HIGH>;
|
+ };
|
+};
|
+
|
+/*+--------------+
|
+ | Misc Modules |
|
+ +--------------+*/
|
+&snvs_pwrkey {
|
+ status = "okay";
|
+};
|
+
|
+&sdma2 {
|
+ status = "okay";
|
+};
|
+
|
+&pwm2 {
|
+ pinctrl-names = "default";
|
+ pinctrl-0 = <&pinctrl_pwm2>;
|
+ status = "okay";
|
+};
|
+
|
+&A53_0 {
|
+ cpu-supply = <&buck2>;
|
+};
|
+
|
+&A53_1 {
|
+ cpu-supply = <&buck2>;
|
+};
|
+
|
+&A53_2 {
|
+ cpu-supply = <&buck2>;
|
+};
|
+
|
+&A53_3 {
|
+ cpu-supply = <&buck2>;
|
+};
|
+
|
+&wdog1 {
|
+ pinctrl-names = "default";
|
+ pinctrl-0 = <&pinctrl_wdog>;
|
+ fsl,ext-reset-output;
|
+ status = "okay";
|
+};
|
+
|
+/*+------------------------+
|
+ | Uart and can interface |
|
+ +------------------------+*/
|
+&uart1 {
|
+ /* RS485 */
|
+ pinctrl-names = "default";
|
+ pinctrl-0 = <&pinctrl_uart1>;
|
+ status = "okay";
|
+};
|
+
|
+&uart2 {
|
+ /* console */
|
+ pinctrl-names = "default";
|
+ pinctrl-0 = <&pinctrl_uart2>;
|
+ status = "okay";
|
+};
|
+
|
+&flexcan1 {
|
+ pinctrl-names = "default";
|
+ pinctrl-0 = <&pinctrl_flexcan1>;
|
+ status = "okay";
|
+};
|
+
|
+/*+--------------+
|
+ | Lvds Modules |
|
+ +--------------+*/
|
+&lcdif2 {
|
+ status = "okay";
|
+};
|
+
|
+&ldb {
|
+ status = "okay";
|
+
|
+ lvds-channel@0 {
|
+ fsl,data-mapping = "spwg";
|
+ fsl,data-width = <24>;
|
+ status = "okay";
|
+
|
+ port@1 {
|
+ reg = <1>;
|
+
|
+ lvds_out: endpoint {
|
+ remote-endpoint = <&panel_lvds_in>;
|
+ };
|
+ };
|
+ };
|
+};
|
+
|
+&ldb_phy {
|
+ status = "okay";
|
+};
|
+
|
+/*+--------------+
|
+ | Spi Modules |
|
+ +--------------+*/
|
+&flexspi {
|
+ pinctrl-names = "default";
|
+ pinctrl-0 = <&pinctrl_flexspi0>;
|
+ status = "okay";
|
+
|
+ flash0: mt25qu256aba@0 {
|
+ reg = <0>;
|
+ #address-cells = <1>;
|
+ #size-cells = <1>;
|
+ compatible = "jedec,spi-nor";
|
+ spi-max-frequency = <80000000>;
|
+ spi-tx-bus-width = <1>;
|
+ spi-rx-bus-width = <4>;
|
+ };
|
+};
|
+
|
+/*+------------------+
|
+ | Ethernet Modules |
|
+ +------------------+*/
|
+&eqos { //T1 eth1
|
+ pinctrl-names = "default";
|
+ pinctrl-0 = <&pinctrl_eqos>;
|
+ phy-mode = "rgmii-id";
|
+ phy-handle = <ðphy1>;
|
+ // snps,force_thresh_dma_mode;
|
+ // snps,mtl-tx-config = <&mtl_tx_setup>; /*TODO: dma相关*/
|
+ // snps,mtl-rx-config = <&mtl_rx_setup>;
|
+ status = "okay";
|
+
|
+ mdio {
|
+ compatible = "snps,dwmac-mdio";
|
+ #address-cells = <1>;
|
+ #size-cells = <0>;
|
+
|
+ ethphy1: ethernet-phy@1 {
|
+ compatible = "ethernet-phy-ieee802.3-c22";
|
+ reg = <1>;
|
+ eee-broken-1000t;
|
+ realtek,clkout-disable;
|
+ };
|
+ };
|
+};
|
+
|
+&fec {//T2 eth0
|
+ pinctrl-names = "default";
|
+ pinctrl-0 = <&pinctrl_fec>;
|
+ phy-mode = "rgmii-id";
|
+ phy-handle = <ðphy2>;
|
+ fsl,magic-packet;
|
+ status = "okay";
|
+
|
+ mdio {
|
+ #address-cells = <1>;
|
+ #size-cells = <0>;
|
+
|
+ ethphy2: ethernet-phy@2 {
|
+ compatible = "ethernet-phy-ieee802.3-c22";
|
+ reg = <2>;
|
+ eee-broken-1000t;
|
+ reset-gpios = <&gpio4 2 GPIO_ACTIVE_LOW>;
|
+ reset-assert-us = <10000>;
|
+ reset-deassert-us = <80000>;
|
+ realtek,clkout-disable;
|
+ };
|
+ };
|
+};
|
+
|
+/*+---------------+
|
+ | I2C Module |
|
+ +---------------+*/
|
+&i2c1 {
|
+ clock-frequency = <400000>;
|
+ pinctrl-names = "default";
|
+ pinctrl-0 = <&pinctrl_i2c1>;
|
+ status = "okay";
|
+
|
+ pmic@25 {
|
+ compatible = "nxp,pca9450c";
|
+ reg = <0x25>;
|
+ pinctrl-names = "default";
|
+ pinctrl-0 = <&pinctrl_pmic>;
|
+ interrupt-parent = <&gpio1>;
|
+ interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
|
+
|
+ regulators {
|
+ buck1: BUCK1 {
|
+ regulator-name = "BUCK1";
|
+ regulator-min-microvolt = <600000>;
|
+ regulator-max-microvolt = <2187500>;
|
+ regulator-boot-on;
|
+ regulator-always-on;
|
+ regulator-ramp-delay = <3125>;
|
+ };
|
+
|
+ buck2: BUCK2 {
|
+ regulator-name = "BUCK2";
|
+ regulator-min-microvolt = <600000>;
|
+ regulator-max-microvolt = <2187500>;
|
+ regulator-boot-on;
|
+ regulator-always-on;
|
+ regulator-ramp-delay = <3125>;
|
+ nxp,dvs-run-voltage = <950000>;
|
+ nxp,dvs-standby-voltage = <850000>;
|
+ };
|
+
|
+ buck4: BUCK4{
|
+ regulator-name = "BUCK4";
|
+ regulator-min-microvolt = <600000>;
|
+ regulator-max-microvolt = <3400000>;
|
+ regulator-boot-on;
|
+ regulator-always-on;
|
+ };
|
+
|
+ buck5: BUCK5{
|
+ regulator-name = "BUCK5";
|
+ regulator-min-microvolt = <600000>;
|
+ regulator-max-microvolt = <3400000>;
|
+ regulator-boot-on;
|
+ regulator-always-on;
|
+ };
|
+
|
+ buck6: BUCK6 {
|
+ regulator-name = "BUCK6";
|
+ regulator-min-microvolt = <600000>;
|
+ regulator-max-microvolt = <3400000>;
|
+ regulator-boot-on;
|
+ regulator-always-on;
|
+ };
|
+
|
+ ldo1: LDO1 {
|
+ regulator-name = "LDO1";
|
+ regulator-min-microvolt = <1600000>;
|
+ regulator-max-microvolt = <3300000>;
|
+ regulator-boot-on;
|
+ regulator-always-on;
|
+ };
|
+
|
+ ldo2: LDO2 {
|
+ regulator-name = "LDO2";
|
+ regulator-min-microvolt = <800000>;
|
+ regulator-max-microvolt = <1150000>;
|
+ regulator-boot-on;
|
+ regulator-always-on;
|
+ };
|
+
|
+ ldo3: LDO3 {
|
+ regulator-name = "LDO3";
|
+ regulator-min-microvolt = <800000>;
|
+ regulator-max-microvolt = <3300000>;
|
+ regulator-boot-on;
|
+ regulator-always-on;
|
+ };
|
+
|
+ ldo4: LDO4 {
|
+ regulator-name = "LDO4";
|
+ regulator-min-microvolt = <800000>;
|
+ regulator-max-microvolt = <3300000>;
|
+ regulator-boot-on;
|
+ regulator-always-on;
|
+ };
|
+
|
+ ldo5: LDO5 {
|
+ regulator-name = "LDO5";
|
+ regulator-min-microvolt = <1800000>;
|
+ regulator-max-microvolt = <3300000>;
|
+ regulator-boot-on;
|
+ regulator-always-on;
|
+ };
|
+ };
|
+ };
|
+};
|
+
|
+&i2c2 {
|
+ clock-frequency = <100000>;
|
+ pinctrl-names = "default";
|
+ pinctrl-0 = <&pinctrl_i2c2>;
|
+ status = "okay";
|
+
|
+ gt9xx@5d {
|
+ compatible = "goodix,gt928";
|
+ reg = <0x5d>;
|
+ pinctrl-names = "default";
|
+ pinctrl-0 = <&pinctrl_ts_pins>;
|
+
|
+ reset-gpios = <&gpio5 8 GPIO_ACTIVE_HIGH>;
|
+ irq-gpios = <&gpio5 9 GPIO_ACTIVE_HIGH>;
|
+ interrupt-parent = <&gpio5>;
|
+ interrupts = <9 IRQ_TYPE_EDGE_FALLING>;
|
+
|
+ status = "okay"; /* Enable in LCD overlay */
|
+ };
|
+};
|
+
|
+&i2c3 {
|
+ clock-frequency = <400000>;
|
+ pinctrl-names = "default";
|
+ pinctrl-0 = <&pinctrl_i2c3>;
|
+ status = "okay";
|
+#ifndef SIMPLE_CARD
|
+ codec: nau8822@1a {
|
+ compatible = "nuvoton,nau8822";
|
+ reg = <0x1a>;
|
+ clocks = <&audio_blk_ctrl IMX8MP_CLK_AUDIO_BLK_CTRL_SAI3_MCLK1>; /*mclk时钟*/
|
+ clock-names = "mclk";
|
+ };
|
+#else
|
+ codec: nau8822@1a {
|
+ compatible = "nuvoton,nau8822";
|
+ reg = <0x1a>;
|
+ #sound-dai-cells = <0>;
|
+ };
|
+#endif
|
+};
|
+
|
+/*+--------------+
|
+ | Audio Module |
|
+ +--------------+*/
|
+&dsp {
|
+ status = "okay";
|
+};
|
+
|
+&aud2htx {
|
+ status = "okay";
|
+};
|
+
|
+&easrc {
|
+ fsl,asrc-rate = <48000>;
|
+ status = "okay";
|
+};
|
+#ifndef SIMPLE_CARD
|
+&sai3 {
|
+ #sound-dai-cells = <0>;
|
+ pinctrl-names = "default";
|
+ pinctrl-0 = <&pinctrl_sai3>;
|
+ assigned-clocks = <&clk IMX8MP_CLK_SAI3>;
|
+ assigned-clock-parents = <&clk IMX8MP_AUDIO_PLL1_OUT>;
|
+ assigned-clock-rates = <12288000>;
|
+ fsl,sai-mclk-direction-output;
|
+ status = "okay";
|
+};
|
+#else
|
+&sai3 {
|
+ #sound-dai-cells = <0>;
|
+ pinctrl-names = "default";
|
+ pinctrl-0 = <&pinctrl_sai3>;
|
+ assigned-clocks = <&clk IMX8MP_CLK_SAI3>;
|
+ assigned-clock-parents = <&clk IMX8MP_AUDIO_PLL1_OUT>;
|
+ // assigned-clock-rates = <24576000>;
|
+ assigned-clock-rates = <12288000>; /*48000*256 是 44100 * 2 * 16 的 2^n 倍数*/
|
+ fsl,sai-mclk-direction-output;
|
+ status = "okay";
|
+};
|
+#endif
|
+
|
+// &xcvr {
|
+// #sound-dai-cells = <0>;
|
+// status = "okay";
|
+// };
|
+
|
+/*+---------------+
|
+ | USB interface |
|
+ +---------------+*/
|
+//USB1
|
+&usb3_phy0 {
|
+ fsl,phy-tx-vref-tune = <0xe>;
|
+ fsl,phy-tx-preemp-amp-tune = <3>;
|
+ fsl,phy-tx-vboost-level = <5>;
|
+ fsl,phy-comp-dis-tune = <7>;
|
+ fsl,pcs-tx-deemph-3p5db = <0x21>;
|
+ fsl,phy-pcs-tx-swing-full = <0x7f>;
|
+ status = "okay";
|
+};
|
+
|
+&usb3_0 {
|
+ status = "okay";
|
+};
|
+
|
+#if 0
|
+&usb_dwc3_0 {
|
+ dr_mode = "host";//应该otg,TODO:otg id未解决
|
+ hnp-disable;
|
+ srp-disable;
|
+ adp-disable;
|
+ snps,usb2-lpm-disable;
|
+ // usb-role-switch;
|
+ // role-switch-default-mode = "none";
|
+ // snps,dis-u1-entry-quirk;
|
+ // snps,dis-u2-entry-quirk;
|
+ pinctrl-names = "default";
|
+ pinctrl-0 = <&pinctrl_usb0_id_grp>;
|
+ // interrupts = <&gpio4 26 IRQ_TYPE_EDGE_BOTH>,
|
+ // <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;// interrupt 需增加修改
|
+ // interrupt-names = "otg","";
|
+ power-polarity-active-high;//
|
+ disable-over-current;//
|
+ status = "okay";
|
+};
|
+#else
|
+&usb_dwc3_0 {
|
+ dr_mode = "otg";
|
+ hnp-disable;
|
+ srp-disable;
|
+ adp-disable;
|
+ status = "okay";
|
+ extcon = <&extcon_dwc3>;
|
+};
|
+#endif
|
+
|
+/* USB2 for 4G or 5G module*/
|
+&usb3_phy1 {
|
+ fsl,phy-tx-preemp-amp-tune = <3>;
|
+ fsl,phy-tx-vref-tune = <0xb>;
|
+ status = "okay";
|
+};
|
+
|
+&usb3_1 {
|
+ status = "okay";
|
+};
|
+
|
+&usb_dwc3_1 {
|
+ dr_mode = "host";
|
+ status = "okay";
|
+};
|
+
|
+/*+------------------+
|
+ | USDCHC interface |
|
+ +------------------+*/
|
+&usdhc3 {
|
+ assigned-clocks = <&clk IMX8MP_CLK_USDHC3>;
|
+ assigned-clock-rates = <400000000>;
|
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
|
+ pinctrl-0 = <&pinctrl_usdhc3>;
|
+ pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
|
+ pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
|
+ bus-width = <8>;
|
+ non-removable;
|
+ status = "okay";
|
+};
|
+
|
+/*+----------------------+
|
+ | Basic pinctrl iomuxc |
|
+ +----------------------+*/
|
+&iomuxc {
|
+ pinctrl-names = "default";
|
+
|
+ pinctrl_backlight: backlightgrp {
|
+ fsl,pins = <
|
+ MX8MP_IOMUXC_ECSPI1_SCLK__GPIO5_IO06 0x19
|
+ >;
|
+ };
|
+
|
+ pinctrl_ts_pins: tsgrp {
|
+ fsl,pins = <
|
+ MX8MP_IOMUXC_ECSPI1_MISO__GPIO5_IO08 0x17059 /* TouchScreen RST */
|
+ MX8MP_IOMUXC_ECSPI1_SS0__GPIO5_IO09 0x17059 /* TouchScreen IRQ */
|
+ >;
|
+ };
|
+
|
+ pinctrl_pwm2: pwm2grp {
|
+ fsl,pins = <
|
+ MX8MP_IOMUXC_GPIO1_IO11__PWM2_OUT 0x116
|
+ >;
|
+ };
|
+
|
+ pinctrl_eqos: eqosgrp { //T1 TODO: 和evk不一致
|
+ fsl,pins = <
|
+ MX8MP_IOMUXC_ENET_MDC__ENET_QOS_MDC 0x3
|
+ MX8MP_IOMUXC_ENET_MDIO__ENET_QOS_MDIO 0x3
|
+ MX8MP_IOMUXC_ENET_RD0__ENET_QOS_RGMII_RD0 0x91
|
+ MX8MP_IOMUXC_ENET_RD1__ENET_QOS_RGMII_RD1 0x91
|
+ MX8MP_IOMUXC_ENET_RD2__ENET_QOS_RGMII_RD2 0x91
|
+ MX8MP_IOMUXC_ENET_RD3__ENET_QOS_RGMII_RD3 0x91
|
+ MX8MP_IOMUXC_ENET_RXC__CCM_ENET_QOS_CLOCK_GENERATE_RX_CLK 0x91
|
+ MX8MP_IOMUXC_ENET_RX_CTL__ENET_QOS_RGMII_RX_CTL 0x91
|
+ MX8MP_IOMUXC_ENET_TD0__ENET_QOS_RGMII_TD0 0x1f
|
+ MX8MP_IOMUXC_ENET_TD1__ENET_QOS_RGMII_TD1 0x1f
|
+ MX8MP_IOMUXC_ENET_TD2__ENET_QOS_RGMII_TD2 0x1f
|
+ MX8MP_IOMUXC_ENET_TD3__ENET_QOS_RGMII_TD3 0x1f
|
+ MX8MP_IOMUXC_ENET_TX_CTL__ENET_QOS_RGMII_TX_CTL 0x1f
|
+ MX8MP_IOMUXC_ENET_TXC__CCM_ENET_QOS_CLOCK_GENERATE_TX_CLK 0x1f
|
+ MX8MP_IOMUXC_SAI2_RXC__GPIO4_IO22 0x19
|
+ >;
|
+ };
|
+
|
+ pinctrl_fec: fecgrp {
|
+ fsl,pins = <
|
+ MX8MP_IOMUXC_SAI1_RXD2__ENET1_MDC 0x3
|
+ MX8MP_IOMUXC_SAI1_RXD3__ENET1_MDIO 0x3
|
+ MX8MP_IOMUXC_SAI1_RXD4__ENET1_RGMII_RD0 0x91
|
+ MX8MP_IOMUXC_SAI1_RXD5__ENET1_RGMII_RD1 0x91
|
+ MX8MP_IOMUXC_SAI1_RXD6__ENET1_RGMII_RD2 0x91
|
+ MX8MP_IOMUXC_SAI1_RXD7__ENET1_RGMII_RD3 0x91
|
+ MX8MP_IOMUXC_SAI1_TXC__ENET1_RGMII_RXC 0x91
|
+ MX8MP_IOMUXC_SAI1_TXFS__ENET1_RGMII_RX_CTL 0x91
|
+ MX8MP_IOMUXC_SAI1_TXD0__ENET1_RGMII_TD0 0x1f
|
+ MX8MP_IOMUXC_SAI1_TXD1__ENET1_RGMII_TD1 0x1f
|
+ MX8MP_IOMUXC_SAI1_TXD2__ENET1_RGMII_TD2 0x1f
|
+ MX8MP_IOMUXC_SAI1_TXD3__ENET1_RGMII_TD3 0x1f
|
+ MX8MP_IOMUXC_SAI1_TXD4__ENET1_RGMII_TX_CTL 0x1f
|
+ MX8MP_IOMUXC_SAI1_TXD5__ENET1_RGMII_TXC 0x1f
|
+ MX8MP_IOMUXC_SAI1_RXD0__GPIO4_IO02 0x19
|
+ >;
|
+ };
|
+
|
+ pinctrl_flexspi0: flexspi0grp {
|
+ fsl,pins = <
|
+ MX8MP_IOMUXC_NAND_ALE__FLEXSPI_A_SCLK 0x1c2
|
+ MX8MP_IOMUXC_NAND_CE0_B__FLEXSPI_A_SS0_B 0x82
|
+ MX8MP_IOMUXC_NAND_DATA00__FLEXSPI_A_DATA00 0x82
|
+ MX8MP_IOMUXC_NAND_DATA01__FLEXSPI_A_DATA01 0x82
|
+ MX8MP_IOMUXC_NAND_DATA02__FLEXSPI_A_DATA02 0x82
|
+ MX8MP_IOMUXC_NAND_DATA03__FLEXSPI_A_DATA03 0x82
|
+ >;
|
+ };
|
+
|
+ pinctrl_flexcan1: flexcan1grp {
|
+ fsl,pins = <
|
+ MX8MP_IOMUXC_SPDIF_RX__CAN1_RX 0x154
|
+ MX8MP_IOMUXC_SPDIF_TX__CAN1_TX 0x154
|
+ >;
|
+ };
|
+
|
+ pinctrl_gpio_leds_group: gpioledsgrp {
|
+ fsl,pins = <
|
+ MX8MP_IOMUXC_NAND_READY_B__GPIO3_IO16 0x140
|
+ MX8MP_IOMUXC_SD1_STROBE__GPIO2_IO11 0x140
|
+ MX8MP_IOMUXC_SD1_RESET_B__GPIO2_IO10 0x140
|
+ MX8MP_IOMUXC_SD2_DATA2__GPIO2_IO17 0x140
|
+ MX8MP_IOMUXC_SAI5_MCLK__GPIO3_IO25 0x140
|
+ MX8MP_IOMUXC_SAI5_RXFS__GPIO3_IO19 0x140
|
+ >;
|
+ };
|
+
|
+ pinctrl_gpio_devs_group: gpiodevsgrp {
|
+ fsl,pins = <
|
+ MX8MP_IOMUXC_SAI2_MCLK__GPIO4_IO27 0x140
|
+ MX8MP_IOMUXC_SAI2_TXC__GPIO4_IO25 0x154
|
+ MX8MP_IOMUXC_SD2_DATA1__GPIO2_IO16 0x140
|
+ MX8MP_IOMUXC_SD1_CMD__GPIO2_IO01 0x154
|
+ >;
|
+ };
|
+
|
+ pinctrl_wwan_reg: wwanprowergrp {
|
+ fsl,pins = <
|
+ MX8MP_IOMUXC_ECSPI2_SCLK__GPIO5_IO10 0x140
|
+ >;
|
+ };
|
+
|
+ pinctrl_usb_host_reg: usbvbusgrp {
|
+ fsl,pins = <
|
+ MX8MP_IOMUXC_ECSPI2_MISO__GPIO5_IO12 0x140
|
+ >;
|
+ };
|
+
|
+ pinctrl_i2c1: i2c1grp {
|
+ fsl,pins = <
|
+ MX8MP_IOMUXC_I2C1_SCL__I2C1_SCL 0x400001c2
|
+ MX8MP_IOMUXC_I2C1_SDA__I2C1_SDA 0x400001c2
|
+ >;
|
+ };
|
+
|
+ pinctrl_i2c2: i2c2grp {
|
+ fsl,pins = <
|
+ MX8MP_IOMUXC_I2C2_SCL__I2C2_SCL 0x400001c2
|
+ MX8MP_IOMUXC_I2C2_SDA__I2C2_SDA 0x400001c2
|
+ >;
|
+ };
|
+
|
+ pinctrl_i2c3: i2c3grp {
|
+ fsl,pins = <
|
+ MX8MP_IOMUXC_I2C3_SCL__I2C3_SCL 0x400001c2
|
+ MX8MP_IOMUXC_I2C3_SDA__I2C3_SDA 0x400001c2
|
+ >;
|
+ };
|
+
|
+ pinctrl_pmic: pmicgrp {
|
+ fsl,pins = <
|
+ MX8MP_IOMUXC_GPIO1_IO03__GPIO1_IO03 0x000001c0
|
+ >;
|
+ };
|
+
|
+ pinctrl_sai3: sai3grp {
|
+ fsl,pins = <
|
+ MX8MP_IOMUXC_SAI3_TXFS__AUDIOMIX_SAI3_TX_SYNC 0xd6
|
+ MX8MP_IOMUXC_SAI3_TXC__AUDIOMIX_SAI3_TX_BCLK 0xd6
|
+ MX8MP_IOMUXC_SAI3_RXD__AUDIOMIX_SAI3_RX_DATA00 0xd6
|
+ MX8MP_IOMUXC_SAI3_TXD__AUDIOMIX_SAI3_TX_DATA00 0xd6
|
+ MX8MP_IOMUXC_SAI3_MCLK__AUDIOMIX_SAI3_MCLK 0xd6
|
+ MX8MP_IOMUXC_SAI3_RXFS__GPIO4_IO28 0xd6
|
+ MX8MP_IOMUXC_SAI3_RXC__GPIO4_IO29 0xd6
|
+ >;
|
+ };
|
+
|
+ pinctrl_uart2: uart2grp {
|
+ fsl,pins = <
|
+ MX8MP_IOMUXC_UART2_RXD__UART2_DCE_RX 0x140
|
+ MX8MP_IOMUXC_UART2_TXD__UART2_DCE_TX 0x140
|
+ >;
|
+ };
|
+
|
+ pinctrl_uart1: uart1grp {
|
+ fsl,pins = <
|
+ MX8MP_IOMUXC_UART1_RXD__UART1_DCE_RX 0x140
|
+ MX8MP_IOMUXC_UART1_TXD__UART1_DCE_TX 0x140
|
+ >;
|
+ };
|
+
|
+ pinctrl_usb0_id_grp: usb0grp{
|
+ fsl,pins = <
|
+ MX8MP_IOMUXC_SAI2_TXD0__GPIO4_IO26 0x19
|
+ >;
|
+ };
|
+
|
+ pinctrl_usdhc3: usdhc3grp {
|
+ fsl,pins = <
|
+ MX8MP_IOMUXC_NAND_WE_B__USDHC3_CLK 0x190
|
+ MX8MP_IOMUXC_NAND_WP_B__USDHC3_CMD 0x1d0
|
+ MX8MP_IOMUXC_NAND_DATA04__USDHC3_DATA0 0x1d0
|
+ MX8MP_IOMUXC_NAND_DATA05__USDHC3_DATA1 0x1d0
|
+ MX8MP_IOMUXC_NAND_DATA06__USDHC3_DATA2 0x1d0
|
+ MX8MP_IOMUXC_NAND_DATA07__USDHC3_DATA3 0x1d0
|
+ MX8MP_IOMUXC_NAND_RE_B__USDHC3_DATA4 0x1d0
|
+ MX8MP_IOMUXC_NAND_CE2_B__USDHC3_DATA5 0x1d0
|
+ MX8MP_IOMUXC_NAND_CE3_B__USDHC3_DATA6 0x1d0
|
+ MX8MP_IOMUXC_NAND_CLE__USDHC3_DATA7 0x1d0
|
+ MX8MP_IOMUXC_NAND_CE1_B__USDHC3_STROBE 0x190
|
+ >;
|
+ };
|
+
|
+ pinctrl_usdhc3_100mhz: usdhc3-100mhzgrp {
|
+ fsl,pins = <
|
+ MX8MP_IOMUXC_NAND_WE_B__USDHC3_CLK 0x194
|
+ MX8MP_IOMUXC_NAND_WP_B__USDHC3_CMD 0x1d4
|
+ MX8MP_IOMUXC_NAND_DATA04__USDHC3_DATA0 0x1d4
|
+ MX8MP_IOMUXC_NAND_DATA05__USDHC3_DATA1 0x1d4
|
+ MX8MP_IOMUXC_NAND_DATA06__USDHC3_DATA2 0x1d4
|
+ MX8MP_IOMUXC_NAND_DATA07__USDHC3_DATA3 0x1d4
|
+ MX8MP_IOMUXC_NAND_RE_B__USDHC3_DATA4 0x1d4
|
+ MX8MP_IOMUXC_NAND_CE2_B__USDHC3_DATA5 0x1d4
|
+ MX8MP_IOMUXC_NAND_CE3_B__USDHC3_DATA6 0x1d4
|
+ MX8MP_IOMUXC_NAND_CLE__USDHC3_DATA7 0x1d4
|
+ MX8MP_IOMUXC_NAND_CE1_B__USDHC3_STROBE 0x194
|
+ >;
|
+ };
|
+
|
+ pinctrl_usdhc3_200mhz: usdhc3-200mhzgrp {
|
+ fsl,pins = <
|
+ MX8MP_IOMUXC_NAND_WE_B__USDHC3_CLK 0x196
|
+ MX8MP_IOMUXC_NAND_WP_B__USDHC3_CMD 0x1d6
|
+ MX8MP_IOMUXC_NAND_DATA04__USDHC3_DATA0 0x1d6
|
+ MX8MP_IOMUXC_NAND_DATA05__USDHC3_DATA1 0x1d6
|
+ MX8MP_IOMUXC_NAND_DATA06__USDHC3_DATA2 0x1d6
|
+ MX8MP_IOMUXC_NAND_DATA07__USDHC3_DATA3 0x1d6
|
+ MX8MP_IOMUXC_NAND_RE_B__USDHC3_DATA4 0x1d6
|
+ MX8MP_IOMUXC_NAND_CE2_B__USDHC3_DATA5 0x1d6
|
+ MX8MP_IOMUXC_NAND_CE3_B__USDHC3_DATA6 0x1d6
|
+ MX8MP_IOMUXC_NAND_CLE__USDHC3_DATA7 0x1d6
|
+ MX8MP_IOMUXC_NAND_CE1_B__USDHC3_STROBE 0x196
|
+ >;
|
+ };
|
+
|
+ pinctrl_wdog: wdoggrp {
|
+ fsl,pins = <
|
+ MX8MP_IOMUXC_GPIO1_IO02__WDOG1_WDOG_B 0x166
|
+ >;
|
+ };
|
+};
|
+
|
+/*+---------------+
|
+ | Other Modules |
|
+ +---------------+*/
|
+&vpu_g1 {
|
+ status = "okay";
|
+};
|
+
|
+&vpu_g2 {
|
+ status = "okay";
|
+};
|
+
|
+&vpu_vc8000e {
|
+ status = "okay";
|
+};
|
+
|
+&vpu_v4l2 {
|
+ status = "okay";
|
+};
|
+
|
+&gpu_3d {
|
+ status = "okay";
|
+};
|
+
|
+&gpu_2d {
|
+ status = "okay";
|
+};
|
+
|
+&ml_vipsi {
|
+ status = "okay";
|
+};
|
+
|
+&mix_gpu_ml {
|
+ status = "okay";
|
+};
|
+
|
+&cameradev {
|
+ status = "okay";
|
+};
|
+
|
+&isi_0 {
|
+ status = "okay";
|
+
|
+ cap_device {
|
+ status = "okay";
|
+ };
|
+
|
+ m2m_device {
|
+ status = "okay";
|
+ };
|
+};
|
+
|
+&isi_1 {
|
+ status = "disabled";
|
+
|
+ cap_device {
|
+ status = "okay";
|
+ };
|
+};
|
diff --git a/arch/arm64/configs/gauguin-imx8mp_defconfig b/arch/arm64/configs/gauguin-imx8mp_defconfig
|
new file mode 100644
|
index 000000000..d5f67800e
|
--- /dev/null
|
+++ b/arch/arm64/configs/gauguin-imx8mp_defconfig
|
@@ -0,0 +1,1034 @@
|
+CONFIG_SYSVIPC=y
|
+CONFIG_POSIX_MQUEUE=y
|
+CONFIG_AUDIT=y
|
+CONFIG_NO_HZ_IDLE=y
|
+CONFIG_HIGH_RES_TIMERS=y
|
+CONFIG_BPF_JIT=y
|
+CONFIG_PREEMPT=y
|
+CONFIG_IRQ_TIME_ACCOUNTING=y
|
+CONFIG_BSD_PROCESS_ACCT=y
|
+CONFIG_BSD_PROCESS_ACCT_V3=y
|
+CONFIG_IKCONFIG=y
|
+CONFIG_IKCONFIG_PROC=y
|
+CONFIG_NUMA_BALANCING=y
|
+CONFIG_MEMCG=y
|
+CONFIG_BLK_CGROUP=y
|
+CONFIG_CGROUP_PIDS=y
|
+CONFIG_CGROUP_FREEZER=y
|
+CONFIG_CGROUP_HUGETLB=y
|
+CONFIG_CPUSETS=y
|
+CONFIG_CGROUP_DEVICE=y
|
+CONFIG_CGROUP_CPUACCT=y
|
+CONFIG_CGROUP_PERF=y
|
+CONFIG_NAMESPACES=y
|
+CONFIG_USER_NS=y
|
+CONFIG_SCHED_AUTOGROUP=y
|
+CONFIG_SYSFS_DEPRECATED=y
|
+CONFIG_SYSFS_DEPRECATED_V2=y
|
+CONFIG_RELAY=y
|
+CONFIG_BLK_DEV_INITRD=y
|
+CONFIG_KALLSYMS_ALL=y
|
+CONFIG_EMBEDDED=y
|
+# CONFIG_COMPAT_BRK is not set
|
+CONFIG_PROFILING=y
|
+CONFIG_ARCH_LAYERSCAPE=y
|
+CONFIG_ARCH_KEEMBAY=y
|
+CONFIG_ARCH_MXC=y
|
+CONFIG_ARCH_S32=y
|
+CONFIG_SOC_S32V234=y
|
+CONFIG_ARM64_VA_BITS_48=y
|
+CONFIG_SCHED_MC=y
|
+CONFIG_SCHED_SMT=y
|
+CONFIG_NUMA=y
|
+CONFIG_KEXEC=y
|
+CONFIG_KEXEC_FILE=y
|
+CONFIG_CRASH_DUMP=y
|
+CONFIG_XEN=y
|
+CONFIG_FORCE_MAX_ZONEORDER=14
|
+CONFIG_COMPAT=y
|
+CONFIG_RANDOMIZE_BASE=y
|
+CONFIG_PM_DEBUG=y
|
+CONFIG_PM_TEST_SUSPEND=y
|
+CONFIG_WQ_POWER_EFFICIENT_DEFAULT=y
|
+CONFIG_ENERGY_MODEL=y
|
+CONFIG_ARM_CPUIDLE=y
|
+CONFIG_ARM_PSCI_CPUIDLE=y
|
+CONFIG_CPU_FREQ=y
|
+CONFIG_CPU_FREQ_STAT=y
|
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
|
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
|
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
|
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
|
+CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
|
+CONFIG_CPUFREQ_DT=y
|
+CONFIG_ACPI_CPPC_CPUFREQ=m
|
+CONFIG_ARM_SCPI_CPUFREQ=y
|
+CONFIG_ARM_IMX_CPUFREQ_DT=y
|
+CONFIG_ARM_SCMI_CPUFREQ=y
|
+CONFIG_QORIQ_CPUFREQ=y
|
+CONFIG_ACPI=y
|
+CONFIG_ACPI_APEI=y
|
+CONFIG_ACPI_APEI_GHES=y
|
+CONFIG_ACPI_APEI_MEMORY_FAILURE=y
|
+CONFIG_ACPI_APEI_EINJ=y
|
+CONFIG_VIRTUALIZATION=y
|
+CONFIG_KVM=y
|
+CONFIG_ARM64_CRYPTO=y
|
+CONFIG_CRYPTO_SHA1_ARM64_CE=y
|
+CONFIG_CRYPTO_SHA2_ARM64_CE=y
|
+CONFIG_CRYPTO_SHA512_ARM64_CE=m
|
+CONFIG_CRYPTO_SHA3_ARM64=m
|
+CONFIG_CRYPTO_SM3_ARM64_CE=m
|
+CONFIG_CRYPTO_GHASH_ARM64_CE=y
|
+CONFIG_CRYPTO_CRCT10DIF_ARM64_CE=m
|
+CONFIG_CRYPTO_AES_ARM64_CE_CCM=y
|
+CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
|
+CONFIG_CRYPTO_CHACHA20_NEON=m
|
+CONFIG_CRYPTO_AES_ARM64_BS=m
|
+CONFIG_JUMP_LABEL=y
|
+CONFIG_MODULES=y
|
+CONFIG_MODULE_UNLOAD=y
|
+CONFIG_MODVERSIONS=y
|
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
|
+CONFIG_KSM=y
|
+CONFIG_MEMORY_FAILURE=y
|
+CONFIG_TRANSPARENT_HUGEPAGE=y
|
+CONFIG_NET=y
|
+CONFIG_PACKET=y
|
+CONFIG_UNIX=y
|
+CONFIG_TLS=y
|
+CONFIG_TLS_DEVICE=y
|
+CONFIG_INET=y
|
+CONFIG_IP_MULTICAST=y
|
+CONFIG_IP_PNP=y
|
+CONFIG_IP_PNP_DHCP=y
|
+CONFIG_IP_PNP_BOOTP=y
|
+CONFIG_IPV6_SIT=m
|
+CONFIG_NETFILTER=y
|
+CONFIG_NF_CONNTRACK=m
|
+CONFIG_NF_CONNTRACK_EVENTS=y
|
+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
|
+CONFIG_NETFILTER_XT_TARGET_LOG=m
|
+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
|
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
|
+CONFIG_IP_NF_IPTABLES=m
|
+CONFIG_IP_NF_FILTER=m
|
+CONFIG_IP_NF_TARGET_REJECT=m
|
+CONFIG_IP_NF_NAT=m
|
+CONFIG_IP_NF_TARGET_MASQUERADE=m
|
+CONFIG_IP_NF_MANGLE=m
|
+CONFIG_IP6_NF_IPTABLES=m
|
+CONFIG_IP6_NF_FILTER=m
|
+CONFIG_IP6_NF_TARGET_REJECT=m
|
+CONFIG_IP6_NF_MANGLE=m
|
+CONFIG_IP6_NF_NAT=m
|
+CONFIG_IP6_NF_TARGET_MASQUERADE=m
|
+CONFIG_BRIDGE=y
|
+CONFIG_BRIDGE_VLAN_FILTERING=y
|
+CONFIG_NET_DSA=m
|
+CONFIG_NET_DSA_TAG_OCELOT=m
|
+CONFIG_NET_DSA_TAG_OCELOT_8021Q=m
|
+CONFIG_VLAN_8021Q_GVRP=y
|
+CONFIG_VLAN_8021Q_MVRP=y
|
+CONFIG_LLC2=y
|
+CONFIG_NET_SCHED=y
|
+CONFIG_NET_SCH_MULTIQ=m
|
+CONFIG_NET_SCH_CBS=m
|
+CONFIG_NET_SCH_ETF=m
|
+CONFIG_NET_SCH_TAPRIO=m
|
+CONFIG_NET_SCH_MQPRIO=m
|
+CONFIG_NET_SCH_INGRESS=m
|
+CONFIG_NET_CLS_BASIC=m
|
+CONFIG_NET_CLS_TCINDEX=m
|
+CONFIG_NET_CLS_FLOWER=m
|
+CONFIG_NET_CLS_ACT=y
|
+CONFIG_NET_ACT_GACT=m
|
+CONFIG_NET_ACT_MIRRED=m
|
+CONFIG_NET_ACT_GATE=m
|
+CONFIG_TSN=y
|
+CONFIG_QRTR=m
|
+CONFIG_QRTR_SMD=m
|
+CONFIG_QRTR_TUN=m
|
+CONFIG_NET_PKTGEN=m
|
+CONFIG_CAN=m
|
+CONFIG_CAN_FLEXCAN=m
|
+CONFIG_BT=y
|
+CONFIG_BT_RFCOMM=y
|
+CONFIG_BT_RFCOMM_TTY=y
|
+CONFIG_BT_BNEP=y
|
+CONFIG_BT_BNEP_MC_FILTER=y
|
+CONFIG_BT_BNEP_PROTO_FILTER=y
|
+CONFIG_BT_HIDP=y
|
+CONFIG_BT_LEDS=y
|
+# CONFIG_BT_DEBUGFS is not set
|
+CONFIG_BT_HCIBTUSB=m
|
+CONFIG_BT_HCIUART=y
|
+CONFIG_BT_HCIUART_BCSP=y
|
+CONFIG_BT_HCIUART_ATH3K=y
|
+CONFIG_BT_HCIUART_LL=y
|
+CONFIG_BT_HCIUART_3WIRE=y
|
+CONFIG_BT_HCIUART_BCM=y
|
+CONFIG_BT_HCIUART_QCA=y
|
+CONFIG_BT_HCIVHCI=y
|
+CONFIG_CFG80211=y
|
+CONFIG_NL80211_TESTMODE=y
|
+CONFIG_CFG80211_WEXT=y
|
+CONFIG_MAC80211=y
|
+CONFIG_MAC80211_LEDS=y
|
+CONFIG_NET_9P=y
|
+CONFIG_NET_9P_VIRTIO=y
|
+CONFIG_NFC=m
|
+CONFIG_NFC_NCI=m
|
+CONFIG_NFC_S3FWRN5_I2C=m
|
+CONFIG_DEVTMPFS=y
|
+CONFIG_DEVTMPFS_MOUNT=y
|
+CONFIG_FW_LOADER_USER_HELPER=y
|
+CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
|
+CONFIG_BRCMSTB_GISB_ARB=y
|
+CONFIG_VEXPRESS_CONFIG=y
|
+CONFIG_FSL_MC_UAPI_SUPPORT=y
|
+CONFIG_ARM_SCMI_PROTOCOL=y
|
+CONFIG_ARM_SCPI_PROTOCOL=y
|
+CONFIG_EFI_CAPSULE_LOADER=y
|
+CONFIG_IMX_DSP=y
|
+CONFIG_IMX_SCU=y
|
+CONFIG_IMX_SCU_PD=y
|
+CONFIG_GNSS=m
|
+CONFIG_GNSS_MTK_SERIAL=m
|
+CONFIG_MTD=y
|
+CONFIG_MTD_CMDLINE_PARTS=y
|
+CONFIG_MTD_BLOCK=y
|
+CONFIG_MTD_CFI=y
|
+CONFIG_MTD_CFI_ADV_OPTIONS=y
|
+CONFIG_MTD_CFI_INTELEXT=y
|
+CONFIG_MTD_CFI_AMDSTD=y
|
+CONFIG_MTD_CFI_STAA=y
|
+CONFIG_MTD_PHYSMAP=y
|
+CONFIG_MTD_PHYSMAP_OF=y
|
+CONFIG_MTD_DATAFLASH=y
|
+CONFIG_MTD_SST25L=y
|
+CONFIG_MTD_RAW_NAND=y
|
+CONFIG_MTD_NAND_DENALI_DT=y
|
+CONFIG_MTD_NAND_GPMI_NAND=y
|
+CONFIG_MTD_NAND_FSL_IFC=y
|
+CONFIG_MTD_SPI_NOR=y
|
+# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
|
+CONFIG_MTD_UBI=y
|
+CONFIG_BLK_DEV_LOOP=y
|
+CONFIG_BLK_DEV_NBD=m
|
+CONFIG_XEN_BLKDEV_BACKEND=m
|
+CONFIG_VIRTIO_BLK=y
|
+CONFIG_SRAM=y
|
+CONFIG_EEPROM_AT24=m
|
+CONFIG_EEPROM_AT25=m
|
+CONFIG_UACCE=m
|
+CONFIG_RAID_ATTRS=m
|
+# CONFIG_SCSI_PROC_FS is not set
|
+CONFIG_BLK_DEV_SD=y
|
+CONFIG_SCSI_SAS_ATA=y
|
+CONFIG_SCSI_HISI_SAS=y
|
+CONFIG_SCSI_UFSHCD=y
|
+CONFIG_SCSI_UFSHCD_PLATFORM=y
|
+CONFIG_ATA=y
|
+CONFIG_SATA_AHCI_PLATFORM=y
|
+CONFIG_AHCI_IMX=y
|
+CONFIG_AHCI_CEVA=y
|
+CONFIG_AHCI_XGENE=y
|
+CONFIG_AHCI_QORIQ=y
|
+CONFIG_PATA_PLATFORM=y
|
+CONFIG_PATA_OF_PLATFORM=y
|
+CONFIG_MD=y
|
+CONFIG_BLK_DEV_MD=m
|
+CONFIG_BLK_DEV_DM=m
|
+CONFIG_DM_CRYPT=m
|
+CONFIG_DM_MIRROR=m
|
+CONFIG_DM_ZERO=m
|
+CONFIG_NETDEVICES=y
|
+CONFIG_MACVLAN=m
|
+CONFIG_MACVTAP=m
|
+CONFIG_TUN=y
|
+CONFIG_VETH=m
|
+CONFIG_VIRTIO_NET=y
|
+CONFIG_AMD_XGBE=y
|
+CONFIG_BCMGENET=m
|
+CONFIG_MACB=y
|
+CONFIG_FEC=y
|
+CONFIG_FEC_UIO=y
|
+CONFIG_FSL_FMAN=y
|
+CONFIG_FSL_DPAA_ETH=y
|
+CONFIG_FSL_DPAA2_ETH=y
|
+CONFIG_FSL_DPAA2_MAC=y
|
+CONFIG_FSL_DPAA2_SWITCH=y
|
+CONFIG_FSL_ENETC_IERB=y
|
+CONFIG_HIX5HD2_GMAC=y
|
+CONFIG_HNS_DSAF=y
|
+CONFIG_HNS_ENET=y
|
+CONFIG_MVMDIO=y
|
+CONFIG_MSCC_OCELOT_SWITCH=y
|
+CONFIG_QCOM_EMAC=m
|
+CONFIG_RMNET=m
|
+CONFIG_SMC91X=y
|
+CONFIG_SMSC911X=y
|
+CONFIG_STMMAC_ETH=y
|
+CONFIG_DWMAC_GENERIC=m
|
+CONFIG_AQUANTIA_PHY=y
|
+CONFIG_BROADCOM_PHY=m
|
+CONFIG_BCM54140_PHY=m
|
+CONFIG_INPHI_PHY=y
|
+CONFIG_MARVELL_PHY=m
|
+CONFIG_MARVELL_10G_PHY=m
|
+CONFIG_MICREL_PHY=y
|
+CONFIG_MICROSEMI_PHY=y
|
+CONFIG_NXP_TJA11XX_PHY=y
|
+CONFIG_AT803X_PHY=y
|
+CONFIG_REALTEK_PHY=y
|
+CONFIG_ROCKCHIP_PHY=y
|
+CONFIG_VITESSE_PHY=y
|
+CONFIG_MDIO_BITBANG=y
|
+CONFIG_MDIO_BUS_MUX_MULTIPLEXER=y
|
+CONFIG_MDIO_BUS_MUX_MMIOREG=y
|
+CONFIG_PPP=y
|
+CONFIG_PPP_BSDCOMP=y
|
+CONFIG_PPP_DEFLATE=y
|
+CONFIG_PPP_FILTER=y
|
+CONFIG_PPP_MPPE=y
|
+CONFIG_PPP_MULTILINK=y
|
+CONFIG_PPPOE=y
|
+CONFIG_PPP_ASYNC=y
|
+CONFIG_PPP_SYNC_TTY=y
|
+CONFIG_SLIP=y
|
+CONFIG_USB_PEGASUS=m
|
+CONFIG_USB_RTL8150=m
|
+CONFIG_USB_RTL8152=y
|
+CONFIG_USB_LAN78XX=m
|
+CONFIG_USB_USBNET=y
|
+CONFIG_USB_NET_AX8817X=m
|
+CONFIG_USB_NET_AX88179_178A=m
|
+CONFIG_USB_NET_CDCETHER=m
|
+CONFIG_USB_NET_CDC_NCM=m
|
+CONFIG_USB_NET_DM9601=m
|
+CONFIG_USB_NET_SR9800=m
|
+CONFIG_USB_NET_SMSC75XX=m
|
+CONFIG_USB_NET_SMSC95XX=m
|
+CONFIG_USB_NET_NET1080=m
|
+CONFIG_USB_NET_PLUSB=m
|
+CONFIG_USB_NET_MCS7830=m
|
+CONFIG_USB_NET_CDC_SUBSET=m
|
+CONFIG_USB_NET_ZAURUS=m
|
+CONFIG_USB_NET_QMI_WWAN=y
|
+CONFIG_HOSTAP=y
|
+CONFIG_WL18XX=m
|
+CONFIG_WLCORE_SDIO=m
|
+CONFIG_XEN_NETDEV_BACKEND=m
|
+CONFIG_INPUT_EVDEV=y
|
+CONFIG_KEYBOARD_ADC=m
|
+CONFIG_KEYBOARD_GPIO=y
|
+CONFIG_KEYBOARD_RPMSG=y
|
+CONFIG_KEYBOARD_SNVS_PWRKEY=y
|
+CONFIG_KEYBOARD_BBNSM_PWRKEY=y
|
+CONFIG_KEYBOARD_IMX_SC_PWRKEY=y
|
+CONFIG_KEYBOARD_CROS_EC=y
|
+CONFIG_INPUT_TOUCHSCREEN=y
|
+CONFIG_TOUCHSCREEN_ATMEL_MXT=m
|
+CONFIG_TOUCHSCREEN_EXC3000=m
|
+CONFIG_TOUCHSCREEN_GOODIX=m
|
+CONFIG_TOUCHSCREEN_EDT_FT5X06=m
|
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_I2C=m
|
+CONFIG_INPUT_MISC=y
|
+CONFIG_INPUT_PWM_VIBRA=m
|
+# CONFIG_SERIO_SERPORT is not set
|
+CONFIG_SERIO_AMBAKMI=y
|
+CONFIG_LEGACY_PTY_COUNT=16
|
+CONFIG_SERIAL_8250=y
|
+CONFIG_SERIAL_8250_CONSOLE=y
|
+CONFIG_SERIAL_8250_EXTENDED=y
|
+CONFIG_SERIAL_8250_SHARE_IRQ=y
|
+CONFIG_SERIAL_8250_DW=y
|
+CONFIG_SERIAL_OF_PLATFORM=y
|
+CONFIG_SERIAL_AMBA_PL011=y
|
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
|
+CONFIG_SERIAL_IMX=y
|
+CONFIG_SERIAL_IMX_CONSOLE=y
|
+CONFIG_SERIAL_XILINX_PS_UART=y
|
+CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y
|
+CONFIG_SERIAL_FSL_LPUART=y
|
+CONFIG_SERIAL_FSL_LPUART_CONSOLE=y
|
+CONFIG_SERIAL_FSL_LINFLEXUART=y
|
+CONFIG_SERIAL_FSL_LINFLEXUART_CONSOLE=y
|
+CONFIG_SERIAL_DEV_BUS=y
|
+CONFIG_VIRTIO_CONSOLE=y
|
+CONFIG_IPMI_HANDLER=m
|
+CONFIG_IPMI_DEVICE_INTERFACE=m
|
+CONFIG_IPMI_SI=m
|
+CONFIG_TCG_TPM=y
|
+CONFIG_TCG_TIS_I2C_INFINEON=y
|
+CONFIG_I2C_CHARDEV=y
|
+CONFIG_I2C_MUX=y
|
+CONFIG_I2C_MUX_PCA954x=y
|
+CONFIG_I2C_DESIGNWARE_PLATFORM=y
|
+CONFIG_I2C_GPIO=m
|
+CONFIG_I2C_IMX=y
|
+CONFIG_I2C_IMX_LPI2C=y
|
+CONFIG_I2C_RK3X=y
|
+CONFIG_I2C_RPBUS=y
|
+CONFIG_I2C_CROS_EC_TUNNEL=y
|
+CONFIG_XEN_I2C_BACKEND=y
|
+CONFIG_I3C=y
|
+CONFIG_SVC_I3C_MASTER=y
|
+CONFIG_SPI=y
|
+CONFIG_SPI_CADENCE_QUADSPI=y
|
+CONFIG_SPI_DESIGNWARE=m
|
+CONFIG_SPI_DW_DMA=y
|
+CONFIG_SPI_DW_MMIO=m
|
+CONFIG_SPI_FSL_LPSPI=y
|
+CONFIG_SPI_FSL_QUADSPI=y
|
+CONFIG_SPI_NXP_FLEXSPI=y
|
+CONFIG_SPI_IMX=y
|
+CONFIG_SPI_FSL_DSPI=y
|
+CONFIG_SPI_PL022=y
|
+CONFIG_SPI_ROCKCHIP=y
|
+CONFIG_SPI_SPIDEV=y
|
+CONFIG_SPI_SLAVE=y
|
+CONFIG_SPI_SLAVE_TIME=y
|
+CONFIG_SPI_SLAVE_SYSTEM_CONTROL=y
|
+CONFIG_SPMI=y
|
+CONFIG_PINCTRL_SINGLE=y
|
+CONFIG_PINCTRL_MAX77620=y
|
+CONFIG_PINCTRL_IMX8MM=y
|
+CONFIG_PINCTRL_IMX8MN=y
|
+CONFIG_PINCTRL_IMX8MP=y
|
+CONFIG_PINCTRL_IMX8MQ=y
|
+CONFIG_PINCTRL_IMX8QM=y
|
+CONFIG_PINCTRL_IMX8QXP=y
|
+CONFIG_PINCTRL_IMX8DXL=y
|
+CONFIG_PINCTRL_IMX8ULP=y
|
+CONFIG_PINCTRL_IMX93=y
|
+CONFIG_PINCTRL_S32V234=y
|
+CONFIG_GPIO_SYSFS=y
|
+CONFIG_GPIO_ALTERA=m
|
+CONFIG_GPIO_DWAPB=y
|
+CONFIG_GPIO_MB86S7X=y
|
+CONFIG_GPIO_MPC8XXX=y
|
+CONFIG_GPIO_PL061=y
|
+CONFIG_GPIO_IMX_RPMSG=y
|
+CONFIG_GPIO_WCD934X=m
|
+CONFIG_GPIO_XGENE=y
|
+CONFIG_GPIO_MAX732X=y
|
+CONFIG_GPIO_PCA953X=y
|
+CONFIG_GPIO_PCA953X_IRQ=y
|
+CONFIG_GPIO_ADP5585=y
|
+CONFIG_GPIO_BD9571MWV=m
|
+CONFIG_GPIO_MAX77620=y
|
+CONFIG_GPIO_SL28CPLD=m
|
+CONFIG_POWER_RESET_BRCMSTB=y
|
+CONFIG_POWER_RESET_XGENE=y
|
+CONFIG_POWER_RESET_SYSCON=y
|
+CONFIG_SYSCON_REBOOT_MODE=y
|
+CONFIG_BATTERY_SBS=m
|
+CONFIG_BATTERY_BQ27XXX=y
|
+CONFIG_BATTERY_MAX17042=m
|
+CONFIG_CHARGER_BQ25890=m
|
+CONFIG_CHARGER_BQ25980=m
|
+CONFIG_SENSORS_ARM_SCMI=y
|
+CONFIG_SENSORS_ARM_SCPI=y
|
+CONFIG_SENSORS_FP9931=y
|
+CONFIG_SENSORS_LM90=m
|
+CONFIG_SENSORS_PWM_FAN=m
|
+CONFIG_SENSORS_SL28CPLD=m
|
+CONFIG_SENSORS_INA2XX=m
|
+CONFIG_SENSORS_INA3221=m
|
+CONFIG_THERMAL_WRITABLE_TRIPS=y
|
+CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
|
+CONFIG_CPU_THERMAL=y
|
+CONFIG_THERMAL_EMULATION=y
|
+CONFIG_IMX_SC_THERMAL=y
|
+CONFIG_IMX8MM_THERMAL=y
|
+CONFIG_DEVICE_THERMAL=y
|
+CONFIG_QORIQ_THERMAL=y
|
+CONFIG_WATCHDOG=y
|
+CONFIG_SL28CPLD_WATCHDOG=m
|
+CONFIG_ARM_SP805_WATCHDOG=y
|
+CONFIG_ARM_SBSA_WATCHDOG=y
|
+CONFIG_DW_WATCHDOG=y
|
+CONFIG_IMX2_WDT=y
|
+CONFIG_IMX_SC_WDT=y
|
+CONFIG_IMX7ULP_WDT=y
|
+CONFIG_ARM_SMC_WATCHDOG=y
|
+CONFIG_XEN_WDT=y
|
+CONFIG_MFD_ADP5585=y
|
+CONFIG_MFD_BD9571MWV=y
|
+CONFIG_MFD_AXP20X_I2C=y
|
+CONFIG_MFD_IMX_MIX=y
|
+CONFIG_MFD_HI6421_PMIC=y
|
+CONFIG_MFD_FP9931=y
|
+CONFIG_MFD_MAX77620=y
|
+CONFIG_MFD_MT6397=y
|
+CONFIG_MFD_RK808=y
|
+CONFIG_MFD_SEC_CORE=y
|
+CONFIG_MFD_SL28CPLD=y
|
+CONFIG_MFD_ROHM_BD718XX=y
|
+CONFIG_MFD_WCD934X=m
|
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
|
+CONFIG_REGULATOR_AXP20X=y
|
+CONFIG_REGULATOR_BD718XX=y
|
+CONFIG_REGULATOR_BD9571MWV=y
|
+CONFIG_REGULATOR_FAN53555=y
|
+CONFIG_REGULATOR_GPIO=y
|
+CONFIG_REGULATOR_HI6421V530=y
|
+CONFIG_REGULATOR_MAX77620=y
|
+CONFIG_REGULATOR_MAX8973=y
|
+CONFIG_REGULATOR_FP9931=y
|
+CONFIG_REGULATOR_MP8859=y
|
+CONFIG_REGULATOR_MT6358=y
|
+CONFIG_REGULATOR_MT6397=y
|
+CONFIG_REGULATOR_PCA9450=y
|
+CONFIG_REGULATOR_PF8X00=y
|
+CONFIG_REGULATOR_PFUZE100=y
|
+CONFIG_REGULATOR_PWM=y
|
+CONFIG_REGULATOR_QCOM_SPMI=y
|
+CONFIG_REGULATOR_RK808=y
|
+CONFIG_REGULATOR_S2MPS11=y
|
+CONFIG_REGULATOR_TPS65132=m
|
+CONFIG_REGULATOR_VCTRL=m
|
+CONFIG_RC_CORE=m
|
+CONFIG_RC_DECODERS=y
|
+CONFIG_IR_NEC_DECODER=m
|
+CONFIG_IR_RC5_DECODER=m
|
+CONFIG_IR_RC6_DECODER=m
|
+CONFIG_IR_JVC_DECODER=m
|
+CONFIG_IR_SONY_DECODER=m
|
+CONFIG_IR_SANYO_DECODER=m
|
+CONFIG_IR_SHARP_DECODER=m
|
+CONFIG_IR_MCE_KBD_DECODER=m
|
+CONFIG_IR_XMP_DECODER=m
|
+CONFIG_IR_IMON_DECODER=m
|
+CONFIG_IR_RCMM_DECODER=m
|
+CONFIG_RC_DEVICES=y
|
+CONFIG_IR_GPIO_CIR=m
|
+CONFIG_MEDIA_SUPPORT=y
|
+CONFIG_MEDIA_SUPPORT_FILTER=y
|
+CONFIG_MEDIA_CAMERA_SUPPORT=y
|
+CONFIG_MEDIA_ANALOG_TV_SUPPORT=y
|
+CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
|
+CONFIG_MEDIA_SDR_SUPPORT=y
|
+CONFIG_MEDIA_PLATFORM_SUPPORT=y
|
+# CONFIG_DVB_NET is not set
|
+CONFIG_MEDIA_USB_SUPPORT=y
|
+CONFIG_USB_VIDEO_CLASS=m
|
+CONFIG_V4L_PLATFORM_DRIVERS=y
|
+CONFIG_VIDEO_IMX8_JPEG=m
|
+CONFIG_VIDEO_AMPHION_VPU=y
|
+CONFIG_VIDEO_MXC_CAPTURE=y
|
+CONFIG_VIDEO_MX8_CAPTURE=y
|
+CONFIG_VIDEO_MXC_CSI_CAMERA=y
|
+CONFIG_MXC_MIPI_CSI=y
|
+CONFIG_MXC_CAMERA_OV5640_MIPI_V2=y
|
+CONFIG_V4L_MEM2MEM_DRIVERS=y
|
+CONFIG_SDR_PLATFORM_DRIVERS=y
|
+CONFIG_VIDEO_IMX219=m
|
+CONFIG_VIDEO_OV5640=y
|
+CONFIG_VIDEO_OV5645=m
|
+CONFIG_VIDEO_MT9M114=y
|
+CONFIG_VIDEO_AP1302=y
|
+CONFIG_IMX_DPU_CORE=y
|
+CONFIG_IMX_LCDIF_CORE=y
|
+CONFIG_IMX_LCDIFV3_CORE=y
|
+CONFIG_DRM=y
|
+CONFIG_DRM_I2C_CH7006=m
|
+CONFIG_DRM_I2C_SIL164=m
|
+CONFIG_DRM_I2C_NXP_TDA998X=m
|
+CONFIG_DRM_MALI_DISPLAY=m
|
+CONFIG_DRM_RCAR_DW_HDMI=m
|
+CONFIG_DRM_RCAR_LVDS=m
|
+CONFIG_DRM_PANEL_BOE_TV101WUM_NL6=m
|
+CONFIG_DRM_PANEL_LVDS=m
|
+CONFIG_DRM_PANEL_SIMPLE=y
|
+CONFIG_DRM_PANEL_MANTIX_MLAF057WE51=m
|
+CONFIG_DRM_PANEL_ONTAT_KD50G21_40NT_A1=y
|
+CONFIG_DRM_PANEL_RAYDIUM_RM67191=y
|
+CONFIG_DRM_PANEL_RAYDIUM_RM68200=y
|
+CONFIG_DRM_PANEL_ROCKTECK_HIMAX8394F=y
|
+CONFIG_DRM_PANEL_SEIKO_43WVF1G=y
|
+CONFIG_DRM_PANEL_SITRONIX_ST7703=m
|
+CONFIG_DRM_PANEL_TRULY_NT35597_WQXGA=m
|
+CONFIG_DRM_PANEL_WKS_101WX001=y
|
+CONFIG_DRM_DISPLAY_CONNECTOR=m
|
+CONFIG_DRM_LONTIUM_LT8912B=m
|
+CONFIG_DRM_LONTIUM_LT9611=m
|
+CONFIG_DRM_LONTIUM_LT9611UXC=m
|
+CONFIG_DRM_FSL_IMX_LVDS_BRIDGE=y
|
+CONFIG_DRM_NWL_MIPI_DSI=y
|
+CONFIG_DRM_NXP_SEIKO_43WVFIG=y
|
+CONFIG_DRM_PARADE_PS8640=m
|
+CONFIG_DRM_SII902X=m
|
+CONFIG_DRM_SIMPLE_BRIDGE=m
|
+CONFIG_DRM_THINE_THC63LVD1024=m
|
+CONFIG_DRM_TI_SN65DSI86=m
|
+CONFIG_DRM_I2C_ADV7511=y
|
+CONFIG_DRM_I2C_ADV7511_AUDIO=y
|
+CONFIG_DRM_CDNS_HDCP=y
|
+CONFIG_DRM_DW_HDMI_AHB_AUDIO=m
|
+CONFIG_DRM_DW_HDMI_I2S_AUDIO=m
|
+CONFIG_DRM_DW_HDMI_GP_AUDIO=y
|
+CONFIG_DRM_DW_HDMI_CEC=m
|
+CONFIG_DRM_ITE_IT6263=y
|
+CONFIG_DRM_ITE_IT6161=y
|
+CONFIG_DRM_IMX=y
|
+CONFIG_DRM_IMX_LCDIF_MUX_DISPLAY=y
|
+CONFIG_DRM_IMX_PARALLEL_DISPLAY=y
|
+CONFIG_DRM_IMX_TVE=y
|
+CONFIG_DRM_IMX_LDB=y
|
+CONFIG_DRM_IMX8QM_LDB=y
|
+CONFIG_DRM_IMX8QXP_LDB=y
|
+CONFIG_DRM_IMX8MP_LDB=y
|
+CONFIG_DRM_IMX93_LDB=y
|
+CONFIG_DRM_IMX93_PARALLEL_DISPLAY_FORMAT=y
|
+CONFIG_DRM_IMX_DW_MIPI_DSI=y
|
+CONFIG_DRM_IMX_HDMI=y
|
+CONFIG_DRM_IMX_SEC_DSIM=y
|
+CONFIG_DRM_IMX_DCNANO=y
|
+CONFIG_DRM_IMX_DCSS=y
|
+CONFIG_DRM_IMX_CDNS_MHDP=y
|
+CONFIG_DRM_ETNAVIV=m
|
+CONFIG_DRM_HISI_KIRIN=m
|
+CONFIG_DRM_MXSFB=y
|
+CONFIG_DRM_PL111=m
|
+CONFIG_DRM_LIMA=m
|
+CONFIG_DRM_PANFROST=m
|
+CONFIG_DRM_LEGACY=y
|
+CONFIG_FB=y
|
+CONFIG_FB_ARMCLCD=y
|
+CONFIG_FB_EFI=y
|
+CONFIG_FB_MXC_EINK_V2_PANEL=y
|
+CONFIG_BACKLIGHT_PWM=y
|
+CONFIG_BACKLIGHT_LP855X=m
|
+CONFIG_FRAMEBUFFER_CONSOLE=y
|
+CONFIG_LOGO=y
|
+# CONFIG_LOGO_LINUX_MONO is not set
|
+# CONFIG_LOGO_LINUX_VGA16 is not set
|
+CONFIG_SOUND=y
|
+CONFIG_SND=y
|
+CONFIG_SND_ALOOP=m
|
+CONFIG_SND_USB_AUDIO=m
|
+CONFIG_SND_SOC=y
|
+CONFIG_SND_SOC_FSL_ASRC=m
|
+CONFIG_SND_SOC_FSL_MQS=m
|
+CONFIG_SND_SOC_FSL_MICFIL=m
|
+CONFIG_SND_SOC_FSL_EASRC=m
|
+CONFIG_SND_SOC_FSL_XCVR=m
|
+CONFIG_SND_SOC_FSL_ESAI_CLIENT=y
|
+CONFIG_SND_SOC_FSL_RPMSG=m
|
+CONFIG_SND_IMX_SOC=m
|
+CONFIG_SND_SOC_IMX_SGTL5000=m
|
+CONFIG_SND_SOC_IMX_SPDIF=m
|
+CONFIG_SND_SOC_FSL_ASOC_CARD=m
|
+CONFIG_SND_SOC_IMX_AUDMIX=m
|
+CONFIG_SND_SOC_IMX_HDMI=m
|
+CONFIG_SND_SOC_IMX_CARD=m
|
+CONFIG_SND_SOC_IMX_PDM_MIC=m
|
+CONFIG_SND_SOC_IMX_PCM512X=m
|
+CONFIG_SND_SOC_SOF_TOPLEVEL=y
|
+CONFIG_SND_SOC_SOF_OF=m
|
+CONFIG_SND_SOC_SOF_IMX_TOPLEVEL=y
|
+CONFIG_SND_SOC_SOF_IMX8=m
|
+CONFIG_SND_SOC_SOF_IMX8M=m
|
+CONFIG_SND_SOC_SOF_IMX8ULP=m
|
+CONFIG_SND_SOC_AK4613=m
|
+CONFIG_SND_SOC_BT_SCO=y
|
+CONFIG_SND_SOC_CROS_EC_CODEC=m
|
+CONFIG_SND_SOC_CS42XX8_I2C=y
|
+CONFIG_SND_SOC_DMIC=m
|
+CONFIG_SND_SOC_ES7134=m
|
+CONFIG_SND_SOC_ES7241=m
|
+CONFIG_SND_SOC_GTM601=m
|
+CONFIG_SND_SOC_MAX98357A=m
|
+CONFIG_SND_SOC_MAX98927=m
|
+CONFIG_SND_SOC_MSM8916_WCD_ANALOG=m
|
+CONFIG_SND_SOC_MSM8916_WCD_DIGITAL=m
|
+CONFIG_SND_SOC_PCM3168A_I2C=m
|
+CONFIG_SND_SOC_RT5659=m
|
+CONFIG_SND_SOC_SIMPLE_AMPLIFIER=m
|
+CONFIG_SND_SOC_SIMPLE_MUX=m
|
+CONFIG_SND_SOC_SPDIF=m
|
+CONFIG_SND_SOC_TAS571X=m
|
+CONFIG_SND_SOC_WCD934X=m
|
+CONFIG_SND_SOC_WM8524=y
|
+CONFIG_SND_SOC_WM8904=m
|
+CONFIG_SND_SOC_WM8960=m
|
+CONFIG_SND_SOC_WM8962=m
|
+CONFIG_SND_SOC_WSA881X=m
|
+CONFIG_SND_SOC_RPMSG_WM8960=m
|
+CONFIG_SND_SOC_RPMSG_AK4497=m
|
+CONFIG_SND_SOC_NAU8810=m
|
+CONFIG_SND_SOC_NAU8822=m
|
+CONFIG_SND_SOC_LPASS_WSA_MACRO=m
|
+CONFIG_SND_SOC_LPASS_VA_MACRO=m
|
+CONFIG_SND_SIMPLE_CARD=y
|
+CONFIG_SND_AUDIO_GRAPH_CARD=y
|
+CONFIG_HID_A4TECH=y
|
+CONFIG_HID_APPLE=y
|
+CONFIG_HID_BELKIN=y
|
+CONFIG_HID_CHERRY=y
|
+CONFIG_HID_CHICONY=y
|
+CONFIG_HID_CYPRESS=y
|
+CONFIG_HID_EZKEY=y
|
+CONFIG_HID_ITE=y
|
+CONFIG_HID_KENSINGTON=y
|
+CONFIG_HID_LOGITECH=y
|
+CONFIG_HID_REDRAGON=y
|
+CONFIG_HID_MICROSOFT=y
|
+CONFIG_HID_MONTEREY=y
|
+CONFIG_HID_MULTITOUCH=m
|
+CONFIG_I2C_HID_ACPI=m
|
+CONFIG_I2C_HID_OF=m
|
+CONFIG_USB_CONN_GPIO=y
|
+CONFIG_USB=y
|
+CONFIG_USB_OTG=y
|
+CONFIG_USB_XHCI_HCD=y
|
+CONFIG_USB_XHCI_PCI_RENESAS=m
|
+CONFIG_USB_EHCI_HCD=y
|
+CONFIG_USB_EHCI_HCD_PLATFORM=y
|
+CONFIG_USB_OHCI_HCD=y
|
+CONFIG_USB_OHCI_HCD_PLATFORM=y
|
+CONFIG_USB_HCD_TEST_MODE=y
|
+CONFIG_USB_ACM=y
|
+CONFIG_USB_STORAGE=y
|
+CONFIG_USB_UAS=y
|
+CONFIG_USB_CDNS_SUPPORT=y
|
+CONFIG_USB_CDNS3=y
|
+CONFIG_USB_CDNS3_GADGET=y
|
+CONFIG_USB_CDNS3_HOST=y
|
+CONFIG_USB_MUSB_HDRC=y
|
+CONFIG_USB_DWC3=y
|
+CONFIG_USB_DWC2=y
|
+CONFIG_USB_CHIPIDEA=y
|
+CONFIG_USB_CHIPIDEA_UDC=y
|
+CONFIG_USB_CHIPIDEA_HOST=y
|
+CONFIG_USB_ISP1760=y
|
+CONFIG_USB_SERIAL=y
|
+CONFIG_USB_SERIAL_CONSOLE=y
|
+CONFIG_USB_SERIAL_GENERIC=y
|
+CONFIG_USB_SERIAL_SIMPLE=y
|
+CONFIG_USB_SERIAL_CP210X=m
|
+CONFIG_USB_SERIAL_FTDI_SIO=y
|
+CONFIG_USB_SERIAL_QUALCOMM=y
|
+CONFIG_USB_SERIAL_OPTION=y
|
+CONFIG_USB_TEST=m
|
+CONFIG_USB_EHSET_TEST_FIXTURE=y
|
+CONFIG_USB_HSIC_USB3503=y
|
+CONFIG_NOP_USB_XCEIV=y
|
+CONFIG_USB_MXS_PHY=y
|
+CONFIG_USB_ULPI=y
|
+CONFIG_USB_GADGET=y
|
+CONFIG_USB_SNP_UDC_PLAT=y
|
+CONFIG_USB_BDC_UDC=y
|
+CONFIG_USB_CONFIGFS=y
|
+CONFIG_USB_CONFIGFS_SERIAL=y
|
+CONFIG_USB_CONFIGFS_ACM=y
|
+CONFIG_USB_CONFIGFS_OBEX=y
|
+CONFIG_USB_CONFIGFS_NCM=y
|
+CONFIG_USB_CONFIGFS_ECM=y
|
+CONFIG_USB_CONFIGFS_ECM_SUBSET=y
|
+CONFIG_USB_CONFIGFS_RNDIS=y
|
+CONFIG_USB_CONFIGFS_EEM=y
|
+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
|
+CONFIG_USB_CONFIGFS_F_LB_SS=y
|
+CONFIG_USB_CONFIGFS_F_FS=y
|
+CONFIG_USB_CONFIGFS_F_UAC1=y
|
+CONFIG_USB_CONFIGFS_F_UAC1_LEGACY=y
|
+CONFIG_USB_CONFIGFS_F_UAC2=y
|
+CONFIG_USB_CONFIGFS_F_MIDI=y
|
+CONFIG_USB_CONFIGFS_F_HID=y
|
+CONFIG_USB_CONFIGFS_F_UVC=y
|
+CONFIG_USB_ZERO=m
|
+CONFIG_USB_AUDIO=m
|
+CONFIG_USB_ETH=m
|
+CONFIG_USB_MASS_STORAGE=m
|
+CONFIG_USB_G_SERIAL=m
|
+CONFIG_TYPEC=y
|
+CONFIG_TYPEC_TCPM=y
|
+CONFIG_TYPEC_TCPCI=y
|
+CONFIG_TYPEC_FUSB302=m
|
+CONFIG_TYPEC_TPS6598X=m
|
+CONFIG_TYPEC_HD3SS3220=m
|
+CONFIG_TYPEC_SWITCH_GPIO=y
|
+CONFIG_MMC=y
|
+CONFIG_MMC_BLOCK_MINORS=32
|
+CONFIG_MMC_ARMMMCI=y
|
+CONFIG_MMC_SDHCI=y
|
+CONFIG_MMC_SDHCI_PLTFM=y
|
+CONFIG_MMC_SDHCI_OF_ARASAN=y
|
+CONFIG_MMC_SDHCI_OF_ESDHC=y
|
+CONFIG_MMC_SDHCI_CADENCE=y
|
+CONFIG_MMC_SDHCI_ESDHC_IMX=y
|
+CONFIG_MMC_SDHCI_F_SDH30=y
|
+CONFIG_MMC_SPI=y
|
+CONFIG_MMC_DW=y
|
+CONFIG_MMC_DW_EXYNOS=y
|
+CONFIG_MMC_DW_HI3798CV200=y
|
+CONFIG_MMC_DW_K3=y
|
+CONFIG_MMC_MTK=y
|
+CONFIG_MMC_SDHCI_XENON=y
|
+CONFIG_MMC_SDHCI_AM654=y
|
+CONFIG_NEW_LEDS=y
|
+CONFIG_LEDS_CLASS=y
|
+CONFIG_LEDS_LM3692X=m
|
+CONFIG_LEDS_PCA9532=m
|
+CONFIG_LEDS_GPIO=y
|
+CONFIG_LEDS_PCA995X=m
|
+CONFIG_LEDS_PWM=y
|
+CONFIG_LEDS_SYSCON=y
|
+CONFIG_LEDS_TRIGGER_TIMER=y
|
+CONFIG_LEDS_TRIGGER_DISK=y
|
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
|
+CONFIG_LEDS_TRIGGER_CPU=y
|
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
|
+CONFIG_LEDS_TRIGGER_PANIC=y
|
+CONFIG_RTC_CLASS=y
|
+CONFIG_RTC_DRV_DS1307=m
|
+CONFIG_RTC_DRV_HYM8563=m
|
+CONFIG_RTC_DRV_MAX77686=y
|
+CONFIG_RTC_DRV_RK808=m
|
+CONFIG_RTC_DRV_PCF85363=m
|
+CONFIG_RTC_DRV_M41T80=m
|
+CONFIG_RTC_DRV_RX8581=m
|
+CONFIG_RTC_DRV_RV3028=m
|
+CONFIG_RTC_DRV_RV8803=m
|
+CONFIG_RTC_DRV_S5M=y
|
+CONFIG_RTC_DRV_DS3232=y
|
+CONFIG_RTC_DRV_PCF2127=m
|
+CONFIG_RTC_DRV_EFI=y
|
+CONFIG_RTC_DRV_CROS_EC=y
|
+CONFIG_RTC_DRV_FSL_FTM_ALARM=m
|
+CONFIG_RTC_DRV_PL031=y
|
+CONFIG_RTC_DRV_SNVS=y
|
+CONFIG_RTC_DRV_BBNSM=y
|
+CONFIG_RTC_DRV_IMX_SC=y
|
+CONFIG_RTC_DRV_IMX_RPMSG=y
|
+CONFIG_DMADEVICES=y
|
+CONFIG_BCM_SBA_RAID=m
|
+CONFIG_FSL_EDMA=y
|
+CONFIG_FSL_QDMA=m
|
+CONFIG_FSL_EDMA_V3=y
|
+CONFIG_IMX_SDMA=y
|
+CONFIG_MV_XOR_V2=y
|
+CONFIG_MXS_DMA=y
|
+CONFIG_MXC_PXP_V3=y
|
+CONFIG_PL330_DMA=y
|
+CONFIG_QCOM_HIDMA_MGMT=y
|
+CONFIG_QCOM_HIDMA=y
|
+CONFIG_FSL_DPAA2_QDMA=m
|
+CONFIG_DMATEST=y
|
+CONFIG_DMABUF_HEAPS=y
|
+CONFIG_DMABUF_HEAPS_SYSTEM=y
|
+CONFIG_DMABUF_HEAPS_CMA=y
|
+CONFIG_DMABUF_HEAPS_DSP=y
|
+CONFIG_VFIO=y
|
+CONFIG_VFIO_FSL_MC=y
|
+CONFIG_VIRTIO_BALLOON=y
|
+CONFIG_VIRTIO_MMIO=y
|
+CONFIG_XEN_GNTDEV=y
|
+CONFIG_XEN_GRANT_DEV_ALLOC=y
|
+CONFIG_STAGING=y
|
+CONFIG_STAGING_MEDIA=y
|
+CONFIG_VIDEO_HANTRO=m
|
+CONFIG_VIDEO_IMX_CAPTURE=y
|
+CONFIG_IMX8_MEDIA_DEVICE=m
|
+CONFIG_MHDP_HDMIRX=y
|
+CONFIG_MHDP_HDMIRX_CEC=y
|
+CONFIG_FSL_DPAA2=y
|
+CONFIG_FSL_PPFE=y
|
+CONFIG_FSL_PPFE_UTIL_DISABLED=y
|
+CONFIG_ETHOSU=y
|
+CONFIG_CHROME_PLATFORMS=y
|
+CONFIG_CROS_EC=y
|
+CONFIG_CROS_EC_I2C=y
|
+CONFIG_CROS_EC_SPI=y
|
+CONFIG_CROS_EC_CHARDEV=m
|
+CONFIG_CLK_VEXPRESS_OSC=y
|
+CONFIG_COMMON_CLK_RK808=y
|
+CONFIG_COMMON_CLK_SCMI=y
|
+CONFIG_COMMON_CLK_SCPI=y
|
+CONFIG_COMMON_CLK_CS2000_CP=y
|
+CONFIG_COMMON_CLK_FSL_SAI=y
|
+CONFIG_COMMON_CLK_S2MPS11=y
|
+CONFIG_COMMON_CLK_XGENE=y
|
+CONFIG_COMMON_CLK_PWM=y
|
+CONFIG_COMMON_CLK_VC5=y
|
+CONFIG_CLK_IMX8MM=y
|
+CONFIG_CLK_IMX8MN=y
|
+CONFIG_CLK_IMX8MP=y
|
+CONFIG_CLK_IMX8MQ=y
|
+CONFIG_CLK_IMX8QXP=y
|
+CONFIG_CLK_IMX8ULP=y
|
+CONFIG_CLK_IMX93=y
|
+CONFIG_HWSPINLOCK=y
|
+CONFIG_ARM_MHU=y
|
+CONFIG_IMX_MBOX=y
|
+CONFIG_PLATFORM_MHU=y
|
+CONFIG_IOMMU_IO_PGTABLE_ARMV7S=y
|
+CONFIG_ARM_SMMU=y
|
+CONFIG_ARM_SMMU_V3=y
|
+CONFIG_REMOTEPROC=y
|
+CONFIG_IMX_REMOTEPROC=y
|
+CONFIG_IMX_DSP_REMOTEPROC=m
|
+CONFIG_RPMSG_CHAR=m
|
+CONFIG_RPMSG_QCOM_GLINK_RPM=y
|
+CONFIG_SOUNDWIRE=m
|
+CONFIG_SOUNDWIRE_QCOM=m
|
+CONFIG_SOC_BRCMSTB=y
|
+CONFIG_FSL_DPAA=y
|
+CONFIG_FSL_MC_DPIO=y
|
+CONFIG_FSL_RCPM=y
|
+CONFIG_FSL_QIXIS=y
|
+CONFIG_SOC_TI=y
|
+CONFIG_EXTCON_PTN5150=m
|
+CONFIG_EXTCON_USB_GPIO=y
|
+CONFIG_EXTCON_USBC_CROS_EC=y
|
+CONFIG_IIO=y
|
+CONFIG_FXLS8962AF_I2C=m
|
+CONFIG_IMX8QXP_ADC=y
|
+CONFIG_IMX93_ADC=y
|
+CONFIG_MAX9611=m
|
+CONFIG_QCOM_SPMI_VADC=m
|
+CONFIG_QCOM_SPMI_ADC5=m
|
+CONFIG_IIO_CROS_EC_SENSORS_CORE=m
|
+CONFIG_IIO_CROS_EC_SENSORS=m
|
+CONFIG_FXAS21002C=y
|
+CONFIG_FXOS8700_I2C=y
|
+CONFIG_RPMSG_IIO_PEDOMETER=m
|
+CONFIG_IIO_ST_LSM6DSX=y
|
+CONFIG_IIO_CROS_EC_LIGHT_PROX=m
|
+CONFIG_SENSORS_ISL29018=y
|
+CONFIG_VCNL4000=m
|
+CONFIG_IIO_ST_MAGN_3AXIS=m
|
+CONFIG_IIO_CROS_EC_BARO=m
|
+CONFIG_MPL3115=y
|
+CONFIG_PWM=y
|
+CONFIG_PWM_ADP5585=y
|
+CONFIG_PWM_CROS_EC=m
|
+CONFIG_PWM_FSL_FTM=m
|
+CONFIG_PWM_IMX27=y
|
+CONFIG_PWM_RPCHIP=y
|
+CONFIG_PWM_SL28CPLD=m
|
+CONFIG_SL28CPLD_INTC=y
|
+CONFIG_RESET_IMX7=y
|
+CONFIG_RESET_IMX8ULP_SIM=y
|
+CONFIG_PHY_XGENE=y
|
+CONFIG_PHY_MIXEL_LVDS=y
|
+CONFIG_PHY_MIXEL_LVDS_COMBO=y
|
+CONFIG_PHY_CADENCE_SALVO=y
|
+CONFIG_PHY_FSL_IMX8MP_LVDS=y
|
+CONFIG_PHY_FSL_IMX93_MIPI_DPHY=y
|
+CONFIG_PHY_MIXEL_MIPI_DPHY=y
|
+CONFIG_PHY_SAMSUNG_HDMI_PHY=y
|
+CONFIG_PHY_QCOM_USB_HS=y
|
+CONFIG_PHY_SAMSUNG_USB2=y
|
+CONFIG_ARM_SMMU_V3_PMU=m
|
+CONFIG_FSL_IMX8_DDR_PMU=y
|
+CONFIG_FSL_IMX9_DDR_PMU=y
|
+CONFIG_HISI_PMU=y
|
+CONFIG_NVMEM_IMX_OCOTP=y
|
+CONFIG_NVMEM_IMX_OCOTP_SCU=y
|
+CONFIG_NVMEM_RMEM=m
|
+CONFIG_FPGA=y
|
+CONFIG_FPGA_BRIDGE=m
|
+CONFIG_ALTERA_FREEZE_BRIDGE=m
|
+CONFIG_FPGA_REGION=m
|
+CONFIG_OF_FPGA_REGION=m
|
+CONFIG_TEE=y
|
+CONFIG_OPTEE=y
|
+CONFIG_MUX_MMIO=y
|
+CONFIG_SLIM_QCOM_CTRL=m
|
+CONFIG_MXC_SIM=y
|
+CONFIG_MXC_EMVSIM=y
|
+CONFIG_EXT2_FS=y
|
+CONFIG_EXT3_FS=y
|
+CONFIG_EXT4_FS_POSIX_ACL=y
|
+CONFIG_BTRFS_FS=m
|
+CONFIG_BTRFS_FS_POSIX_ACL=y
|
+CONFIG_FANOTIFY=y
|
+CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y
|
+CONFIG_QUOTA=y
|
+CONFIG_AUTOFS4_FS=y
|
+CONFIG_FUSE_FS=m
|
+CONFIG_CUSE=m
|
+CONFIG_OVERLAY_FS=m
|
+CONFIG_VFAT_FS=y
|
+CONFIG_TMPFS_POSIX_ACL=y
|
+CONFIG_HUGETLBFS=y
|
+CONFIG_EFIVAR_FS=y
|
+CONFIG_JFFS2_FS=y
|
+CONFIG_UBIFS_FS=y
|
+CONFIG_SQUASHFS=y
|
+CONFIG_SQUASHFS_XZ=y
|
+CONFIG_NFS_FS=y
|
+CONFIG_NFS_V4=y
|
+CONFIG_NFS_V4_1=y
|
+CONFIG_NFS_V4_2=y
|
+CONFIG_ROOT_NFS=y
|
+CONFIG_9P_FS=y
|
+CONFIG_NLS_CODEPAGE_437=y
|
+CONFIG_NLS_ISO8859_1=y
|
+CONFIG_TRUSTED_KEYS=m
|
+# CONFIG_TRUSTED_KEYS_TPM is not set
|
+# CONFIG_TRUSTED_KEYS_TEE is not set
|
+CONFIG_SECURITY=y
|
+CONFIG_CRYPTO_USER=y
|
+CONFIG_CRYPTO_TEST=m
|
+CONFIG_CRYPTO_DH=m
|
+CONFIG_CRYPTO_CURVE25519=m
|
+CONFIG_CRYPTO_CHACHA20POLY1305=m
|
+CONFIG_CRYPTO_ECHAINIV=y
|
+CONFIG_CRYPTO_TLS=m
|
+CONFIG_CRYPTO_CFB=m
|
+CONFIG_CRYPTO_CTS=m
|
+CONFIG_CRYPTO_LRW=m
|
+CONFIG_CRYPTO_OFB=m
|
+CONFIG_CRYPTO_PCBC=m
|
+CONFIG_CRYPTO_XCBC=m
|
+CONFIG_CRYPTO_VMAC=m
|
+CONFIG_CRYPTO_MD4=m
|
+CONFIG_CRYPTO_RMD160=m
|
+CONFIG_CRYPTO_STREEBOG=m
|
+CONFIG_CRYPTO_WP512=m
|
+CONFIG_CRYPTO_ANUBIS=m
|
+CONFIG_CRYPTO_ARC4=m
|
+CONFIG_CRYPTO_BLOWFISH=m
|
+CONFIG_CRYPTO_CAMELLIA=m
|
+CONFIG_CRYPTO_CAST5=m
|
+CONFIG_CRYPTO_CAST6=m
|
+CONFIG_CRYPTO_FCRYPT=m
|
+CONFIG_CRYPTO_KHAZAD=m
|
+CONFIG_CRYPTO_SEED=m
|
+CONFIG_CRYPTO_SERPENT=m
|
+CONFIG_CRYPTO_TEA=m
|
+CONFIG_CRYPTO_TWOFISH=m
|
+CONFIG_CRYPTO_ANSI_CPRNG=y
|
+CONFIG_CRYPTO_USER_API_HASH=m
|
+CONFIG_CRYPTO_USER_API_SKCIPHER=m
|
+CONFIG_CRYPTO_USER_API_RNG=m
|
+CONFIG_CRYPTO_USER_API_AEAD=m
|
+CONFIG_CRYPTO_DEV_FSL_CAAM_SECVIO=m
|
+CONFIG_CRYPTO_DEV_FSL_CAAM=m
|
+CONFIG_CRYPTO_DEV_FSL_CAAM_SM_TEST=m
|
+CONFIG_CRYPTO_DEV_FSL_DPAA2_CAAM=m
|
+CONFIG_CRYPTO_DEV_CCREE=m
|
+CONFIG_CRYPTO_DEV_HISI_TRNG=m
|
+CONFIG_CRYPTO_DEV_AMLOGIC_GXL=m
|
+CONFIG_INDIRECT_PIO=y
|
+CONFIG_CRC8=y
|
+CONFIG_CMA_SIZE_MBYTES=32
|
+CONFIG_IRQ_POLL=y
|
+CONFIG_PRINTK_TIME=y
|
+CONFIG_DEBUG_INFO=y
|
+CONFIG_DEBUG_INFO_REDUCED=y
|
+CONFIG_MAGIC_SYSRQ=y
|
+CONFIG_DEBUG_FS=y
|
+# CONFIG_SCHED_DEBUG is not set
|
+# CONFIG_DEBUG_PREEMPT is not set
|
+# CONFIG_FTRACE is not set
|
+CONFIG_CORESIGHT=y
|
+CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y
|
+CONFIG_CORESIGHT_SOURCE_ETM4X=y
|
+CONFIG_MEMTEST=y
|
diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
|
index 47e1a2a60..1dde096b7 100644
|
--- a/drivers/gpu/drm/panel/panel-simple.c
|
+++ b/drivers/gpu/drm/panel/panel-simple.c
|
@@ -1234,6 +1234,31 @@ static const struct panel_desc auo_g101evn010 = {
|
.connector_type = DRM_MODE_CONNECTOR_LVDS,
|
};
|
|
+/* add by datasheet*/
|
+static const struct drm_display_mode auo_g101ean02_mode = {
|
+ .clock = 74250,
|
+ .hdisplay = 1280,
|
+ .hsync_start = 1280 + 100,
|
+ .hsync_end = 1280 + 100 + 20,
|
+ .htotal = 1280 + 100 + 20 + 80,
|
+ .vdisplay = 800,
|
+ .vsync_start = 800 + 18,
|
+ .vsync_end = 800 + 18 + 6,
|
+ .vtotal = 800 + 18 + 6 + 12,
|
+};
|
+
|
+static const struct panel_desc auo_g101ean02 = {
|
+ .modes = &auo_g101ean02_mode,
|
+ .num_modes = 1,
|
+ .bpc = 8,
|
+ .size = {
|
+ .width = 228,
|
+ .height = 148,
|
+ },
|
+ .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
|
+ .connector_type = DRM_MODE_CONNECTOR_LVDS,
|
+};
|
+
|
static const struct drm_display_mode auo_g104sn02_mode = {
|
.clock = 40000,
|
.hdisplay = 800,
|
@@ -4583,6 +4608,9 @@ static const struct of_device_id platform_of_match[] = {
|
}, {
|
.compatible = "auo,g101evn010",
|
.data = &auo_g101evn010,
|
+ }, {
|
+ .compatible = "auo,g101ean02",
|
+ .data = &auo_g101ean02,
|
}, {
|
.compatible = "auo,g104sn02",
|
.data = &auo_g104sn02,
|
diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig
|
index 8939e5fbd..1b2430047 100644
|
--- a/drivers/net/usb/Kconfig
|
+++ b/drivers/net/usb/Kconfig
|
@@ -644,4 +644,11 @@ config USB_RTL8153_ECM
|
CONFIG_USB_RTL8152 is not set, or the RTL8153 device is not
|
supported by r8152 driver.
|
|
+config USB_GOBI_NET
|
+ tristate"Gobi USB Net driver for Quectel module"
|
+ help
|
+ Support Quectelmodule.
|
+ A modemmanager with support for GobiNet is recommended.
|
+ Tocompile this driver as a module, choose M here: the module will be calledGobiNet.
|
+
|
endif # USB_NET_DRIVERS
|
diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile
|
index 4964f7b32..e34d3d112 100644
|
--- a/drivers/net/usb/Makefile
|
+++ b/drivers/net/usb/Makefile
|
@@ -37,8 +37,11 @@ obj-$(CONFIG_USB_NET_CX82310_ETH) += cx82310_eth.o
|
obj-$(CONFIG_USB_NET_CDC_NCM) += cdc_ncm.o
|
obj-$(CONFIG_USB_NET_HUAWEI_CDC_NCM) += huawei_cdc_ncm.o
|
obj-$(CONFIG_USB_VL600) += lg-vl600.o
|
+obj-$(CONFIG_USB_NET_QMI_WWAN) += qmi_wwan_q.o
|
obj-$(CONFIG_USB_NET_QMI_WWAN) += qmi_wwan.o
|
obj-$(CONFIG_USB_NET_CDC_MBIM) += cdc_mbim.o
|
obj-$(CONFIG_USB_NET_CH9200) += ch9200.o
|
obj-$(CONFIG_USB_NET_AQC111) += aqc111.o
|
obj-$(CONFIG_USB_RTL8153_ECM) += r8153_ecm.o
|
+# obj-$(CONFIG_USB_GOBI_NET) += GobiNet.o
|
+# GobiNet-objs := qmap.o GobiUSBNet.o QMIDevice.o QMI.o
|
diff --git a/drivers/net/usb/qmi_wwan_q.c b/drivers/net/usb/qmi_wwan_q.c
|
new file mode 100644
|
index 000000000..5b9c9ac18
|
--- /dev/null
|
+++ b/drivers/net/usb/qmi_wwan_q.c
|
@@ -0,0 +1,2577 @@
|
+/*
|
+ * Copyright (c) 2012 Bjørn Mork <bjorn@mork.no>
|
+ *
|
+ * The probing code is heavily inspired by cdc_ether, which is:
|
+ * Copyright (C) 2003-2005 by David Brownell
|
+ * Copyright (C) 2006 by Ole Andre Vadla Ravnas (ActiveSync)
|
+ *
|
+ * This program is free software; you can redistribute it and/or
|
+ * modify it under the terms of the GNU General Public License
|
+ * version 2 as published by the Free Software Foundation.
|
+ */
|
+
|
+#include <linux/module.h>
|
+#include <linux/version.h>
|
+#include <linux/interrupt.h>
|
+#include <linux/netdevice.h>
|
+#include <linux/ethtool.h>
|
+#include <linux/etherdevice.h>
|
+#include <linux/time.h>
|
+#if LINUX_VERSION_CODE > KERNEL_VERSION(3,16,0) //8b094cd03b4a3793220d8d8d86a173bfea8c285b
|
+#include <linux/timekeeping.h>
|
+#else
|
+#define timespec64 timespec
|
+#define ktime_get_ts64 ktime_get_ts
|
+#define timespec64_sub timespec_sub
|
+#endif
|
+#include <net/arp.h>
|
+#include <net/ip.h>
|
+#include <net/ipv6.h>
|
+#include <linux/mii.h>
|
+#include <linux/usb.h>
|
+#include <linux/usb/cdc.h>
|
+#include <linux/usb/usbnet.h>
|
+#include <linux/usb/cdc-wdm.h>
|
+
|
+#ifndef ETH_P_MAP
|
+#define ETH_P_MAP 0xDA1A
|
+#endif
|
+
|
+#if (ETH_P_MAP == 0x00F9)
|
+#undef ETH_P_MAP
|
+#define ETH_P_MAP 0xDA1A
|
+#endif
|
+
|
+#ifndef ARPHRD_RAWIP
|
+#define ARPHRD_RAWIP ARPHRD_NONE
|
+#endif
|
+
|
+#ifdef CONFIG_PINCTRL_IPQ807x
|
+#define CONFIG_QCA_NSS_DRV
|
+//#define CONFIG_QCA_NSS_PACKET_FILTER
|
+#endif
|
+
|
+#define _RMNET_NSS_H_
|
+#define _RMENT_NSS_H_
|
+struct rmnet_nss_cb {
|
+ int (*nss_create)(struct net_device *dev);
|
+ int (*nss_free)(struct net_device *dev);
|
+ int (*nss_tx)(struct sk_buff *skb);
|
+};
|
+static struct rmnet_nss_cb __read_mostly *nss_cb = NULL;
|
+#if defined(CONFIG_PINCTRL_IPQ807x) || defined(CONFIG_PINCTRL_IPQ5018)
|
+#ifdef CONFIG_RMNET_DATA
|
+#define CONFIG_QCA_NSS_DRV
|
+/* define at qsdk/qca/src/linux-4.4/net/rmnet_data/rmnet_data_main.c */
|
+/* set at qsdk/qca/src/data-kernel/drivers/rmnet-nss/rmnet_nss.c */
|
+extern struct rmnet_nss_cb *rmnet_nss_callbacks __rcu __read_mostly;
|
+#endif
|
+#endif
|
+
|
+/* This driver supports wwan (3G/LTE/?) devices using a vendor
|
+ * specific management protocol called Qualcomm MSM Interface (QMI) -
|
+ * in addition to the more common AT commands over serial interface
|
+ * management
|
+ *
|
+ * QMI is wrapped in CDC, using CDC encapsulated commands on the
|
+ * control ("master") interface of a two-interface CDC Union
|
+ * resembling standard CDC ECM. The devices do not use the control
|
+ * interface for any other CDC messages. Most likely because the
|
+ * management protocol is used in place of the standard CDC
|
+ * notifications NOTIFY_NETWORK_CONNECTION and NOTIFY_SPEED_CHANGE
|
+ *
|
+ * Alternatively, control and data functions can be combined in a
|
+ * single USB interface.
|
+ *
|
+ * Handling a protocol like QMI is out of the scope for any driver.
|
+ * It is exported as a character device using the cdc-wdm driver as
|
+ * a subdriver, enabling userspace applications ("modem managers") to
|
+ * handle it.
|
+ *
|
+ * These devices may alternatively/additionally be configured using AT
|
+ * commands on a serial interface
|
+ */
|
+#define VERSION_NUMBER "V1.2.2"
|
+#define QUECTEL_WWAN_VERSION "Quectel_Linux&Android_QMI_WWAN_Driver_"VERSION_NUMBER
|
+static const char driver_name[] = "qmi_wwan_q";
|
+
|
+/* driver specific data */
|
+struct qmi_wwan_state {
|
+ struct usb_driver *subdriver;
|
+ atomic_t pmcount;
|
+ unsigned long unused;
|
+ struct usb_interface *control;
|
+ struct usb_interface *data;
|
+};
|
+
|
+/* default ethernet address used by the modem */
|
+static const u8 default_modem_addr[ETH_ALEN] = {0x02, 0x50, 0xf3};
|
+
|
+#if 1 //Added by Quectel
|
+/*
|
+ Quectel_WCDMA<E_Linux_USB_Driver_User_Guide_V1.9.pdf
|
+ 5.6. Test QMAP on GobiNet or QMI WWAN
|
+ 0 - no QMAP
|
+ 1 - QMAP (Aggregation protocol)
|
+ X - QMAP (Multiplexing and Aggregation protocol)
|
+*/
|
+#define QUECTEL_WWAN_QMAP 4 //MAX is 7
|
+
|
+#if defined(QUECTEL_WWAN_QMAP)
|
+#define QUECTEL_QMAP_MUX_ID 0x81
|
+
|
+static uint __read_mostly qmap_mode = 0;
|
+module_param( qmap_mode, uint, S_IRUGO);
|
+module_param_named( rx_qmap, qmap_mode, uint, S_IRUGO );
|
+#endif
|
+
|
+#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) || defined(CONFIG_BRIDGE_LAN)
|
+#define QUECTEL_BRIDGE_MODE
|
+#endif
|
+
|
+#ifdef QUECTEL_BRIDGE_MODE
|
+static uint __read_mostly bridge_mode = 0/*|BIT(1)*/;
|
+module_param( bridge_mode, uint, S_IRUGO );
|
+#endif
|
+
|
+#ifdef CONFIG_BRIDGE_LAN
|
+static const u8 broadcast_mac_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
+#endif
|
+
|
+//#define QMI_NETDEV_ONE_CARD_MODE
|
+static uint __read_mostly one_card_mode = 0;
|
+
|
+#if defined(QUECTEL_WWAN_QMAP)
|
+#define QUECTEL_UL_DATA_AGG 1
|
+
|
+#if defined(QUECTEL_UL_DATA_AGG)
|
+struct tx_agg_ctx {
|
+ /* QMIWDS_ADMIN_SET_DATA_FORMAT_RESP TLV_0x17 and TLV_0x18 */
|
+ uint ul_data_aggregation_max_datagrams; //UplinkDataAggregationMaxDatagramsTlv
|
+ uint ul_data_aggregation_max_size; //UplinkDataAggregationMaxSizeTlv
|
+ uint dl_minimum_padding; //0x1A
|
+};
|
+#endif
|
+
|
+typedef struct {
|
+ unsigned int size;
|
+ unsigned int rx_urb_size;
|
+ unsigned int ep_type;
|
+ unsigned int iface_id;
|
+ unsigned int qmap_mode;
|
+ unsigned int qmap_version;
|
+ unsigned int dl_minimum_padding;
|
+ char ifname[8][16];
|
+ unsigned char mux_id[8];
|
+} RMNET_INFO;
|
+
|
+typedef struct sQmiWwanQmap
|
+{
|
+ struct usbnet *mpNetDev;
|
+ struct driver_info driver_info;
|
+ atomic_t refcount;
|
+ struct net_device *mpQmapNetDev[QUECTEL_WWAN_QMAP];
|
+ uint link_state;
|
+ uint qmap_mode;
|
+ uint qmap_size;
|
+ uint qmap_version;
|
+
|
+#if defined(QUECTEL_UL_DATA_AGG)
|
+ struct tx_agg_ctx tx_ctx;
|
+ struct tasklet_struct txq;
|
+ struct tasklet_struct usbnet_bh;
|
+#endif
|
+
|
+#ifdef QUECTEL_BRIDGE_MODE
|
+ uint bridge_mode;
|
+ uint bridge_ipv4;
|
+ unsigned char bridge_mac[ETH_ALEN];
|
+#ifdef CONFIG_BRIDGE_LAN
|
+ unsigned char bridge_self_mac[ETH_ALEN];
|
+#endif
|
+#endif
|
+ uint use_rmnet_usb;
|
+ RMNET_INFO rmnet_info;
|
+} sQmiWwanQmap;
|
+
|
+#if LINUX_VERSION_CODE > KERNEL_VERSION(3,13,0) //8f84985fec10de64a6b4cdfea45f2b0ab8f07c78
|
+#define MHI_NETDEV_STATUS64
|
+#endif
|
+struct qmap_priv {
|
+ struct usbnet *dev;
|
+ struct net_device *real_dev;
|
+ struct net_device *self_dev;
|
+ u8 offset_id;
|
+ u8 mux_id;
|
+ u8 qmap_version; // 5~v1, 9~v5
|
+ u8 link_state;
|
+
|
+#if defined(MHI_NETDEV_STATUS64)
|
+ struct pcpu_sw_netstats __percpu *stats64;
|
+#endif
|
+
|
+ spinlock_t agg_lock;
|
+ struct sk_buff *agg_skb;
|
+ unsigned agg_count;
|
+ struct timespec64 agg_time;
|
+ struct hrtimer agg_hrtimer;
|
+ struct work_struct agg_wq;
|
+
|
+#ifdef QUECTEL_BRIDGE_MODE
|
+ uint bridge_mode;
|
+ uint bridge_ipv4;
|
+ unsigned char bridge_mac[ETH_ALEN];
|
+#ifdef CONFIG_BRIDGE_LAN
|
+ unsigned char bridge_self_mac[ETH_ALEN];
|
+#endif
|
+#endif
|
+ uint use_qca_nss;
|
+};
|
+
|
+struct qmap_hdr {
|
+ u8 cd_rsvd_pad;
|
+ u8 mux_id;
|
+ u16 pkt_len;
|
+} __packed;
|
+
|
+enum rmnet_map_v5_header_type {
|
+ RMNET_MAP_HEADER_TYPE_UNKNOWN,
|
+ RMNET_MAP_HEADER_TYPE_COALESCING = 0x1,
|
+ RMNET_MAP_HEADER_TYPE_CSUM_OFFLOAD = 0x2,
|
+ RMNET_MAP_HEADER_TYPE_ENUM_LENGTH
|
+};
|
+
|
+/* Main QMAP header */
|
+struct rmnet_map_header {
|
+#if defined(__LITTLE_ENDIAN_BITFIELD)
|
+ u8 pad_len:6;
|
+ u8 next_hdr:1;
|
+ u8 cd_bit:1;
|
+#elif defined (__BIG_ENDIAN_BITFIELD)
|
+ u8 cd_bit:1;
|
+ u8 next_hdr:1;
|
+ u8 pad_len:6;
|
+#else
|
+#error "Please fix <asm/byteorder.h>"
|
+#endif
|
+ u8 mux_id;
|
+ __be16 pkt_len;
|
+} __aligned(1);
|
+
|
+/* QMAP v5 headers */
|
+struct rmnet_map_v5_csum_header {
|
+#if defined(__LITTLE_ENDIAN_BITFIELD)
|
+ u8 next_hdr:1;
|
+ u8 header_type:7;
|
+ u8 hw_reserved:7;
|
+ u8 csum_valid_required:1;
|
+#elif defined (__BIG_ENDIAN_BITFIELD)
|
+ u8 header_type:7;
|
+ u8 next_hdr:1;
|
+ u8 csum_valid_required:1;
|
+ u8 hw_reserved:7;
|
+#else
|
+#error "Please fix <asm/byteorder.h>"
|
+#endif
|
+ __be16 reserved;
|
+} __aligned(1);
|
+
|
+#ifdef QUECTEL_BRIDGE_MODE
|
+static int is_qmap_netdev(const struct net_device *netdev);
|
+#endif
|
+#endif
|
+
|
+static const struct driver_info rmnet_usb_info;
|
+
|
+#ifdef QUECTEL_BRIDGE_MODE
|
+static int bridge_arp_reply(struct net_device *net, struct sk_buff *skb, uint bridge_ipv4) {
|
+ struct arphdr *parp;
|
+ u8 *arpptr, *sha;
|
+ u8 sip[4], tip[4], ipv4[4];
|
+ struct sk_buff *reply = NULL;
|
+
|
+ ipv4[0] = (bridge_ipv4 >> 24) & 0xFF;
|
+ ipv4[1] = (bridge_ipv4 >> 16) & 0xFF;
|
+ ipv4[2] = (bridge_ipv4 >> 8) & 0xFF;
|
+ ipv4[3] = (bridge_ipv4 >> 0) & 0xFF;
|
+
|
+ parp = arp_hdr(skb);
|
+
|
+ if (parp->ar_hrd == htons(ARPHRD_ETHER) && parp->ar_pro == htons(ETH_P_IP)
|
+ && parp->ar_op == htons(ARPOP_REQUEST) && parp->ar_hln == 6 && parp->ar_pln == 4) {
|
+ arpptr = (u8 *)parp + sizeof(struct arphdr);
|
+ sha = arpptr;
|
+ arpptr += net->addr_len; /* sha */
|
+ memcpy(sip, arpptr, sizeof(sip));
|
+ arpptr += sizeof(sip);
|
+ arpptr += net->addr_len; /* tha */
|
+ memcpy(tip, arpptr, sizeof(tip));
|
+
|
+ pr_info("%s sip = %d.%d.%d.%d, tip=%d.%d.%d.%d, ipv4=%d.%d.%d.%d\n", netdev_name(net),
|
+ sip[0], sip[1], sip[2], sip[3], tip[0], tip[1], tip[2], tip[3], ipv4[0], ipv4[1], ipv4[2], ipv4[3]);
|
+ //wwan0 sip = 10.151.137.255, tip=10.151.138.0, ipv4=10.151.137.255
|
+ if (tip[0] == ipv4[0] && tip[1] == ipv4[1] && (tip[2]&0xFC) == (ipv4[2]&0xFC) && tip[3] != ipv4[3])
|
+ reply = arp_create(ARPOP_REPLY, ETH_P_ARP, *((__be32 *)sip), net, *((__be32 *)tip), sha, default_modem_addr, sha);
|
+
|
+ if (reply) {
|
+ skb_reset_mac_header(reply);
|
+ __skb_pull(reply, skb_network_offset(reply));
|
+ reply->ip_summed = CHECKSUM_UNNECESSARY;
|
+ reply->pkt_type = PACKET_HOST;
|
+
|
+ netif_rx_ni(reply);
|
+ }
|
+ return 1;
|
+ }
|
+
|
+ return 0;
|
+}
|
+
|
+static struct sk_buff *bridge_mode_tx_fixup(struct net_device *net, struct sk_buff *skb, uint bridge_ipv4, unsigned char *bridge_mac) {
|
+ struct ethhdr *ehdr;
|
+ const struct iphdr *iph;
|
+
|
+ skb_reset_mac_header(skb);
|
+ ehdr = eth_hdr(skb);
|
+
|
+ if (ehdr->h_proto == htons(ETH_P_ARP)) {
|
+ if (bridge_ipv4)
|
+ bridge_arp_reply(net, skb, bridge_ipv4);
|
+ return NULL;
|
+ }
|
+
|
+ iph = ip_hdr(skb);
|
+ //DBG("iphdr: ");
|
+ //PrintHex((void *)iph, sizeof(struct iphdr));
|
+
|
+// 1 0.000000000 0.0.0.0 255.255.255.255 DHCP 362 DHCP Request - Transaction ID 0xe7643ad7
|
+ if (ehdr->h_proto == htons(ETH_P_IP) && iph->protocol == IPPROTO_UDP && iph->saddr == 0x00000000 && iph->daddr == 0xFFFFFFFF) {
|
+ //if (udp_hdr(skb)->dest == htons(67)) //DHCP Request
|
+ {
|
+ memcpy(bridge_mac, ehdr->h_source, ETH_ALEN);
|
+ pr_info("%s PC Mac Address: %02x:%02x:%02x:%02x:%02x:%02x\n", netdev_name(net),
|
+ bridge_mac[0], bridge_mac[1], bridge_mac[2], bridge_mac[3], bridge_mac[4], bridge_mac[5]);
|
+ }
|
+ }
|
+
|
+#ifdef CONFIG_BRIDGE_LAN
|
+ //bridge Lan IP 192.168.0.0
|
+ if (ehdr->h_proto == htons(ETH_P_IP) && (iph->daddr & 0xFFFF) == 0xA8C0)
|
+ {
|
+ struct sk_buff *reply = skb_copy(skb, GFP_ATOMIC);
|
+ ehdr = eth_hdr(reply);
|
+
|
+ memcpy(ehdr->h_source, default_modem_addr, ETH_ALEN);
|
+ if(is_qmap_netdev(net))
|
+ {
|
+ struct qmap_priv *priv = netdev_priv(net);
|
+ memcpy(ehdr->h_dest, priv->bridge_self_mac, ETH_ALEN);
|
+ }
|
+ else
|
+ {
|
+ struct usbnet * usbnetdev = netdev_priv(net);
|
+ struct qmi_wwan_state *info = (void *)&usbnetdev->data;
|
+ sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused;
|
+ memcpy(ehdr->h_dest, pQmapDev->bridge_self_mac, ETH_ALEN);
|
+ }
|
+
|
+ //pr_info("%s br rx pkt addr: %02x:%02x:%02x:%02x:%02x:%02x -> %02x:%02x:%02x:%02x:%02x:%02x\n", netdev_name(net),
|
+ // ehdr->h_source[0], ehdr->h_source[1], ehdr->h_source[2], ehdr->h_source[3], ehdr->h_source[4], ehdr->h_source[5],
|
+ // ehdr->h_dest[0], ehdr->h_dest[1], ehdr->h_dest[2], ehdr->h_dest[3], ehdr->h_dest[4], ehdr->h_dest[5]);
|
+
|
+ skb_reset_mac_header(reply);
|
+ __skb_pull(reply, skb_network_offset(reply));
|
+ reply->ip_summed = CHECKSUM_UNNECESSARY;
|
+ reply->pkt_type = PACKET_HOST;
|
+ netif_rx_ni(reply);
|
+ return NULL;
|
+ }
|
+#endif
|
+
|
+ if (memcmp(ehdr->h_source, bridge_mac, ETH_ALEN)) {
|
+ return NULL;
|
+ }
|
+
|
+ return skb;
|
+}
|
+
|
+static void bridge_mode_rx_fixup(sQmiWwanQmap *pQmapDev, struct net_device *net, struct sk_buff *skb) {
|
+ uint bridge_mode = 0;
|
+ unsigned char *bridge_mac;
|
+
|
+ if (pQmapDev->qmap_mode > 1 || pQmapDev->use_rmnet_usb == 1) {
|
+ struct qmap_priv *priv = netdev_priv(net);
|
+ bridge_mode = priv->bridge_mode;
|
+ bridge_mac = priv->bridge_mac;
|
+ }
|
+ else {
|
+ bridge_mode = pQmapDev->bridge_mode;
|
+ bridge_mac = pQmapDev->bridge_mac;
|
+ }
|
+
|
+ if (bridge_mode)
|
+ memcpy(eth_hdr(skb)->h_dest, bridge_mac, ETH_ALEN);
|
+ else
|
+ memcpy(eth_hdr(skb)->h_dest, net->dev_addr, ETH_ALEN);
|
+}
|
+#endif
|
+
|
+#if defined(QUECTEL_WWAN_QMAP)
|
+static ssize_t qmap_mode_show(struct device *dev, struct device_attribute *attr, char *buf) {
|
+ struct net_device *netdev = to_net_dev(dev);
|
+ struct usbnet * usbnetdev = netdev_priv( netdev );
|
+ struct qmi_wwan_state *info = (void *)&usbnetdev->data;
|
+ sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused;
|
+
|
+ return snprintf(buf, PAGE_SIZE, "%d\n", pQmapDev->qmap_mode);
|
+}
|
+
|
+static DEVICE_ATTR(qmap_mode, S_IRUGO, qmap_mode_show, NULL);
|
+
|
+static ssize_t qmap_size_show(struct device *dev, struct device_attribute *attr, char *buf) {
|
+ struct net_device *netdev = to_net_dev(dev);
|
+ struct usbnet * usbnetdev = netdev_priv( netdev );
|
+ struct qmi_wwan_state *info = (void *)&usbnetdev->data;
|
+ sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused;
|
+
|
+ return snprintf(buf, PAGE_SIZE, "%u\n", pQmapDev->qmap_size);
|
+}
|
+
|
+static DEVICE_ATTR(qmap_size, S_IRUGO, qmap_size_show, NULL);
|
+
|
+static ssize_t link_state_show(struct device *dev, struct device_attribute *attr, char *buf) {
|
+ struct net_device *netdev = to_net_dev(dev);
|
+ struct usbnet * usbnetdev = netdev_priv( netdev );
|
+ struct qmi_wwan_state *info = (void *)&usbnetdev->data;
|
+ sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused;
|
+
|
+ return snprintf(buf, PAGE_SIZE, "0x%x\n", pQmapDev->link_state);
|
+}
|
+
|
+static ssize_t link_state_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) {
|
+ struct net_device *netdev = to_net_dev(dev);
|
+ struct usbnet * usbnetdev = netdev_priv( netdev );
|
+ struct qmi_wwan_state *info = (void *)&usbnetdev->data;
|
+ sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused;
|
+ unsigned link_state = 0;
|
+ unsigned old_link = pQmapDev->link_state;
|
+ uint offset_id = 0;
|
+
|
+ link_state = simple_strtoul(buf, NULL, 0);
|
+
|
+ if (pQmapDev->qmap_mode == 1) {
|
+ pQmapDev->link_state = !!link_state;
|
+ }
|
+ else if (pQmapDev->qmap_mode > 1) {
|
+ offset_id = ((link_state&0x7F) - 1);
|
+
|
+ if (offset_id >= pQmapDev->qmap_mode) {
|
+ dev_info(dev, "%s offset_id is %d. but qmap_mode is %d\n", __func__, offset_id, pQmapDev->qmap_mode);
|
+ return count;
|
+ }
|
+
|
+ if (link_state&0x80)
|
+ pQmapDev->link_state &= ~(1 << offset_id);
|
+ else
|
+ pQmapDev->link_state |= (1 << offset_id);
|
+ }
|
+
|
+ if (old_link != pQmapDev->link_state) {
|
+ struct net_device *qmap_net = pQmapDev->mpQmapNetDev[offset_id];
|
+
|
+ if (usbnetdev->net->flags & IFF_UP) {
|
+ if (pQmapDev->link_state) {
|
+ netif_carrier_on(usbnetdev->net);
|
+ }
|
+ }
|
+
|
+ if (qmap_net && qmap_net != netdev) {
|
+ struct qmap_priv *priv = netdev_priv(qmap_net);
|
+
|
+ priv->link_state = !!(pQmapDev->link_state & (1 << offset_id));
|
+
|
+ if (qmap_net->flags & IFF_UP) {
|
+ if (priv->link_state) {
|
+ netif_carrier_on(qmap_net);
|
+ if (netif_queue_stopped(qmap_net) && !netif_queue_stopped(usbnetdev->net))
|
+ netif_wake_queue(qmap_net);
|
+ }
|
+ else {
|
+ netif_carrier_off(qmap_net);
|
+ }
|
+ }
|
+ }
|
+
|
+ if (usbnetdev->net->flags & IFF_UP) {
|
+ if (!pQmapDev->link_state) {
|
+ netif_carrier_off(usbnetdev->net);
|
+ }
|
+ }
|
+
|
+ dev_info(dev, "link_state 0x%x -> 0x%x\n", old_link, pQmapDev->link_state);
|
+ }
|
+
|
+ return count;
|
+}
|
+
|
+#ifdef QUECTEL_BRIDGE_MODE
|
+static ssize_t bridge_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) {
|
+ struct net_device *netdev = to_net_dev(dev);
|
+ uint old_mode = 0;
|
+ uint bridge_mode = simple_strtoul(buf, NULL, 0);
|
+
|
+ if (netdev->type != ARPHRD_ETHER) {
|
+ return count;
|
+ }
|
+
|
+ if (is_qmap_netdev(netdev)) {
|
+ struct qmap_priv *priv = netdev_priv(netdev);
|
+ old_mode = priv->bridge_mode;
|
+ priv->bridge_mode = bridge_mode;
|
+ }
|
+ else {
|
+ struct usbnet * usbnetdev = netdev_priv( netdev );
|
+ struct qmi_wwan_state *info = (void *)&usbnetdev->data;
|
+ sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused;
|
+ old_mode = pQmapDev->bridge_mode;
|
+ pQmapDev->bridge_mode = bridge_mode;
|
+ }
|
+
|
+ if (old_mode != bridge_mode) {
|
+ dev_info(dev, "bridge_mode change to 0x%x\n", bridge_mode);
|
+ }
|
+
|
+ return count;
|
+}
|
+
|
+static ssize_t bridge_mode_show(struct device *dev, struct device_attribute *attr, char *buf) {
|
+ struct net_device *netdev = to_net_dev(dev);
|
+ uint bridge_mode = 0;
|
+
|
+ if (is_qmap_netdev(netdev)) {
|
+ struct qmap_priv *priv = netdev_priv(netdev);
|
+ bridge_mode = priv->bridge_mode;
|
+ }
|
+ else {
|
+ struct usbnet * usbnetdev = netdev_priv( netdev );
|
+ struct qmi_wwan_state *info = (void *)&usbnetdev->data;
|
+ sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused;
|
+ bridge_mode = pQmapDev->bridge_mode;
|
+ }
|
+
|
+ return snprintf(buf, PAGE_SIZE, "%u\n", bridge_mode);
|
+}
|
+
|
+static ssize_t bridge_ipv4_show(struct device *dev, struct device_attribute *attr, char *buf) {
|
+ struct net_device *netdev = to_net_dev(dev);
|
+ unsigned int bridge_ipv4 = 0;
|
+ unsigned char ipv4[4];
|
+
|
+ if (is_qmap_netdev(netdev)) {
|
+ struct qmap_priv *priv = netdev_priv(netdev);
|
+ bridge_ipv4 = priv->bridge_ipv4;
|
+ }
|
+ else {
|
+ struct usbnet * usbnetdev = netdev_priv( netdev );
|
+ struct qmi_wwan_state *info = (void *)&usbnetdev->data;
|
+ sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused;
|
+ bridge_ipv4 = pQmapDev->bridge_ipv4;
|
+ }
|
+
|
+ ipv4[0] = (bridge_ipv4 >> 24) & 0xFF;
|
+ ipv4[1] = (bridge_ipv4 >> 16) & 0xFF;
|
+ ipv4[2] = (bridge_ipv4 >> 8) & 0xFF;
|
+ ipv4[3] = (bridge_ipv4 >> 0) & 0xFF;
|
+
|
+ return snprintf(buf, PAGE_SIZE, "%d.%d.%d.%d\n", ipv4[0], ipv4[1], ipv4[2], ipv4[3]);
|
+}
|
+
|
+static ssize_t bridge_ipv4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) {
|
+ struct net_device *netdev = to_net_dev(dev);
|
+
|
+ if (is_qmap_netdev(netdev)) {
|
+ struct qmap_priv *priv = netdev_priv(netdev);
|
+ priv->bridge_ipv4 = simple_strtoul(buf, NULL, 16);
|
+ }
|
+ else {
|
+ struct usbnet * usbnetdev = netdev_priv( netdev );
|
+ struct qmi_wwan_state *info = (void *)&usbnetdev->data;
|
+ sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused;
|
+ pQmapDev->bridge_ipv4 = simple_strtoul(buf, NULL, 16);
|
+ }
|
+
|
+ return count;
|
+}
|
+#endif
|
+
|
+static DEVICE_ATTR(link_state, S_IWUSR | S_IRUGO, link_state_show, link_state_store);
|
+#ifdef QUECTEL_BRIDGE_MODE
|
+static DEVICE_ATTR(bridge_mode, S_IWUSR | S_IRUGO, bridge_mode_show, bridge_mode_store);
|
+static DEVICE_ATTR(bridge_ipv4, S_IWUSR | S_IRUGO, bridge_ipv4_show, bridge_ipv4_store);
|
+#endif
|
+
|
+static struct attribute *qmi_wwan_sysfs_attrs[] = {
|
+ &dev_attr_link_state.attr,
|
+ &dev_attr_qmap_mode.attr,
|
+ &dev_attr_qmap_size.attr,
|
+#ifdef QUECTEL_BRIDGE_MODE
|
+ &dev_attr_bridge_mode.attr,
|
+ &dev_attr_bridge_ipv4.attr,
|
+#endif
|
+ NULL,
|
+};
|
+
|
+static struct attribute_group qmi_wwan_sysfs_attr_group = {
|
+ .attrs = qmi_wwan_sysfs_attrs,
|
+};
|
+
|
+#ifdef QUECTEL_BRIDGE_MODE
|
+static struct attribute *qmi_qmap_sysfs_attrs[] = {
|
+ &dev_attr_bridge_mode.attr,
|
+ &dev_attr_bridge_ipv4.attr,
|
+ NULL,
|
+};
|
+
|
+static struct attribute_group qmi_qmap_sysfs_attr_group = {
|
+ .attrs = qmi_qmap_sysfs_attrs,
|
+};
|
+#endif
|
+
|
+static int qmap_open(struct net_device *qmap_net)
|
+{
|
+ struct qmap_priv *priv = netdev_priv(qmap_net);
|
+ struct net_device *real_dev = priv->real_dev;
|
+
|
+ //printk("%s %s real_dev %d %d %d %d+++\n", __func__, dev->name,
|
+ // netif_carrier_ok(real_dev), netif_queue_stopped(real_dev), netif_carrier_ok(dev), netif_queue_stopped(dev));
|
+
|
+ if (!(priv->real_dev->flags & IFF_UP))
|
+ return -ENETDOWN;
|
+
|
+ if (priv->link_state) {
|
+ netif_carrier_on(real_dev);
|
+ netif_carrier_on(qmap_net);
|
+ if (netif_queue_stopped(qmap_net) && !netif_queue_stopped(real_dev))
|
+ netif_wake_queue(qmap_net);
|
+ }
|
+ //printk("%s %s real_dev %d %d %d %d---\n", __func__, dev->name,
|
+ // netif_carrier_ok(real_dev), netif_queue_stopped(real_dev), netif_carrier_ok(dev), netif_queue_stopped(dev));
|
+
|
+ return 0;
|
+}
|
+
|
+static int qmap_stop(struct net_device *qmap_net)
|
+{
|
+ //printk("%s %s %d %d+++\n", __func__, dev->name,
|
+ // netif_carrier_ok(dev), netif_queue_stopped(dev));
|
+
|
+ netif_carrier_off(qmap_net);
|
+ return 0;
|
+}
|
+
|
+static void qmap_wake_queue(sQmiWwanQmap *pQmapDev)
|
+{
|
+ uint i = 0;
|
+
|
+ if (!pQmapDev || !pQmapDev->use_rmnet_usb)
|
+ return;
|
+
|
+ for (i = 0; i < pQmapDev->qmap_mode; i++) {
|
+ struct net_device *qmap_net = pQmapDev->mpQmapNetDev[i];
|
+
|
+ if (qmap_net && netif_carrier_ok(qmap_net) && netif_queue_stopped(qmap_net)) {
|
+ netif_wake_queue(qmap_net);
|
+ }
|
+ }
|
+}
|
+
|
+static struct sk_buff * add_qhdr(struct sk_buff *skb, u8 mux_id) {
|
+ struct qmap_hdr *qhdr;
|
+ int pad = 0;
|
+
|
+ pad = skb->len%4;
|
+ if (pad) {
|
+ pad = 4 - pad;
|
+ if (skb_tailroom(skb) < pad) {
|
+ printk("skb_tailroom small!\n");
|
+ pad = 0;
|
+ }
|
+ if (pad)
|
+ __skb_put(skb, pad);
|
+ }
|
+
|
+ qhdr = (struct qmap_hdr *)skb_push(skb, sizeof(struct qmap_hdr));
|
+ qhdr->cd_rsvd_pad = pad;
|
+ qhdr->mux_id = mux_id;
|
+ qhdr->pkt_len = cpu_to_be16(skb->len - sizeof(struct qmap_hdr));
|
+
|
+ return skb;
|
+}
|
+
|
+static struct sk_buff * add_qhdr_v5(struct sk_buff *skb, u8 mux_id) {
|
+ struct rmnet_map_header *map_header;
|
+ struct rmnet_map_v5_csum_header *ul_header;
|
+ u32 padding, map_datalen;
|
+
|
+ map_datalen = skb->len;
|
+ padding = map_datalen%4;
|
+ if (padding) {
|
+ padding = 4 - padding;
|
+ if (skb_tailroom(skb) < padding) {
|
+ printk("skb_tailroom small!\n");
|
+ padding = 0;
|
+ }
|
+ if (padding)
|
+ __skb_put(skb, padding);
|
+ }
|
+
|
+ map_header = (struct rmnet_map_header *)skb_push(skb, (sizeof(struct rmnet_map_header) + sizeof(struct rmnet_map_v5_csum_header)));
|
+ map_header->cd_bit = 0;
|
+ map_header->next_hdr = 1;
|
+ map_header->pad_len = padding;
|
+ map_header->mux_id = mux_id;
|
+ map_header->pkt_len = htons(map_datalen + padding);
|
+
|
+ ul_header = (struct rmnet_map_v5_csum_header *)(map_header + 1);
|
+ memset(ul_header, 0, sizeof(*ul_header));
|
+ ul_header->header_type = RMNET_MAP_HEADER_TYPE_CSUM_OFFLOAD;
|
+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
|
+#if 0 //TODO
|
+ skb->ip_summed = CHECKSUM_NONE;
|
+ /* Ask for checksum offloading */
|
+ ul_header->csum_valid_required = 1;
|
+#endif
|
+ }
|
+
|
+ return skb;
|
+}
|
+
|
+static void rmnet_vnd_update_rx_stats(struct net_device *net,
|
+ unsigned rx_packets, unsigned rx_bytes) {
|
+#if defined(MHI_NETDEV_STATUS64)
|
+ struct qmap_priv *dev = netdev_priv(net);
|
+ struct pcpu_sw_netstats *stats64 = this_cpu_ptr(dev->stats64);
|
+
|
+ u64_stats_update_begin(&stats64->syncp);
|
+ stats64->rx_packets += rx_packets;
|
+ stats64->rx_bytes += rx_bytes;
|
+ u64_stats_update_end(&stats64->syncp);
|
+#else
|
+ net->stats.rx_packets += rx_packets;
|
+ net->stats.rx_bytes += rx_bytes;
|
+#endif
|
+}
|
+
|
+static void rmnet_vnd_update_tx_stats(struct net_device *net,
|
+ unsigned tx_packets, unsigned tx_bytes) {
|
+#if defined(MHI_NETDEV_STATUS64)
|
+ struct qmap_priv *dev = netdev_priv(net);
|
+ struct pcpu_sw_netstats *stats64 = this_cpu_ptr(dev->stats64);
|
+
|
+ u64_stats_update_begin(&stats64->syncp);
|
+ stats64->tx_packets += tx_packets;
|
+ stats64->tx_bytes += tx_bytes;
|
+ u64_stats_update_end(&stats64->syncp);
|
+#else
|
+ net->stats.tx_packets += tx_packets;
|
+ net->stats.tx_bytes += tx_bytes;
|
+#endif
|
+}
|
+
|
+#if defined(MHI_NETDEV_STATUS64)
|
+static struct rtnl_link_stats64 *_rmnet_vnd_get_stats64(struct net_device *net, struct rtnl_link_stats64 *stats)
|
+{
|
+ struct qmap_priv *dev = netdev_priv(net);
|
+ unsigned int start;
|
+ int cpu;
|
+
|
+ netdev_stats_to_stats64(stats, &net->stats);
|
+
|
+ if (nss_cb && dev->use_qca_nss) { // rmnet_nss.c:rmnet_nss_tx() will update rx stats
|
+ stats->rx_packets = 0;
|
+ stats->rx_bytes = 0;
|
+ }
|
+
|
+ for_each_possible_cpu(cpu) {
|
+ struct pcpu_sw_netstats *stats64;
|
+ u64 rx_packets, rx_bytes;
|
+ u64 tx_packets, tx_bytes;
|
+
|
+ stats64 = per_cpu_ptr(dev->stats64, cpu);
|
+
|
+ do {
|
+ start = u64_stats_fetch_begin_irq(&stats64->syncp);
|
+ rx_packets = stats64->rx_packets;
|
+ rx_bytes = stats64->rx_bytes;
|
+ tx_packets = stats64->tx_packets;
|
+ tx_bytes = stats64->tx_bytes;
|
+ } while (u64_stats_fetch_retry_irq(&stats64->syncp, start));
|
+
|
+ stats->rx_packets += rx_packets;
|
+ stats->rx_bytes += rx_bytes;
|
+ stats->tx_packets += tx_packets;
|
+ stats->tx_bytes += tx_bytes;
|
+ }
|
+
|
+ return stats;
|
+}
|
+
|
+#if (LINUX_VERSION_CODE > KERNEL_VERSION( 4,10,0 )) //bc1f44709cf27fb2a5766cadafe7e2ad5e9cb221
|
+static void rmnet_vnd_get_stats64(struct net_device *net, struct rtnl_link_stats64 *stats) {
|
+ _rmnet_vnd_get_stats64(net, stats);
|
+}
|
+#else
|
+static struct rtnl_link_stats64 *rmnet_vnd_get_stats64(struct net_device *net, struct rtnl_link_stats64 *stats) {
|
+ return _rmnet_vnd_get_stats64(net, stats);
|
+}
|
+#endif
|
+#endif
|
+
|
+#if defined(QUECTEL_UL_DATA_AGG)
|
+static void usbnet_bh(unsigned long data) {
|
+ sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)data;
|
+ struct tasklet_struct *t = &pQmapDev->usbnet_bh;
|
+ bool use_callback = false;
|
+
|
+#if (LINUX_VERSION_CODE > KERNEL_VERSION( 5,8,0 )) //c955e329bb9d44fab75cf2116542fcc0de0473c5
|
+ use_callback = t->use_callback;
|
+ if (use_callback)
|
+ t->callback(&pQmapDev->mpNetDev->bh);
|
+#endif
|
+
|
+ if (!use_callback)
|
+ t->func(t->data);
|
+
|
+ if (!netif_queue_stopped(pQmapDev->mpNetDev->net)) {
|
+ qmap_wake_queue((sQmiWwanQmap *)data);
|
+ }
|
+}
|
+
|
+static void rmnet_usb_tx_wake_queue(unsigned long data) {
|
+ qmap_wake_queue((sQmiWwanQmap *)data);
|
+}
|
+
|
+#if 0
|
+static void rmnet_usb_tx_skb_destructor(struct sk_buff *skb) {
|
+ struct net_device *net = skb->dev;
|
+ struct usbnet * dev = netdev_priv( net );
|
+ struct qmi_wwan_state *info = (void *)&dev->data;
|
+ sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused;
|
+
|
+ if (pQmapDev && pQmapDev->use_rmnet_usb) {
|
+ int i;
|
+
|
+ for (i = 0; i < pQmapDev->qmap_mode; i++) {
|
+ struct net_device *qmap_net = pQmapDev->mpQmapNetDev[i];
|
+
|
+ if (qmap_net && netif_carrier_ok(qmap_net) && netif_queue_stopped(qmap_net)) {
|
+ tasklet_schedule(&pQmapDev->txq);
|
+ break;
|
+ }
|
+ }
|
+ }
|
+}
|
+#endif
|
+
|
+static int rmnet_usb_tx_agg_skip(struct sk_buff *skb, int offset)
|
+{
|
+ u8 *packet_start = skb->data + offset;
|
+ int ready2send = 0;
|
+
|
+ if (skb->protocol == htons(ETH_P_IP)) {
|
+ struct iphdr *ip4h = (struct iphdr *)(packet_start);
|
+
|
+ if (ip4h->protocol == IPPROTO_TCP) {
|
+ const struct tcphdr *th = (const struct tcphdr *)(packet_start + sizeof(struct iphdr));
|
+ if (th->psh) {
|
+ ready2send = 1;
|
+ }
|
+ }
|
+ else if (ip4h->protocol == IPPROTO_ICMP)
|
+ ready2send = 1;
|
+
|
+ } else if (skb->protocol == htons(ETH_P_IPV6)) {
|
+ struct ipv6hdr *ip6h = (struct ipv6hdr *)(packet_start);
|
+
|
+ if (ip6h->nexthdr == NEXTHDR_TCP) {
|
+ const struct tcphdr *th = (const struct tcphdr *)(packet_start + sizeof(struct ipv6hdr));
|
+ if (th->psh) {
|
+ ready2send = 1;
|
+ }
|
+ } else if (ip6h->nexthdr == NEXTHDR_ICMP) {
|
+ ready2send = 1;
|
+ } else if (ip6h->nexthdr == NEXTHDR_FRAGMENT) {
|
+ struct frag_hdr *frag;
|
+
|
+ frag = (struct frag_hdr *)(packet_start
|
+ + sizeof(struct ipv6hdr));
|
+ if (frag->nexthdr == IPPROTO_ICMPV6)
|
+ ready2send = 1;
|
+ }
|
+ }
|
+
|
+ return ready2send;
|
+}
|
+
|
+static void rmnet_usb_tx_agg_work(struct work_struct *work)
|
+{
|
+ struct qmap_priv *priv =
|
+ container_of(work, struct qmap_priv, agg_wq);
|
+ struct sk_buff *skb = NULL;
|
+ unsigned long flags;
|
+
|
+ spin_lock_irqsave(&priv->agg_lock, flags);
|
+ if (likely(priv->agg_skb)) {
|
+ skb = priv->agg_skb;
|
+ priv->agg_skb = NULL;
|
+ priv->agg_count = 0;
|
+ skb->protocol = htons(ETH_P_MAP);
|
+ skb->dev = priv->real_dev;
|
+ ktime_get_ts64(&priv->agg_time);
|
+ }
|
+ spin_unlock_irqrestore(&priv->agg_lock, flags);
|
+
|
+ if (skb) {
|
+ int err;
|
+#if 0
|
+ if (!skb->destructor)
|
+ skb->destructor = rmnet_usb_tx_skb_destructor;
|
+#endif
|
+ err = dev_queue_xmit(skb);
|
+ if (err != NET_XMIT_SUCCESS) {
|
+ priv->self_dev->stats.tx_errors++;
|
+ }
|
+ }
|
+}
|
+
|
+static enum hrtimer_restart rmnet_usb_tx_agg_timer_cb(struct hrtimer *timer)
|
+{
|
+ struct qmap_priv *priv =
|
+ container_of(timer, struct qmap_priv, agg_hrtimer);
|
+
|
+ schedule_work(&priv->agg_wq);
|
+ return HRTIMER_NORESTART;
|
+}
|
+
|
+static long agg_time_limit __read_mostly = 1000000L; //reduce this time, can get better TPUT performance, but will increase USB interrupts
|
+module_param(agg_time_limit, long, S_IRUGO | S_IWUSR);
|
+MODULE_PARM_DESC(agg_time_limit, "Maximum time packets sit in the agg buf");
|
+
|
+static long agg_bypass_time __read_mostly = 10000000L;
|
+module_param(agg_bypass_time, long, S_IRUGO | S_IWUSR);
|
+MODULE_PARM_DESC(agg_bypass_time, "Skip agg when apart spaced more than this");
|
+
|
+static int rmnet_usb_tx_agg(struct sk_buff *skb, struct qmap_priv *priv) {
|
+ struct qmi_wwan_state *info = (void *)&priv->dev->data;
|
+ sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused;
|
+ struct tx_agg_ctx *ctx = &pQmapDev->tx_ctx;
|
+ int ready2send = 0;
|
+ int xmit_more = 0;
|
+ struct timespec64 diff, now;
|
+ struct sk_buff *agg_skb = NULL;
|
+ unsigned long flags;
|
+ int err;
|
+ struct net_device *pNet = priv->self_dev;
|
+
|
+#if LINUX_VERSION_CODE < KERNEL_VERSION(5,1,0) //6b16f9ee89b8d5709f24bc3ac89ae8b5452c0d7c
|
+#if LINUX_VERSION_CODE > KERNEL_VERSION(3,16,0)
|
+ xmit_more = skb->xmit_more;
|
+#endif
|
+#else
|
+ xmit_more = netdev_xmit_more();
|
+#endif
|
+
|
+ rmnet_vnd_update_tx_stats(pNet, 1, skb->len);
|
+
|
+ if (ctx->ul_data_aggregation_max_datagrams == 1) {
|
+ skb->protocol = htons(ETH_P_MAP);
|
+ skb->dev = priv->real_dev;
|
+#if 0
|
+ if (!skb->destructor)
|
+ skb->destructor = rmnet_usb_tx_skb_destructor;
|
+#endif
|
+ err = dev_queue_xmit(skb);
|
+ if (err != NET_XMIT_SUCCESS)
|
+ pNet->stats.tx_errors++;
|
+ return NET_XMIT_SUCCESS;
|
+ }
|
+
|
+new_packet:
|
+ spin_lock_irqsave(&priv->agg_lock, flags);
|
+ agg_skb = NULL;
|
+ ready2send = 0;
|
+ ktime_get_ts64(&now);
|
+ diff = timespec64_sub(now, priv->agg_time);
|
+
|
+ if (priv->agg_skb) {
|
+ if ((priv->agg_skb->len + skb->len) < ctx->ul_data_aggregation_max_size) {
|
+ memcpy(skb_put(priv->agg_skb, skb->len), skb->data, skb->len);
|
+ priv->agg_count++;
|
+
|
+ if (diff.tv_sec > 0 || diff.tv_nsec > agg_time_limit) {
|
+ ready2send = 1;
|
+ }
|
+ else if (priv->agg_count == ctx->ul_data_aggregation_max_datagrams) {
|
+ ready2send = 1;
|
+ }
|
+ else if (xmit_more == 0) {
|
+ struct rmnet_map_header *map_header = (struct rmnet_map_header *)skb->data;
|
+ size_t offset = sizeof(struct rmnet_map_header);
|
+ if (map_header->next_hdr)
|
+ offset += sizeof(struct rmnet_map_v5_csum_header);
|
+
|
+ ready2send = rmnet_usb_tx_agg_skip(skb, offset);
|
+ }
|
+
|
+ dev_kfree_skb_any(skb);
|
+ skb = NULL;
|
+ }
|
+ else {
|
+ ready2send = 1;
|
+ }
|
+
|
+ if (ready2send) {
|
+ agg_skb = priv->agg_skb;
|
+ priv->agg_skb = NULL;
|
+ priv->agg_count = 0;
|
+ }
|
+ }
|
+ else if (skb) {
|
+ if (diff.tv_sec > 0 || diff.tv_nsec > agg_bypass_time) {
|
+ ready2send = 1;
|
+ }
|
+ else if (xmit_more == 0) {
|
+ struct rmnet_map_header *map_header = (struct rmnet_map_header *)skb->data;
|
+ size_t offset = sizeof(struct rmnet_map_header);
|
+ if (map_header->next_hdr)
|
+ offset += sizeof(struct rmnet_map_v5_csum_header);
|
+
|
+ ready2send = rmnet_usb_tx_agg_skip(skb, offset);
|
+ }
|
+
|
+ if (ready2send == 0) {
|
+ priv->agg_skb = alloc_skb(ctx->ul_data_aggregation_max_size, GFP_ATOMIC);
|
+ if (priv->agg_skb) {
|
+ skb_reset_network_header(priv->agg_skb); //protocol da1a is buggy, dev wwan0
|
+ memcpy(skb_put(priv->agg_skb, skb->len), skb->data, skb->len);
|
+ priv->agg_count++;
|
+ dev_kfree_skb_any(skb);
|
+ skb = NULL;
|
+ }
|
+ else {
|
+ ready2send = 1;
|
+ }
|
+ }
|
+
|
+ if (ready2send) {
|
+ agg_skb = skb;
|
+ skb = NULL;
|
+ }
|
+ }
|
+
|
+ if (ready2send) {
|
+ priv->agg_time = now;
|
+ }
|
+ spin_unlock_irqrestore(&priv->agg_lock, flags);
|
+
|
+ if (agg_skb) {
|
+ agg_skb->protocol = htons(ETH_P_MAP);
|
+ agg_skb->dev = priv->real_dev;
|
+#if 0
|
+ if (!agg_skb->destructor)
|
+ agg_skb->destructor = rmnet_usb_tx_skb_destructor;
|
+#endif
|
+ err = dev_queue_xmit(agg_skb);
|
+ if (err != NET_XMIT_SUCCESS) {
|
+ pNet->stats.tx_errors++;
|
+ }
|
+ }
|
+
|
+ if (skb) {
|
+ goto new_packet;
|
+ }
|
+
|
+ if (priv->agg_skb) {
|
+ if (!hrtimer_is_queued(&priv->agg_hrtimer))
|
+ hrtimer_start(&priv->agg_hrtimer, ns_to_ktime(NSEC_PER_MSEC * 2), HRTIMER_MODE_REL);
|
+ }
|
+
|
+ return NET_XMIT_SUCCESS;
|
+}
|
+#endif
|
+
|
+static netdev_tx_t rmnet_vnd_start_xmit(struct sk_buff *skb,
|
+ struct net_device *pNet)
|
+{
|
+ int err;
|
+ struct qmap_priv *priv = netdev_priv(pNet);
|
+
|
+ if (netif_queue_stopped(priv->real_dev)) {
|
+ netif_stop_queue(pNet);
|
+ return NETDEV_TX_BUSY;
|
+ }
|
+
|
+ //printk("%s 1 skb=%p, len=%d, protocol=%x, hdr_len=%d\n", __func__, skb, skb->len, skb->protocol, skb->hdr_len);
|
+ if (pNet->type == ARPHRD_ETHER) {
|
+ skb_reset_mac_header(skb);
|
+
|
+#ifdef QUECTEL_BRIDGE_MODE
|
+ if (priv->bridge_mode && bridge_mode_tx_fixup(pNet, skb, priv->bridge_ipv4, priv->bridge_mac) == NULL) {
|
+ dev_kfree_skb_any (skb);
|
+ return NETDEV_TX_OK;
|
+ }
|
+#endif
|
+
|
+ if (skb_pull(skb, ETH_HLEN) == NULL) {
|
+ dev_kfree_skb_any (skb);
|
+ return NETDEV_TX_OK;
|
+ }
|
+ }
|
+ //printk("%s 2 skb=%p, len=%d, protocol=%x, hdr_len=%d\n", __func__, skb, skb->len, skb->protocol, skb->hdr_len);
|
+
|
+ if (priv->qmap_version == 5) {
|
+ add_qhdr(skb, priv->mux_id);
|
+ }
|
+ else if (priv->qmap_version == 9) {
|
+ add_qhdr_v5(skb, priv->mux_id);
|
+ }
|
+ else {
|
+ dev_kfree_skb_any (skb);
|
+ return NETDEV_TX_OK;
|
+ }
|
+ //printk("%s skb=%p, len=%d, protocol=%x, hdr_len=%d\n", __func__, skb, skb->len, skb->protocol, skb->hdr_len);
|
+
|
+ err = rmnet_usb_tx_agg(skb, priv);
|
+
|
+ return err;
|
+}
|
+
|
+static int rmnet_vnd_change_mtu(struct net_device *rmnet_dev, int new_mtu)
|
+{
|
+ if (new_mtu < 0)
|
+ return -EINVAL;
|
+
|
+ if (new_mtu > 1500)
|
+ printk("warning, set mtu greater than 1500, %d\n", new_mtu);
|
+
|
+ rmnet_dev->mtu = new_mtu;
|
+ return 0;
|
+}
|
+
|
+/* drivers may override default ethtool_ops in their bind() routine */
|
+static const struct ethtool_ops rmnet_vnd_ethtool_ops = {
|
+ .get_link = ethtool_op_get_link,
|
+};
|
+
|
+static const struct net_device_ops rmnet_vnd_ops = {
|
+ .ndo_open = qmap_open,
|
+ .ndo_stop = qmap_stop,
|
+ .ndo_start_xmit = rmnet_vnd_start_xmit,
|
+ .ndo_change_mtu = rmnet_vnd_change_mtu,
|
+#if defined(MHI_NETDEV_STATUS64)
|
+ .ndo_get_stats64 = rmnet_vnd_get_stats64,
|
+#endif
|
+};
|
+
|
+static void rmnet_usb_ether_setup(struct net_device *rmnet_dev)
|
+{
|
+ ether_setup(rmnet_dev);
|
+
|
+ rmnet_dev->flags |= IFF_NOARP;
|
+ rmnet_dev->flags &= ~(IFF_BROADCAST | IFF_MULTICAST);
|
+
|
+#if LINUX_VERSION_CODE > KERNEL_VERSION(4,10,0)
|
+ rmnet_dev->max_mtu = 65535;
|
+#endif
|
+
|
+ rmnet_dev->ethtool_ops = &rmnet_vnd_ethtool_ops;
|
+ rmnet_dev->netdev_ops = &rmnet_vnd_ops;
|
+}
|
+
|
+static void rmnet_usb_rawip_setup(struct net_device *rmnet_dev)
|
+{
|
+ rmnet_dev->needed_headroom = 16;
|
+
|
+ /* Raw IP mode */
|
+ rmnet_dev->header_ops = NULL; /* No header */
|
+ rmnet_dev->type = ARPHRD_RAWIP;
|
+ rmnet_dev->hard_header_len = 0;
|
+ rmnet_dev->flags |= IFF_NOARP;
|
+ rmnet_dev->flags &= ~(IFF_BROADCAST | IFF_MULTICAST);
|
+
|
+ rmnet_dev->ethtool_ops = &rmnet_vnd_ethtool_ops;
|
+ rmnet_dev->netdev_ops = &rmnet_vnd_ops;
|
+}
|
+
|
+static rx_handler_result_t qca_nss_rx_handler(struct sk_buff **pskb)
|
+{
|
+ struct sk_buff *skb = *pskb;
|
+
|
+ if (!skb)
|
+ return RX_HANDLER_CONSUMED;
|
+
|
+ //printk("%s skb=%p, len=%d, protocol=%x, hdr_len=%d\n", __func__, skb, skb->len, skb->protocol, skb->hdr_len);
|
+
|
+ if (skb->pkt_type == PACKET_LOOPBACK)
|
+ return RX_HANDLER_PASS;
|
+
|
+ /* Check this so that we dont loop around netif_receive_skb */
|
+ if (skb->cb[0] == 1) {
|
+ skb->cb[0] = 0;
|
+
|
+ return RX_HANDLER_PASS;
|
+ }
|
+
|
+ if (nss_cb) {
|
+ nss_cb->nss_tx(skb);
|
+ return RX_HANDLER_CONSUMED;
|
+ }
|
+
|
+ return RX_HANDLER_PASS;
|
+}
|
+
|
+static int qmap_register_device(sQmiWwanQmap * pDev, u8 offset_id)
|
+{
|
+ struct net_device *real_dev = pDev->mpNetDev->net;
|
+ struct net_device *qmap_net;
|
+ struct qmap_priv *priv;
|
+ int err;
|
+ char name[IFNAMSIZ];
|
+ int use_qca_nss = !!nss_cb;
|
+
|
+ sprintf(name, "%s_%d", real_dev->name, offset_id + 1);
|
+#ifdef NET_NAME_UNKNOWN
|
+ qmap_net = alloc_netdev(sizeof(struct qmap_priv), name,
|
+ NET_NAME_UNKNOWN, rmnet_usb_ether_setup);
|
+#else
|
+ qmap_net = alloc_netdev(sizeof(struct qmap_priv), name,
|
+ rmnet_usb_ether_setup);
|
+#endif
|
+ if (!qmap_net)
|
+ return -ENOBUFS;
|
+
|
+ SET_NETDEV_DEV(qmap_net, &real_dev->dev);
|
+ priv = netdev_priv(qmap_net);
|
+ priv->offset_id = offset_id;
|
+ priv->real_dev = real_dev;
|
+ priv->self_dev = qmap_net;
|
+ priv->dev = pDev->mpNetDev;
|
+ priv->qmap_version = pDev->qmap_version;
|
+ priv->mux_id = QUECTEL_QMAP_MUX_ID + offset_id;
|
+ memcpy (qmap_net->dev_addr, real_dev->dev_addr, ETH_ALEN);
|
+
|
+#ifdef QUECTEL_BRIDGE_MODE
|
+ priv->bridge_mode = !!(pDev->bridge_mode & BIT(offset_id));
|
+ qmap_net->sysfs_groups[0] = &qmi_qmap_sysfs_attr_group;
|
+ if (priv->bridge_mode)
|
+ use_qca_nss = 0;
|
+#ifdef CONFIG_BRIDGE_LAN
|
+ memcpy(priv->bridge_self_mac, broadcast_mac_addr, ETH_ALEN);
|
+#endif
|
+#endif
|
+
|
+ if (nss_cb && use_qca_nss) {
|
+ rmnet_usb_rawip_setup(qmap_net);
|
+ }
|
+
|
+ priv->agg_skb = NULL;
|
+ priv->agg_count = 0;
|
+ hrtimer_init(&priv->agg_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
+ priv->agg_hrtimer.function = rmnet_usb_tx_agg_timer_cb;
|
+ INIT_WORK(&priv->agg_wq, rmnet_usb_tx_agg_work);
|
+ ktime_get_ts64(&priv->agg_time);
|
+ spin_lock_init(&priv->agg_lock);
|
+ priv->use_qca_nss = 0;
|
+
|
+#if defined(MHI_NETDEV_STATUS64)
|
+ priv->stats64 = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
|
+ if (!priv->stats64) {
|
+ err = -ENOBUFS;
|
+ goto out_free_newdev;
|
+ }
|
+#endif
|
+
|
+ err = register_netdev(qmap_net);
|
+ if (err)
|
+ dev_info(&real_dev->dev, "%s(%s)=%d\n", __func__, qmap_net->name, err);
|
+ if (err < 0)
|
+ goto out_free_newdev;
|
+ netif_device_attach (qmap_net);
|
+ netif_carrier_off(qmap_net);
|
+
|
+ if (nss_cb && use_qca_nss) {
|
+ int rc = nss_cb->nss_create(qmap_net);
|
+ if (rc) {
|
+ /* Log, but don't fail the device creation */
|
+ netdev_err(qmap_net, "Device will not use NSS path: %d\n", rc);
|
+ } else {
|
+ priv->use_qca_nss = 1;
|
+ netdev_info(qmap_net, "NSS context created\n");
|
+ rtnl_lock();
|
+ netdev_rx_handler_register(qmap_net, qca_nss_rx_handler, NULL);
|
+ rtnl_unlock();
|
+ }
|
+ }
|
+
|
+ strcpy(pDev->rmnet_info.ifname[offset_id], qmap_net->name);
|
+ pDev->rmnet_info.mux_id[offset_id] = priv->mux_id;
|
+
|
+ pDev->mpQmapNetDev[offset_id] = qmap_net;
|
+
|
+ dev_info(&real_dev->dev, "%s %s\n", __func__, qmap_net->name);
|
+
|
+ return 0;
|
+
|
+out_free_newdev:
|
+ free_netdev(qmap_net);
|
+ return err;
|
+}
|
+
|
+static void qmap_unregister_device(sQmiWwanQmap * pDev, u8 offset_id) {
|
+ struct net_device *qmap_net = pDev->mpQmapNetDev[offset_id];
|
+
|
+ if (qmap_net != NULL && qmap_net != pDev->mpNetDev->net) {
|
+ struct qmap_priv *priv = netdev_priv(qmap_net);
|
+ unsigned long flags;
|
+
|
+ pr_info("qmap_unregister_device(%s)\n", qmap_net->name);
|
+ pDev->mpQmapNetDev[offset_id] = NULL;
|
+ netif_carrier_off( qmap_net );
|
+ netif_stop_queue( qmap_net );
|
+
|
+ hrtimer_cancel(&priv->agg_hrtimer);
|
+ cancel_work_sync(&priv->agg_wq);
|
+ spin_lock_irqsave(&priv->agg_lock, flags);
|
+ if (priv->agg_skb) {
|
+ kfree_skb(priv->agg_skb);
|
+ }
|
+ spin_unlock_irqrestore(&priv->agg_lock, flags);
|
+
|
+ if (nss_cb && priv->use_qca_nss) {
|
+ rtnl_lock();
|
+ netdev_rx_handler_unregister(qmap_net);
|
+ rtnl_unlock();
|
+ nss_cb->nss_free(qmap_net);
|
+ }
|
+
|
+#if defined(MHI_NETDEV_STATUS64)
|
+ free_percpu(priv->stats64);
|
+#endif
|
+ unregister_netdev (qmap_net);
|
+ free_netdev(qmap_net);
|
+ }
|
+}
|
+
|
+typedef struct {
|
+ unsigned int size;
|
+ unsigned int rx_urb_size;
|
+ unsigned int ep_type;
|
+ unsigned int iface_id;
|
+ unsigned int MuxId;
|
+ unsigned int ul_data_aggregation_max_datagrams; //0x17
|
+ unsigned int ul_data_aggregation_max_size ;//0x18
|
+ unsigned int dl_minimum_padding; //0x1A
|
+} QMAP_SETTING;
|
+
|
+#ifdef CONFIG_BRIDGE_LAN
|
+typedef struct {
|
+ u8 id;
|
+ u8 brmac[ETH_ALEN];
|
+} BRMAC_SETTING;
|
+#endif
|
+
|
+int qma_setting_store(struct device *dev, QMAP_SETTING *qmap_settings, size_t size) {
|
+ struct net_device *netdev = to_net_dev(dev);
|
+ struct usbnet * usbnetdev = netdev_priv( netdev );
|
+ struct qmi_wwan_state *info = (void *)&usbnetdev->data;
|
+ sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused;
|
+
|
+ if (qmap_settings->size != size) {
|
+ dev_err(dev, "ERROR: qmap_settings.size donot match!\n");
|
+ return -EOPNOTSUPP;
|
+ }
|
+
|
+#ifdef QUECTEL_UL_DATA_AGG
|
+ netif_tx_lock_bh(netdev);
|
+ if (pQmapDev->tx_ctx.ul_data_aggregation_max_datagrams == 1 && qmap_settings->ul_data_aggregation_max_datagrams > 1) {
|
+ pQmapDev->tx_ctx.ul_data_aggregation_max_datagrams = qmap_settings->ul_data_aggregation_max_datagrams;
|
+ pQmapDev->tx_ctx.ul_data_aggregation_max_size = qmap_settings->ul_data_aggregation_max_size;
|
+ pQmapDev->tx_ctx.dl_minimum_padding = qmap_settings->dl_minimum_padding;
|
+ dev_info(dev, "ul_data_aggregation_max_datagrams=%d, ul_data_aggregation_max_size=%d, dl_minimum_padding=%d\n",
|
+ pQmapDev->tx_ctx.ul_data_aggregation_max_datagrams,
|
+ pQmapDev->tx_ctx.ul_data_aggregation_max_size,
|
+ pQmapDev->tx_ctx.dl_minimum_padding);
|
+ }
|
+ netif_tx_unlock_bh(netdev);
|
+ return 0;
|
+#endif
|
+
|
+ return -EOPNOTSUPP;
|
+}
|
+
|
+static int qmap_ndo_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) {
|
+ struct usbnet * usbnetdev = netdev_priv( dev );
|
+ struct qmi_wwan_state *info = (void *)&usbnetdev->data;
|
+ sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused;
|
+ int rc = -EOPNOTSUPP;
|
+ uint link_state = 0;
|
+ QMAP_SETTING qmap_settings = {0};
|
+#ifdef CONFIG_BRIDGE_LAN
|
+ BRMAC_SETTING brmac_settings = {0};
|
+#endif
|
+
|
+ switch (cmd) {
|
+ case 0x89F1: //SIOCDEVPRIVATE
|
+ rc = copy_from_user(&link_state, ifr->ifr_ifru.ifru_data, sizeof(link_state));
|
+ if (!rc) {
|
+ char buf[32];
|
+ snprintf(buf, sizeof(buf), "%u", link_state);
|
+ link_state_store(&dev->dev, NULL, buf, strlen(buf));
|
+ }
|
+ break;
|
+
|
+ case 0x89F2: //SIOCDEVPRIVATE
|
+ rc = copy_from_user(&qmap_settings, ifr->ifr_ifru.ifru_data, sizeof(qmap_settings));
|
+ if (!rc) {
|
+ rc = qma_setting_store(&dev->dev, &qmap_settings, sizeof(qmap_settings));
|
+ }
|
+ break;
|
+
|
+ case 0x89F3: //SIOCDEVPRIVATE
|
+ if (pQmapDev->use_rmnet_usb) {
|
+ uint i;
|
+
|
+ for (i = 0; i < pQmapDev->qmap_mode; i++) {
|
+ struct net_device *qmap_net = pQmapDev->mpQmapNetDev[i];
|
+
|
+ if (!qmap_net)
|
+ break;
|
+
|
+ strcpy(pQmapDev->rmnet_info.ifname[i], qmap_net->name);
|
+ }
|
+ rc = copy_to_user(ifr->ifr_ifru.ifru_data, &pQmapDev->rmnet_info, sizeof(pQmapDev->rmnet_info));
|
+ }
|
+ break;
|
+
|
+#ifdef CONFIG_BRIDGE_LAN
|
+ case 0x89F4: //SIOCDEVPRIVATE
|
+ rc = copy_from_user(&brmac_settings, ifr->ifr_ifru.ifru_data, sizeof(brmac_settings));
|
+ if (pQmapDev->use_rmnet_usb && brmac_settings.id < qmap_mode) {
|
+ struct net_device *qmap_net = pQmapDev->mpQmapNetDev[brmac_settings.id];
|
+ struct qmap_priv *priv = netdev_priv(qmap_net);
|
+ memcpy(priv->bridge_self_mac, brmac_settings.brmac, ETH_ALEN);
|
+ pr_info("ioctl 0x89F4 change qmapnet bridge(%d) lan mac -> %02x:%02x:%02x:%02x:%02x:%02x\n", brmac_settings.id, priv->bridge_self_mac[0],
|
+ priv->bridge_self_mac[1], priv->bridge_self_mac[2], priv->bridge_self_mac[3], priv->bridge_self_mac[4], priv->bridge_self_mac[5]);
|
+ }
|
+ else if (!pQmapDev->use_rmnet_usb && brmac_settings.id == 0) {
|
+ memcpy(pQmapDev->bridge_self_mac, brmac_settings.brmac, ETH_ALEN);
|
+ pr_info("ioctl 0x89F4 change usbnet bridge(%d) lan mac -> %02x:%02x:%02x:%02x:%02x:%02x\n", brmac_settings.id, pQmapDev->bridge_self_mac[0],
|
+ pQmapDev->bridge_self_mac[1], pQmapDev->bridge_self_mac[2], pQmapDev->bridge_self_mac[3], pQmapDev->bridge_self_mac[4], pQmapDev->bridge_self_mac[5]);
|
+ }
|
+ else {
|
+ pr_info("ioctl 0x89F4 change bridge(%d) lan mac -> error id\n", brmac_settings.id);
|
+ rc = -1;
|
+ }
|
+ break;
|
+#endif
|
+
|
+ default:
|
+ break;
|
+ }
|
+
|
+ return rc;
|
+}
|
+
|
+#ifdef QUECTEL_BRIDGE_MODE
|
+static int is_qmap_netdev(const struct net_device *netdev) {
|
+ return netdev->netdev_ops == &rmnet_vnd_ops;
|
+}
|
+#endif
|
+#endif
|
+
|
+static struct sk_buff *qmi_wwan_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) {
|
+ //MDM9x07,MDM9628,MDM9x40,SDX20,SDX24 only work on RAW IP mode
|
+ if ((dev->driver_info->flags & FLAG_NOARP) == 0)
|
+ return skb;
|
+
|
+ // Skip Ethernet header from message
|
+ if (dev->net->hard_header_len == 0)
|
+ return skb;
|
+ else
|
+ skb_reset_mac_header(skb);
|
+
|
+#ifdef QUECTEL_BRIDGE_MODE
|
+{
|
+ struct qmi_wwan_state *info = (void *)&dev->data;
|
+ sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused;
|
+
|
+ if (pQmapDev->bridge_mode && bridge_mode_tx_fixup(dev->net, skb, pQmapDev->bridge_ipv4, pQmapDev->bridge_mac) == NULL) {
|
+ dev_kfree_skb_any (skb);
|
+ return NULL;
|
+ }
|
+}
|
+#endif
|
+
|
+ if (skb_pull(skb, ETH_HLEN)) {
|
+ return skb;
|
+ } else {
|
+ dev_err(&dev->intf->dev, "Packet Dropped ");
|
+ }
|
+
|
+ // Filter the packet out, release it
|
+ dev_kfree_skb_any(skb);
|
+ return NULL;
|
+}
|
+#endif
|
+
|
+/* Make up an ethernet header if the packet doesn't have one.
|
+ *
|
+ * A firmware bug common among several devices cause them to send raw
|
+ * IP packets under some circumstances. There is no way for the
|
+ * driver/host to know when this will happen. And even when the bug
|
+ * hits, some packets will still arrive with an intact header.
|
+ *
|
+ * The supported devices are only capably of sending IPv4, IPv6 and
|
+ * ARP packets on a point-to-point link. Any packet with an ethernet
|
+ * header will have either our address or a broadcast/multicast
|
+ * address as destination. ARP packets will always have a header.
|
+ *
|
+ * This means that this function will reliably add the appropriate
|
+ * header iff necessary, provided our hardware address does not start
|
+ * with 4 or 6.
|
+ *
|
+ * Another common firmware bug results in all packets being addressed
|
+ * to 00:a0:c6:00:00:00 despite the host address being different.
|
+ * This function will also fixup such packets.
|
+ */
|
+static int qmi_wwan_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
|
+{
|
+ __be16 proto;
|
+
|
+ /* This check is no longer done by usbnet */
|
+ if (skb->len < dev->net->hard_header_len)
|
+ return 0;
|
+
|
+ switch (skb->data[0] & 0xf0) {
|
+ case 0x40:
|
+ proto = htons(ETH_P_IP);
|
+ break;
|
+ case 0x60:
|
+ proto = htons(ETH_P_IPV6);
|
+ break;
|
+ case 0x00:
|
+ if (is_multicast_ether_addr(skb->data))
|
+ return 1;
|
+ /* possibly bogus destination - rewrite just in case */
|
+ skb_reset_mac_header(skb);
|
+ goto fix_dest;
|
+ default:
|
+ /* pass along other packets without modifications */
|
+ return 1;
|
+ }
|
+ if (skb_headroom(skb) < ETH_HLEN)
|
+ return 0;
|
+ skb_push(skb, ETH_HLEN);
|
+ skb_reset_mac_header(skb);
|
+ eth_hdr(skb)->h_proto = proto;
|
+ memset(eth_hdr(skb)->h_source, 0, ETH_ALEN);
|
+#if 1 //Added by Quectel
|
+ //some kernel will drop ethernet packet which's souce mac is all zero
|
+ memcpy(eth_hdr(skb)->h_source, default_modem_addr, ETH_ALEN);
|
+#endif
|
+
|
+fix_dest:
|
+#ifdef QUECTEL_BRIDGE_MODE
|
+{
|
+ struct qmi_wwan_state *info = (void *)&dev->data;
|
+ sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused;
|
+ bridge_mode_rx_fixup(pQmapDev, dev->net, skb);
|
+}
|
+#else
|
+ memcpy(eth_hdr(skb)->h_dest, dev->net->dev_addr, ETH_ALEN);
|
+#endif
|
+
|
+ return 1;
|
+}
|
+
|
+#if defined(QUECTEL_WWAN_QMAP)
|
+static struct sk_buff *qmap_qmi_wwan_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) {
|
+ struct qmi_wwan_state *info = (void *)&dev->data;
|
+ sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused;
|
+
|
+ if (unlikely(pQmapDev == NULL)) {
|
+ goto drop_skb;
|
+ } else if (unlikely(pQmapDev->qmap_mode && !pQmapDev->link_state)) {
|
+ dev_dbg(&dev->net->dev, "link_state 0x%x, drop skb, len = %u\n", pQmapDev->link_state, skb->len);
|
+ goto drop_skb;
|
+ } else if (pQmapDev->qmap_mode == 0) {
|
+ skb = qmi_wwan_tx_fixup(dev, skb, flags);
|
+ }
|
+ else if (pQmapDev->qmap_mode > 1) {
|
+ WARN_ON(1); //never reach here.
|
+ }
|
+ else {
|
+ if (likely(skb)) {
|
+ skb = qmi_wwan_tx_fixup(dev, skb, flags);
|
+
|
+ if (skb) {
|
+ if(pQmapDev->qmap_version == 5)
|
+ add_qhdr(skb, QUECTEL_QMAP_MUX_ID);
|
+ else
|
+ add_qhdr_v5(skb, QUECTEL_QMAP_MUX_ID);
|
+ }
|
+ else {
|
+ return NULL;
|
+ }
|
+ }
|
+ }
|
+
|
+ return skb;
|
+drop_skb:
|
+ dev_kfree_skb_any (skb);
|
+ return NULL;
|
+}
|
+
|
+static void qmap_packet_decode(sQmiWwanQmap *pQmapDev,
|
+ struct sk_buff *skb_in, struct sk_buff_head *skb_chain)
|
+{
|
+ struct device *dev = &pQmapDev->mpNetDev->net->dev;
|
+ struct sk_buff *qmap_skb;
|
+ uint dl_minimum_padding = 0;
|
+
|
+ if (pQmapDev->qmap_version == 9)
|
+ dl_minimum_padding = pQmapDev->tx_ctx.dl_minimum_padding;
|
+
|
+ /* __skb_queue_head_init() do not call spin_lock_init(&list->lock),
|
+ so should not call skb_queue_tail/queue later. */
|
+ __skb_queue_head_init(skb_chain);
|
+
|
+ while (skb_in->len > sizeof(struct qmap_hdr)) {
|
+ struct rmnet_map_header *map_header = (struct rmnet_map_header *)skb_in->data;
|
+ struct rmnet_map_v5_csum_header *ul_header = NULL;
|
+ size_t hdr_size = sizeof(struct rmnet_map_header);
|
+ struct net_device *qmap_net;
|
+ int pkt_len = ntohs(map_header->pkt_len);
|
+ int skb_len;
|
+ __be16 protocol;
|
+ int mux_id;
|
+ int skip_nss = 0;
|
+
|
+ if (map_header->next_hdr) {
|
+ ul_header = (struct rmnet_map_v5_csum_header *)(map_header + 1);
|
+ hdr_size += sizeof(struct rmnet_map_v5_csum_header);
|
+ }
|
+
|
+ skb_len = pkt_len - (map_header->pad_len&0x3F);
|
+ skb_len -= dl_minimum_padding;
|
+
|
+ mux_id = map_header->mux_id - QUECTEL_QMAP_MUX_ID;
|
+ if (mux_id >= pQmapDev->qmap_mode) {
|
+ dev_info(dev, "drop qmap unknow mux_id %x\n", map_header->mux_id);
|
+ goto error_pkt;
|
+ }
|
+
|
+ qmap_net = pQmapDev->mpQmapNetDev[mux_id];
|
+ if (qmap_net == NULL) {
|
+ dev_info(dev, "drop qmap unknow mux_id %x\n", map_header->mux_id);
|
+ goto skip_pkt;
|
+ }
|
+
|
+ if (skb_len > qmap_net->mtu) {
|
+ dev_info(dev, "drop skb_len=%x larger than mtu=%d\n", skb_len, qmap_net->mtu);
|
+ goto error_pkt;
|
+ }
|
+
|
+ if (skb_in->len < (pkt_len + hdr_size)) {
|
+ dev_info(dev, "drop qmap unknow pkt, len=%d, pkt_len=%d\n", skb_in->len, pkt_len);
|
+ goto error_pkt;
|
+ }
|
+
|
+ if (map_header->cd_bit) {
|
+ dev_info(dev, "skip qmap command packet\n");
|
+ goto skip_pkt;
|
+ }
|
+
|
+ switch (skb_in->data[hdr_size] & 0xf0) {
|
+ case 0x40:
|
+#ifdef CONFIG_QCA_NSS_PACKET_FILTER
|
+ {
|
+ struct iphdr *ip4h = (struct iphdr *)(&skb_in->data[hdr_size]);
|
+ if (ip4h->protocol == IPPROTO_ICMP) {
|
+ skip_nss = 1;
|
+ }
|
+ }
|
+#endif
|
+ protocol = htons(ETH_P_IP);
|
+ break;
|
+ case 0x60:
|
+#ifdef CONFIG_QCA_NSS_PACKET_FILTER
|
+ {
|
+ struct ipv6hdr *ip6h = (struct ipv6hdr *)(&skb_in->data[hdr_size]);
|
+ if (ip6h->nexthdr == NEXTHDR_ICMP) {
|
+ skip_nss = 1;
|
+ }
|
+ }
|
+#endif
|
+ protocol = htons(ETH_P_IPV6);
|
+ break;
|
+ default:
|
+ dev_info(dev, "unknow skb->protocol %02x\n", skb_in->data[hdr_size]);
|
+ goto error_pkt;
|
+ }
|
+
|
+ qmap_skb = netdev_alloc_skb(qmap_net, skb_len);
|
+ if (qmap_skb) {
|
+ skb_put(qmap_skb, skb_len);
|
+ memcpy(qmap_skb->data, skb_in->data + hdr_size, skb_len);
|
+ }
|
+
|
+ if (qmap_skb == NULL) {
|
+ dev_info(dev, "fail to alloc skb, pkt_len = %d\n", skb_len);
|
+ goto error_pkt;
|
+ }
|
+
|
+ skb_reset_transport_header(qmap_skb);
|
+ skb_reset_network_header(qmap_skb);
|
+ qmap_skb->pkt_type = PACKET_HOST;
|
+ skb_set_mac_header(qmap_skb, 0);
|
+ qmap_skb->protocol = protocol;
|
+
|
+ if(skip_nss)
|
+ qmap_skb->cb[0] = 1;
|
+
|
+ if (ul_header && ul_header->header_type == RMNET_MAP_HEADER_TYPE_CSUM_OFFLOAD
|
+ && ul_header->csum_valid_required) {
|
+#if 0 //TODO
|
+ qmap_skb->ip_summed = CHECKSUM_UNNECESSARY;
|
+#endif
|
+ }
|
+
|
+ if (qmap_skb->dev->type == ARPHRD_ETHER) {
|
+ skb_push(qmap_skb, ETH_HLEN);
|
+ skb_reset_mac_header(qmap_skb);
|
+ memcpy(eth_hdr(qmap_skb)->h_source, default_modem_addr, ETH_ALEN);
|
+ memcpy(eth_hdr(qmap_skb)->h_dest, qmap_net->dev_addr, ETH_ALEN);
|
+ eth_hdr(qmap_skb)->h_proto = protocol;
|
+#ifdef QUECTEL_BRIDGE_MODE
|
+ bridge_mode_rx_fixup(pQmapDev, qmap_net, qmap_skb);
|
+#endif
|
+ }
|
+
|
+ __skb_queue_tail(skb_chain, qmap_skb);
|
+
|
+skip_pkt:
|
+ skb_pull(skb_in, pkt_len + hdr_size);
|
+ }
|
+
|
+error_pkt:
|
+ return;
|
+}
|
+
|
+static int qmap_qmi_wwan_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
|
+{
|
+ struct qmi_wwan_state *info = (void *)&dev->data;
|
+ sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused;
|
+ struct sk_buff *qmap_skb;
|
+ struct sk_buff_head skb_chain;
|
+
|
+ if (pQmapDev->qmap_mode == 0)
|
+ return qmi_wwan_rx_fixup(dev, skb_in);
|
+
|
+ qmap_packet_decode(pQmapDev, skb_in, &skb_chain);
|
+
|
+ while ((qmap_skb = __skb_dequeue (&skb_chain))) {
|
+ if (qmap_skb->dev != dev->net) {
|
+ WARN_ON(1); //never reach here.
|
+ }
|
+ else {
|
+ qmap_skb->protocol = 0;
|
+ usbnet_skb_return(dev, qmap_skb);
|
+ }
|
+ }
|
+
|
+ return 0;
|
+}
|
+#endif
|
+
|
+/* very simplistic detection of IPv4 or IPv6 headers */
|
+static bool possibly_iphdr(const char *data)
|
+{
|
+ return (data[0] & 0xd0) == 0x40;
|
+}
|
+
|
+/* disallow addresses which may be confused with IP headers */
|
+static int qmi_wwan_mac_addr(struct net_device *dev, void *p)
|
+{
|
+ int ret;
|
+ struct sockaddr *addr = p;
|
+
|
+ ret = eth_prepare_mac_addr_change(dev, p);
|
+ if (ret < 0)
|
+ return ret;
|
+ if (possibly_iphdr(addr->sa_data))
|
+ return -EADDRNOTAVAIL;
|
+ eth_commit_mac_addr_change(dev, p);
|
+ return 0;
|
+}
|
+
|
+#if (LINUX_VERSION_CODE > KERNEL_VERSION( 4,10,0 )) //bc1f44709cf27fb2a5766cadafe7e2ad5e9cb221
|
+static void (*_usbnet_get_stats64)(struct net_device *net, struct rtnl_link_stats64 *stats);
|
+
|
+static void qmi_wwan_get_stats64(struct net_device *net, struct rtnl_link_stats64 *stats) {
|
+ if (_usbnet_get_stats64) ////c8b5d129ee293bcf972e7279ac996bb8a138505c
|
+ return _usbnet_get_stats64(net, stats);
|
+
|
+ netdev_stats_to_stats64(stats, &net->stats);
|
+}
|
+#else
|
+static struct rtnl_link_stats64 * (*_usbnet_get_stats64)(struct net_device *net, struct rtnl_link_stats64 *stats);
|
+
|
+static struct rtnl_link_stats64 * qmi_wwan_get_stats64(struct net_device *net, struct rtnl_link_stats64 *stats) {
|
+ if (_usbnet_get_stats64)
|
+ return _usbnet_get_stats64(net, stats);
|
+
|
+ netdev_stats_to_stats64(stats, &net->stats);
|
+ return stats;
|
+}
|
+#endif
|
+
|
+static int qmi_wwan_open (struct net_device *net) {
|
+ struct usbnet * usbnetdev = netdev_priv( net );
|
+ struct qmi_wwan_state *info = (void *)&usbnetdev->data;
|
+ sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused;
|
+ int retval;
|
+
|
+ retval = usbnet_open(net);
|
+
|
+ if (!retval) {
|
+ if (pQmapDev && pQmapDev->qmap_mode == 1) {
|
+ if (pQmapDev->link_state)
|
+ netif_carrier_on(net);
|
+ }
|
+ }
|
+
|
+ return retval;
|
+}
|
+
|
+static netdev_tx_t qmi_wwan_start_xmit (struct sk_buff *skb,
|
+ struct net_device *net)
|
+{
|
+ struct usbnet * usbnetdev = netdev_priv( net );
|
+ struct qmi_wwan_state *info = (void *)&usbnetdev->data;
|
+ sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused;
|
+ int retval;
|
+
|
+ retval = usbnet_start_xmit(skb, net);
|
+
|
+ if (netif_queue_stopped(net) && pQmapDev && pQmapDev->use_rmnet_usb) {
|
+ int i;
|
+
|
+ for (i = 0; i < pQmapDev->qmap_mode; i++) {
|
+ struct net_device *qmap_net = pQmapDev->mpQmapNetDev[i];
|
+ if (qmap_net) {
|
+ netif_stop_queue(qmap_net);
|
+ }
|
+ }
|
+ }
|
+
|
+ return retval;
|
+}
|
+
|
+#if (LINUX_VERSION_CODE > KERNEL_VERSION( 5,14,0 )) //b9067f5dc4a07c8e24e01a1b277c6722d91be39e
|
+#define use_ndo_siocdevprivate
|
+#endif
|
+#ifdef use_ndo_siocdevprivate
|
+static int qmap_ndo_siocdevprivate(struct net_device *dev, struct ifreq *ifr, void __user *data, int cmd) {
|
+ return qmap_ndo_do_ioctl(dev, ifr, cmd);
|
+}
|
+#endif
|
+
|
+static const struct net_device_ops qmi_wwan_netdev_ops = {
|
+ .ndo_open = qmi_wwan_open,
|
+ .ndo_stop = usbnet_stop,
|
+ .ndo_start_xmit = qmi_wwan_start_xmit,
|
+ .ndo_tx_timeout = usbnet_tx_timeout,
|
+ .ndo_change_mtu = usbnet_change_mtu,
|
+ .ndo_get_stats64 = qmi_wwan_get_stats64,
|
+ .ndo_set_mac_address = qmi_wwan_mac_addr,
|
+ .ndo_validate_addr = eth_validate_addr,
|
+#if defined(QUECTEL_WWAN_QMAP)// && defined(CONFIG_ANDROID)
|
+ .ndo_do_ioctl = qmap_ndo_do_ioctl,
|
+#ifdef use_ndo_siocdevprivate
|
+ .ndo_siocdevprivate = qmap_ndo_siocdevprivate,
|
+#endif
|
+#endif
|
+};
|
+
|
+static void ql_net_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info)
|
+{
|
+ /* Inherit standard device info */
|
+ usbnet_get_drvinfo(net, info);
|
+ strlcpy(info->driver, driver_name, sizeof(info->driver));
|
+ strlcpy(info->version, VERSION_NUMBER, sizeof(info->version));
|
+}
|
+
|
+static struct ethtool_ops ql_net_ethtool_ops;
|
+
|
+/* using a counter to merge subdriver requests with our own into a
|
+ * combined state
|
+ */
|
+static int qmi_wwan_manage_power(struct usbnet *dev, int on)
|
+{
|
+ struct qmi_wwan_state *info = (void *)&dev->data;
|
+ int rv;
|
+
|
+ dev_dbg(&dev->intf->dev, "%s() pmcount=%d, on=%d\n", __func__,
|
+ atomic_read(&info->pmcount), on);
|
+
|
+ if ((on && atomic_add_return(1, &info->pmcount) == 1) ||
|
+ (!on && atomic_dec_and_test(&info->pmcount))) {
|
+ /* need autopm_get/put here to ensure the usbcore sees
|
+ * the new value
|
+ */
|
+ rv = usb_autopm_get_interface(dev->intf);
|
+ dev->intf->needs_remote_wakeup = on;
|
+ if (!rv)
|
+ usb_autopm_put_interface(dev->intf);
|
+ }
|
+ return 0;
|
+}
|
+
|
+static int qmi_wwan_cdc_wdm_manage_power(struct usb_interface *intf, int on)
|
+{
|
+ struct usbnet *dev = usb_get_intfdata(intf);
|
+
|
+ /* can be called while disconnecting */
|
+ if (!dev)
|
+ return 0;
|
+ return qmi_wwan_manage_power(dev, on);
|
+}
|
+
|
+/* collect all three endpoints and register subdriver */
|
+static int qmi_wwan_register_subdriver(struct usbnet *dev)
|
+{
|
+ int rv;
|
+ struct usb_driver *subdriver = NULL;
|
+ struct qmi_wwan_state *info = (void *)&dev->data;
|
+
|
+ /* collect bulk endpoints */
|
+ rv = usbnet_get_endpoints(dev, info->data);
|
+ if (rv < 0)
|
+ goto err;
|
+
|
+ /* update status endpoint if separate control interface */
|
+ if (info->control != info->data)
|
+ dev->status = &info->control->cur_altsetting->endpoint[0];
|
+
|
+ /* require interrupt endpoint for subdriver */
|
+ if (!dev->status) {
|
+ rv = -EINVAL;
|
+ goto err;
|
+ }
|
+
|
+ /* for subdriver power management */
|
+ atomic_set(&info->pmcount, 0);
|
+
|
+ /* register subdriver */
|
+#if (LINUX_VERSION_CODE > KERNEL_VERSION( 5,12,0 )) //cac6fb015f719104e60b1c68c15ca5b734f57b9c
|
+ subdriver = usb_cdc_wdm_register(info->control, &dev->status->desc,
|
+ 4096, WWAN_PORT_QMI, &qmi_wwan_cdc_wdm_manage_power);
|
+#else
|
+ subdriver = usb_cdc_wdm_register(info->control, &dev->status->desc,
|
+ 4096, &qmi_wwan_cdc_wdm_manage_power);
|
+
|
+#endif
|
+ if (IS_ERR(subdriver)) {
|
+ dev_err(&info->control->dev, "subdriver registration failed\n");
|
+ rv = PTR_ERR(subdriver);
|
+ goto err;
|
+ }
|
+
|
+ /* prevent usbnet from using status endpoint */
|
+ dev->status = NULL;
|
+
|
+ /* save subdriver struct for suspend/resume wrappers */
|
+ info->subdriver = subdriver;
|
+
|
+err:
|
+ return rv;
|
+}
|
+
|
+static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf)
|
+{
|
+ int status = -1;
|
+ struct usb_driver *driver = driver_of(intf);
|
+ struct qmi_wwan_state *info = (void *)&dev->data;
|
+
|
+ BUILD_BUG_ON((sizeof(((struct usbnet *)0)->data) <
|
+ sizeof(struct qmi_wwan_state)));
|
+
|
+ /* set up initial state */
|
+ info->control = intf;
|
+ info->data = intf;
|
+
|
+ status = qmi_wwan_register_subdriver(dev);
|
+ if (status < 0 && info->control != info->data) {
|
+ usb_set_intfdata(info->data, NULL);
|
+ usb_driver_release_interface(driver, info->data);
|
+ }
|
+
|
+ /* Never use the same address on both ends of the link, even
|
+ * if the buggy firmware told us to.
|
+ */
|
+ if (ether_addr_equal(dev->net->dev_addr, default_modem_addr))
|
+ eth_hw_addr_random(dev->net);
|
+
|
+ /* make MAC addr easily distinguishable from an IP header */
|
+ if (possibly_iphdr(dev->net->dev_addr)) {
|
+ dev->net->dev_addr[0] |= 0x02; /* set local assignment bit */
|
+ dev->net->dev_addr[0] &= 0xbf; /* clear "IP" bit */
|
+ }
|
+ if (!_usbnet_get_stats64)
|
+ _usbnet_get_stats64 = dev->net->netdev_ops->ndo_get_stats64;
|
+ dev->net->netdev_ops = &qmi_wwan_netdev_ops;
|
+
|
+ ql_net_ethtool_ops = *dev->net->ethtool_ops;
|
+ ql_net_ethtool_ops.get_drvinfo = ql_net_get_drvinfo;
|
+ dev->net->ethtool_ops = &ql_net_ethtool_ops;
|
+
|
+#if 1 //Added by Quectel
|
+ if (dev->driver_info->flags & FLAG_NOARP) {
|
+ int ret;
|
+ char buf[32] = "Module";
|
+
|
+ ret = usb_string(dev->udev, dev->udev->descriptor.iProduct, buf, sizeof(buf));
|
+ if (ret > 0) {
|
+ buf[ret] = '\0';
|
+ }
|
+
|
+ dev_info(&intf->dev, "Quectel %s work on RawIP mode\n", buf);
|
+ dev->net->flags |= IFF_NOARP;
|
+ dev->net->flags &= ~(IFF_BROADCAST | IFF_MULTICAST);
|
+
|
+ usb_control_msg(
|
+ interface_to_usbdev(intf),
|
+ usb_sndctrlpipe(interface_to_usbdev(intf), 0),
|
+ 0x22, //USB_CDC_REQ_SET_CONTROL_LINE_STATE
|
+ 0x21, //USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE
|
+ 1, //active CDC DTR
|
+ intf->cur_altsetting->desc.bInterfaceNumber,
|
+ NULL, 0, 100);
|
+ }
|
+
|
+ //to advoid module report mtu 1460, but rx 1500 bytes IP packets, and cause the customer's system crash
|
+ //next setting can make usbnet.c:usbnet_change_mtu() do not modify rx_urb_size according to hard mtu
|
+ dev->rx_urb_size = ETH_DATA_LEN + ETH_HLEN + 6;
|
+
|
+#if defined(QUECTEL_WWAN_QMAP)
|
+ if (qmap_mode > QUECTEL_WWAN_QMAP)
|
+ qmap_mode = QUECTEL_WWAN_QMAP;
|
+
|
+ if (!status)
|
+ {
|
+ sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)kzalloc(sizeof(sQmiWwanQmap), GFP_KERNEL);
|
+
|
+ if (pQmapDev == NULL)
|
+ return -ENODEV;
|
+
|
+#ifdef QUECTEL_BRIDGE_MODE
|
+ pQmapDev->bridge_mode = bridge_mode;
|
+#ifdef CONFIG_BRIDGE_LAN
|
+ memcpy(pQmapDev->bridge_self_mac, broadcast_mac_addr, ETH_ALEN);
|
+#endif
|
+#endif
|
+ pQmapDev->mpNetDev = dev;
|
+ pQmapDev->link_state = 1;
|
+ //on OpenWrt, if set rmnet_usb0.1 as WAN, '/sbin/netifd' will auto create VLAN for rmnet_usb0
|
+ dev->net->features |= (NETIF_F_VLAN_CHALLENGED);
|
+
|
+ if (dev->driver_info->flags & FLAG_NOARP)
|
+ {
|
+ int qmap_version = (dev->driver_info->data>>8)&0xFF;
|
+ int qmap_size = (dev->driver_info->data)&0xFF;
|
+ int idProduct = le16_to_cpu(dev->udev->descriptor.idProduct);
|
+ int lte_a = (idProduct == 0x0306 || idProduct == 0x030B || idProduct == 0x0512 || idProduct == 0x0620 || idProduct == 0x0800 || idProduct == 0x0801);
|
+
|
+ if (qmap_size > 4096 || dev->udev->speed >= USB_SPEED_SUPER) { //if meet this requirements, must be LTE-A or 5G
|
+ lte_a = 1;
|
+ }
|
+
|
+ pQmapDev->qmap_mode = qmap_mode;
|
+ if (lte_a && pQmapDev->qmap_mode == 0) {
|
+ pQmapDev->qmap_mode = 1; //force use QMAP
|
+ if(qmap_mode == 0)
|
+ qmap_mode = 1; //old quectel-CM only check sys/module/wwan0/parameters/qmap_mode
|
+ }
|
+
|
+ if (pQmapDev->qmap_mode) {
|
+ pQmapDev->qmap_version = qmap_version;
|
+ pQmapDev->qmap_size = qmap_size*1024;
|
+ dev->rx_urb_size = pQmapDev->qmap_size;
|
+ //for these modules, if send packet before qmi_start_network, or cause host PC crash, or cause modules crash
|
+ pQmapDev->link_state = !lte_a;
|
+
|
+ if (pQmapDev->qmap_mode > 1)
|
+ pQmapDev->use_rmnet_usb = 1;
|
+ else if (idProduct == 0x0800 || idProduct == 0x0801)
|
+ pQmapDev->use_rmnet_usb = 1; //benefit for ul data agg
|
+#ifdef QMI_NETDEV_ONE_CARD_MODE
|
+ if(pQmapDev->use_rmnet_usb == 1 && pQmapDev->qmap_mode == 1)
|
+ one_card_mode = 1;
|
+ pQmapDev->rmnet_info.mux_id[0] = QUECTEL_QMAP_MUX_ID;
|
+#endif
|
+ pQmapDev->rmnet_info.size = sizeof(RMNET_INFO);
|
+ pQmapDev->rmnet_info.rx_urb_size = pQmapDev->qmap_size;
|
+ pQmapDev->rmnet_info.ep_type = 2; //DATA_EP_TYPE_HSUSB
|
+ pQmapDev->rmnet_info.iface_id = 4;
|
+ pQmapDev->rmnet_info.qmap_mode = pQmapDev->qmap_mode;
|
+ pQmapDev->rmnet_info.qmap_version = pQmapDev->qmap_version;
|
+ pQmapDev->rmnet_info.dl_minimum_padding = 0;
|
+
|
+#if defined(QUECTEL_UL_DATA_AGG)
|
+ pQmapDev->tx_ctx.ul_data_aggregation_max_datagrams = 1;
|
+ pQmapDev->tx_ctx.ul_data_aggregation_max_size = 1500;
|
+#endif
|
+
|
+ if (pQmapDev->use_rmnet_usb && !one_card_mode) {
|
+ pQmapDev->driver_info = rmnet_usb_info;
|
+ pQmapDev->driver_info.data = dev->driver_info->data;
|
+ dev->driver_info = &pQmapDev->driver_info;
|
+ }
|
+
|
+ if (pQmapDev->use_rmnet_usb && !one_card_mode) {
|
+ pQmapDev->usbnet_bh = dev->bh;
|
+ tasklet_init(&dev->bh, usbnet_bh, (unsigned long)pQmapDev);
|
+ }
|
+ }
|
+ }
|
+
|
+ info->unused = (unsigned long)pQmapDev;
|
+ dev->net->sysfs_groups[0] = &qmi_wwan_sysfs_attr_group;
|
+
|
+ dev_info(&intf->dev, "rx_urb_size = %zd\n", dev->rx_urb_size);
|
+ }
|
+#endif
|
+#endif
|
+
|
+ return status;
|
+}
|
+
|
+static void qmi_wwan_unbind(struct usbnet *dev, struct usb_interface *intf)
|
+{
|
+ struct qmi_wwan_state *info = (void *)&dev->data;
|
+ struct usb_driver *driver = driver_of(intf);
|
+ struct usb_interface *other;
|
+
|
+ if (dev->udev && dev->udev->state == USB_STATE_CONFIGURED) {
|
+ usb_control_msg(
|
+ interface_to_usbdev(intf),
|
+ usb_sndctrlpipe(interface_to_usbdev(intf), 0),
|
+ 0x22, //USB_CDC_REQ_SET_CONTROL_LINE_STATE
|
+ 0x21, //USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE
|
+ 0, //deactive CDC DTR
|
+ intf->cur_altsetting->desc.bInterfaceNumber,
|
+ NULL, 0, 100);
|
+ }
|
+
|
+ if (info->subdriver && info->subdriver->disconnect)
|
+ info->subdriver->disconnect(info->control);
|
+
|
+ /* allow user to unbind using either control or data */
|
+ if (intf == info->control)
|
+ other = info->data;
|
+ else
|
+ other = info->control;
|
+
|
+ /* only if not shared */
|
+ if (other && intf != other) {
|
+ usb_set_intfdata(other, NULL);
|
+ usb_driver_release_interface(driver, other);
|
+ }
|
+
|
+ info->subdriver = NULL;
|
+ info->data = NULL;
|
+ info->control = NULL;
|
+}
|
+
|
+/* suspend/resume wrappers calling both usbnet and the cdc-wdm
|
+ * subdriver if present.
|
+ *
|
+ * NOTE: cdc-wdm also supports pre/post_reset, but we cannot provide
|
+ * wrappers for those without adding usbnet reset support first.
|
+ */
|
+static int qmi_wwan_suspend(struct usb_interface *intf, pm_message_t message)
|
+{
|
+ struct usbnet *dev = usb_get_intfdata(intf);
|
+ struct qmi_wwan_state *info = (void *)&dev->data;
|
+ int ret;
|
+
|
+ /* Both usbnet_suspend() and subdriver->suspend() MUST return 0
|
+ * in system sleep context, otherwise, the resume callback has
|
+ * to recover device from previous suspend failure.
|
+ */
|
+ ret = usbnet_suspend(intf, message);
|
+ if (ret < 0)
|
+ goto err;
|
+
|
+ if (intf == info->control && info->subdriver &&
|
+ info->subdriver->suspend)
|
+ ret = info->subdriver->suspend(intf, message);
|
+ if (ret < 0)
|
+ usbnet_resume(intf);
|
+err:
|
+ return ret;
|
+}
|
+
|
+static int qmi_wwan_resume(struct usb_interface *intf)
|
+{
|
+ struct usbnet *dev = usb_get_intfdata(intf);
|
+ struct qmi_wwan_state *info = (void *)&dev->data;
|
+ int ret = 0;
|
+ bool callsub = (intf == info->control && info->subdriver &&
|
+ info->subdriver->resume);
|
+
|
+ if (callsub)
|
+ ret = info->subdriver->resume(intf);
|
+ if (ret < 0)
|
+ goto err;
|
+ ret = usbnet_resume(intf);
|
+ if (ret < 0 && callsub)
|
+ info->subdriver->suspend(intf, PMSG_SUSPEND);
|
+
|
+#if defined(QUECTEL_WWAN_QMAP)
|
+ if (!netif_queue_stopped(dev->net)) {
|
+ qmap_wake_queue((sQmiWwanQmap *)info->unused);
|
+ }
|
+#endif
|
+
|
+err:
|
+ return ret;
|
+}
|
+
|
+static int qmi_wwan_reset_resume(struct usb_interface *intf)
|
+{
|
+ dev_info(&intf->dev, "device do not support reset_resume\n");
|
+ intf->needs_binding = 1;
|
+ return -EOPNOTSUPP;
|
+}
|
+
|
+static struct sk_buff *rmnet_usb_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
|
+{
|
+ //printk("%s skb=%p, len=%d, protocol=%x, hdr_len=%d\n", __func__, skb, skb->len, skb->protocol, skb->hdr_len);
|
+ if (skb->protocol != htons(ETH_P_MAP)) {
|
+ dev_kfree_skb_any(skb);
|
+ return NULL;
|
+ }
|
+
|
+ return skb;
|
+}
|
+
|
+static int rmnet_usb_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
|
+{
|
+ struct net_device *net = dev->net;
|
+ unsigned headroom = skb_headroom(skb);
|
+
|
+#if (LINUX_VERSION_CODE < KERNEL_VERSION( 3,3,1 )) //7bdd402706cf26bfef9050dfee3f229b7f33ee4f
|
+//some customers port to v3.2
|
+ if (net->type == ARPHRD_ETHER && headroom < ETH_HLEN) {
|
+ unsigned tailroom = skb_tailroom(skb);
|
+
|
+ if ((tailroom + headroom) >= ETH_HLEN) {
|
+ unsigned moveroom = ETH_HLEN - headroom;
|
+
|
+ memmove(skb->data + moveroom ,skb->data, skb->len);
|
+ skb->data += moveroom;
|
+ skb->tail += moveroom;
|
+ #ifdef WARN_ONCE
|
+ WARN_ONCE(1, "It is better reserve headroom in usbnet.c:rx_submit()!\n");
|
+ #endif
|
+ }
|
+ }
|
+#endif
|
+
|
+ //printk("%s skb=%p, len=%d, protocol=%x, hdr_len=%d\n", __func__, skb, skb->len, skb->protocol, skb->hdr_len);
|
+ if (net->type == ARPHRD_ETHER && headroom >= ETH_HLEN) {
|
+ //usbnet.c rx_process() usbnet_skb_return() eth_type_trans()
|
+ skb_push(skb, ETH_HLEN);
|
+ skb_reset_mac_header(skb);
|
+ memcpy(eth_hdr(skb)->h_source, default_modem_addr, ETH_ALEN);
|
+ memcpy(eth_hdr(skb)->h_dest, net->dev_addr, ETH_ALEN);
|
+ eth_hdr(skb)->h_proto = htons(ETH_P_MAP);
|
+
|
+ return 1;
|
+ }
|
+
|
+ return 0;
|
+}
|
+
|
+static rx_handler_result_t rmnet_usb_rx_handler(struct sk_buff **pskb)
|
+{
|
+ struct sk_buff *skb = *pskb;
|
+ struct usbnet *dev;
|
+ struct qmi_wwan_state *info;
|
+ sQmiWwanQmap *pQmapDev;
|
+ struct sk_buff *qmap_skb;
|
+ struct sk_buff_head skb_chain;
|
+
|
+ if (!skb)
|
+ goto done;
|
+
|
+ //printk("%s skb=%p, protocol=%x, len=%d\n", __func__, skb, skb->protocol, skb->len);
|
+
|
+ if (skb->pkt_type == PACKET_LOOPBACK)
|
+ return RX_HANDLER_PASS;
|
+
|
+ if (skb->protocol != htons(ETH_P_MAP)) {
|
+ WARN_ON(1);
|
+ return RX_HANDLER_PASS;
|
+ }
|
+ /* when open hyfi function, run cm will make system crash */
|
+ //dev = rcu_dereference(skb->dev->rx_handler_data);
|
+ dev = netdev_priv(skb->dev);
|
+
|
+ if (dev == NULL) {
|
+ WARN_ON(1);
|
+ return RX_HANDLER_PASS;
|
+ }
|
+
|
+ info = (struct qmi_wwan_state *)&dev->data;
|
+ pQmapDev = (sQmiWwanQmap *)info->unused;
|
+
|
+ qmap_packet_decode(pQmapDev, skb, &skb_chain);
|
+ while ((qmap_skb = __skb_dequeue (&skb_chain))) {
|
+ struct net_device *qmap_net = qmap_skb->dev;
|
+
|
+ rmnet_vnd_update_rx_stats(qmap_net, 1, qmap_skb->len);
|
+ if (qmap_net->type == ARPHRD_ETHER)
|
+ __skb_pull(qmap_skb, ETH_HLEN);
|
+ netif_receive_skb(qmap_skb);
|
+ }
|
+ consume_skb(skb);
|
+
|
+done:
|
+ return RX_HANDLER_CONSUMED;
|
+}
|
+
|
+static const struct driver_info qmi_wwan_info = {
|
+ .description = "WWAN/QMI device",
|
+ .flags = FLAG_WWAN,
|
+ .bind = qmi_wwan_bind,
|
+ .unbind = qmi_wwan_unbind,
|
+ .manage_power = qmi_wwan_manage_power,
|
+};
|
+
|
+#define qmi_wwan_raw_ip_info \
|
+ .description = "WWAN/QMI device", \
|
+ .flags = FLAG_WWAN | FLAG_RX_ASSEMBLE | FLAG_NOARP | FLAG_SEND_ZLP, \
|
+ .bind = qmi_wwan_bind, \
|
+ .unbind = qmi_wwan_unbind, \
|
+ .manage_power = qmi_wwan_manage_power, \
|
+ .tx_fixup = qmap_qmi_wwan_tx_fixup, \
|
+ .rx_fixup = qmap_qmi_wwan_rx_fixup, \
|
+
|
+static const struct driver_info rmnet_usb_info = {
|
+ .description = "RMNET/USB device",
|
+ .flags = FLAG_WWAN | FLAG_NOARP | FLAG_SEND_ZLP,
|
+ .bind = qmi_wwan_bind,
|
+ .unbind = qmi_wwan_unbind,
|
+ .manage_power = qmi_wwan_manage_power,
|
+ .tx_fixup = rmnet_usb_tx_fixup,
|
+ .rx_fixup = rmnet_usb_rx_fixup,
|
+};
|
+
|
+static const struct driver_info qmi_wwan_raw_ip_info_mdm9x07 = {
|
+ qmi_wwan_raw_ip_info
|
+ .data = (5<<8)|4, //QMAPV1 and 4KB
|
+};
|
+
|
+// mdm9x40/sdx12/sdx20/sdx24 share the same config
|
+static const struct driver_info qmi_wwan_raw_ip_info_mdm9x40 = {
|
+ qmi_wwan_raw_ip_info
|
+ .data = (5<<8)|16, //QMAPV1 and 16KB
|
+};
|
+
|
+static const struct driver_info qmi_wwan_raw_ip_info_sdx55 = {
|
+ qmi_wwan_raw_ip_info
|
+ .data = (9<<8)|31, //QMAPV5 and 31KB
|
+};
|
+
|
+/* map QMI/wwan function by a fixed interface number */
|
+#define QMI_FIXED_INTF(vend, prod, num) \
|
+ USB_DEVICE_INTERFACE_NUMBER(vend, prod, num), \
|
+ .driver_info = (unsigned long)&qmi_wwan_info
|
+
|
+#define QMI_FIXED_RAWIP_INTF(vend, prod, num, chip) \
|
+ USB_DEVICE_INTERFACE_NUMBER(vend, prod, num), \
|
+ .driver_info = (unsigned long)&qmi_wwan_raw_ip_info_##chip
|
+
|
+static const struct usb_device_id products[] = {
|
+ { QMI_FIXED_INTF(0x05C6, 0x9003, 4) }, /* Quectel UC20 */
|
+ { QMI_FIXED_INTF(0x05C6, 0x9215, 4) }, /* Quectel EC20 (MDM9215) */
|
+ { QMI_FIXED_RAWIP_INTF(0x2C7C, 0x0125, 4, mdm9x07) }, /* Quectel EC20 (MDM9X07)/EC25/EG25 */
|
+ { QMI_FIXED_RAWIP_INTF(0x2C7C, 0x0121, 4, mdm9x07) }, /* Quectel EC21 */
|
+ { QMI_FIXED_RAWIP_INTF(0x2C7C, 0x0191, 4, mdm9x07) }, /* Quectel EG91 */
|
+ { QMI_FIXED_RAWIP_INTF(0x2C7C, 0x0195, 4, mdm9x07) }, /* Quectel EG95 */
|
+ { QMI_FIXED_RAWIP_INTF(0x2C7C, 0x0700, 3, mdm9x07) }, /* Quectel BG95 (at+qcfgext="usbnet","rmnet") */
|
+ { QMI_FIXED_RAWIP_INTF(0x2C7C, 0x0306, 4, mdm9x40) }, /* Quectel EG06/EP06/EM06 */
|
+ { QMI_FIXED_RAWIP_INTF(0x2C7C, 0x030B, 4, mdm9x40) }, /* Quectel EG065k/EG060K */
|
+ { QMI_FIXED_RAWIP_INTF(0x2C7C, 0x0512, 4, mdm9x40) }, /* Quectel EG12/EP12/EM12/EG16/EG18 */
|
+ { QMI_FIXED_RAWIP_INTF(0x2C7C, 0x0296, 4, mdm9x07) }, /* Quectel BG96 */
|
+ { QMI_FIXED_RAWIP_INTF(0x2C7C, 0x0435, 4, mdm9x07) }, /* Quectel AG35 */
|
+ { QMI_FIXED_RAWIP_INTF(0x2C7C, 0x0620, 4, mdm9x40) }, /* Quectel EG20 */
|
+ { QMI_FIXED_RAWIP_INTF(0x2C7C, 0x0800, 4, sdx55) }, /* Quectel RG500 */
|
+ { QMI_FIXED_RAWIP_INTF(0x2C7C, 0x0801, 4, sdx55) }, /* Quectel RG520 */
|
+ { } /* END */
|
+};
|
+MODULE_DEVICE_TABLE(usb, products);
|
+
|
+static int qmi_wwan_probe(struct usb_interface *intf,
|
+ const struct usb_device_id *prod)
|
+{
|
+ struct usb_device_id *id = (struct usb_device_id *)prod;
|
+
|
+ /* Workaround to enable dynamic IDs. This disables usbnet
|
+ * blacklisting functionality. Which, if required, can be
|
+ * reimplemented here by using a magic "blacklist" value
|
+ * instead of 0 in the static device id table
|
+ */
|
+ if (!id->driver_info) {
|
+ dev_dbg(&intf->dev, "setting defaults for dynamic device id\n");
|
+ id->driver_info = (unsigned long)&qmi_wwan_info;
|
+ }
|
+
|
+ if (intf->cur_altsetting->desc.bInterfaceClass != 0xff) {
|
+ dev_info(&intf->dev, "Quectel module not qmi_wwan mode! please check 'at+qcfg=\"usbnet\"'\n");
|
+ return -ENODEV;
|
+ }
|
+
|
+ return usbnet_probe(intf, id);
|
+}
|
+
|
+#if defined(QUECTEL_WWAN_QMAP)
|
+static int qmap_qmi_wwan_probe(struct usb_interface *intf,
|
+ const struct usb_device_id *prod)
|
+{
|
+ int status = qmi_wwan_probe(intf, prod);
|
+
|
+ if (!status) {
|
+ struct usbnet *dev = usb_get_intfdata(intf);
|
+ struct qmi_wwan_state *info = (void *)&dev->data;
|
+ sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused;
|
+ unsigned i;
|
+
|
+ if (!pQmapDev)
|
+ return status;
|
+
|
+ tasklet_init(&pQmapDev->txq, rmnet_usb_tx_wake_queue, (unsigned long)pQmapDev);
|
+
|
+ if (pQmapDev->qmap_mode == 1) {
|
+ pQmapDev->mpQmapNetDev[0] = dev->net;
|
+ if (pQmapDev->use_rmnet_usb && !one_card_mode) {
|
+ pQmapDev->mpQmapNetDev[0] = NULL;
|
+ qmap_register_device(pQmapDev, 0);
|
+ }
|
+ }
|
+ else if (pQmapDev->qmap_mode > 1) {
|
+ for (i = 0; i < pQmapDev->qmap_mode; i++) {
|
+ qmap_register_device(pQmapDev, i);
|
+ }
|
+ }
|
+
|
+ if (pQmapDev->use_rmnet_usb && !one_card_mode) {
|
+ rtnl_lock();
|
+ /* when open hyfi function, run cm will make system crash */
|
+ //netdev_rx_handler_register(dev->net, rmnet_usb_rx_handler, dev);
|
+ netdev_rx_handler_register(dev->net, rmnet_usb_rx_handler, NULL);
|
+ rtnl_unlock();
|
+ }
|
+
|
+ if (pQmapDev->link_state == 0) {
|
+ netif_carrier_off(dev->net);
|
+ }
|
+ }
|
+
|
+ return status;
|
+}
|
+
|
+static void qmap_qmi_wwan_disconnect(struct usb_interface *intf)
|
+{
|
+ struct usbnet *dev = usb_get_intfdata(intf);
|
+ struct qmi_wwan_state *info;
|
+ sQmiWwanQmap *pQmapDev;
|
+ uint i;
|
+
|
+ if (!dev)
|
+ return;
|
+
|
+ info = (void *)&dev->data;
|
+ pQmapDev = (sQmiWwanQmap *)info->unused;
|
+
|
+ if (!pQmapDev) {
|
+ return usbnet_disconnect(intf);
|
+ }
|
+
|
+ pQmapDev->link_state = 0;
|
+
|
+ if (pQmapDev->qmap_mode > 1) {
|
+ for (i = 0; i < pQmapDev->qmap_mode; i++) {
|
+ qmap_unregister_device(pQmapDev, i);
|
+ }
|
+ }
|
+
|
+ if (pQmapDev->use_rmnet_usb && !one_card_mode) {
|
+ qmap_unregister_device(pQmapDev, 0);
|
+ rtnl_lock();
|
+ netdev_rx_handler_unregister(dev->net);
|
+ rtnl_unlock();
|
+ }
|
+
|
+ tasklet_kill(&pQmapDev->txq);
|
+
|
+ usbnet_disconnect(intf);
|
+ /* struct usbnet *dev had free by usbnet_disconnect()->free_netdev().
|
+ so we should access info. */
|
+ //info->unused = 0;
|
+ kfree(pQmapDev);
|
+}
|
+#endif
|
+
|
+static struct usb_driver qmi_wwan_driver = {
|
+ .name = "qmi_wwan_q",
|
+ .id_table = products,
|
+ .probe = qmi_wwan_probe,
|
+#if defined(QUECTEL_WWAN_QMAP)
|
+ .probe = qmap_qmi_wwan_probe,
|
+ .disconnect = qmap_qmi_wwan_disconnect,
|
+#else
|
+ .probe = qmi_wwan_probe,
|
+ .disconnect = usbnet_disconnect,
|
+#endif
|
+ .suspend = qmi_wwan_suspend,
|
+ .resume = qmi_wwan_resume,
|
+ .reset_resume = qmi_wwan_reset_resume,
|
+ .supports_autosuspend = 1,
|
+ .disable_hub_initiated_lpm = 1,
|
+};
|
+
|
+static int __init qmi_wwan_driver_init(void)
|
+{
|
+#ifdef CONFIG_QCA_NSS_DRV
|
+ nss_cb = rcu_dereference(rmnet_nss_callbacks);
|
+ if (!nss_cb) {
|
+ printk(KERN_ERR "qmi_wwan_driver_init: driver load must after '/etc/modules.d/42-rmnet-nss'\n");
|
+ }
|
+#endif
|
+ return usb_register(&qmi_wwan_driver);
|
+}
|
+module_init(qmi_wwan_driver_init);
|
+static void __exit qmi_wwan_driver_exit(void)
|
+{
|
+ usb_deregister(&qmi_wwan_driver);
|
+}
|
+module_exit(qmi_wwan_driver_exit);
|
+
|
+MODULE_AUTHOR("Bjørn Mork <bjorn@mork.no>");
|
+MODULE_DESCRIPTION("Qualcomm MSM Interface (QMI) WWAN driver");
|
+MODULE_LICENSE("GPL");
|
+MODULE_VERSION(QUECTEL_WWAN_VERSION);
|
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
|
index 691fd8ab7..372241cd5 100644
|
--- a/drivers/usb/dwc3/core.c
|
+++ b/drivers/usb/dwc3/core.c
|
@@ -99,6 +99,9 @@ static int dwc3_get_dr_mode(struct dwc3 *dwc)
|
dwc->dr_mode = mode;
|
}
|
|
+ /* Add by linke */
|
+ dwc->dr_mode = USB_DR_MODE_OTG;
|
+
|
return 0;
|
}
|
|
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
|
index 697683e3f..3fe38fb85 100644
|
--- a/drivers/usb/serial/option.c
|
+++ b/drivers/usb/serial/option.c
|
@@ -198,8 +198,6 @@ static void option_instat_callback(struct urb *urb);
|
|
#define DELL_PRODUCT_5821E 0x81d7
|
#define DELL_PRODUCT_5821E_ESIM 0x81e0
|
-#define DELL_PRODUCT_5829E_ESIM 0x81e4
|
-#define DELL_PRODUCT_5829E 0x81e6
|
|
#define KYOCERA_VENDOR_ID 0x0c88
|
#define KYOCERA_PRODUCT_KPC650 0x17da
|
@@ -252,14 +250,10 @@ static void option_instat_callback(struct urb *urb);
|
#define QUECTEL_PRODUCT_EG95 0x0195
|
#define QUECTEL_PRODUCT_BG96 0x0296
|
#define QUECTEL_PRODUCT_EP06 0x0306
|
-#define QUECTEL_PRODUCT_EM05G 0x030a
|
-#define QUECTEL_PRODUCT_EM060K 0x030b
|
#define QUECTEL_PRODUCT_EM12 0x0512
|
#define QUECTEL_PRODUCT_RM500Q 0x0800
|
-#define QUECTEL_PRODUCT_RM520N 0x0801
|
#define QUECTEL_PRODUCT_EC200S_CN 0x6002
|
#define QUECTEL_PRODUCT_EC200T 0x6026
|
-#define QUECTEL_PRODUCT_RM500K 0x7001
|
|
#define CMOTECH_VENDOR_ID 0x16d8
|
#define CMOTECH_PRODUCT_6001 0x6001
|
@@ -436,12 +430,6 @@ static void option_instat_callback(struct urb *urb);
|
#define CINTERION_PRODUCT_CLS8 0x00b0
|
#define CINTERION_PRODUCT_MV31_MBIM 0x00b3
|
#define CINTERION_PRODUCT_MV31_RMNET 0x00b7
|
-#define CINTERION_PRODUCT_MV31_2_MBIM 0x00b8
|
-#define CINTERION_PRODUCT_MV31_2_RMNET 0x00b9
|
-#define CINTERION_PRODUCT_MV32_WA 0x00f1
|
-#define CINTERION_PRODUCT_MV32_WB 0x00f2
|
-#define CINTERION_PRODUCT_MV32_WA_RMNET 0x00f3
|
-#define CINTERION_PRODUCT_MV32_WB_RMNET 0x00f4
|
|
/* Olivetti products */
|
#define OLIVETTI_VENDOR_ID 0x0b3c
|
@@ -577,10 +565,6 @@ static void option_instat_callback(struct urb *urb);
|
#define WETELECOM_PRODUCT_6802 0x6802
|
#define WETELECOM_PRODUCT_WMD300 0x6803
|
|
-/* OPPO products */
|
-#define OPPO_VENDOR_ID 0x22d9
|
-#define OPPO_PRODUCT_R11 0x276c
|
-
|
|
/* Device flags */
|
|
@@ -601,6 +585,32 @@ static void option_instat_callback(struct urb *urb);
|
|
|
static const struct usb_device_id option_ids[] = {
|
+#if 1 //Added by Quectel
|
+ { USB_DEVICE(0x05C6, 0x9090) }, /* Quectel UC15 */
|
+ { USB_DEVICE(0x05C6, 0x9003) }, /* Quectel UC20 */
|
+ { USB_DEVICE(0x05C6, 0x9215) }, /* Quectel EC20(MDM9215) */
|
+ { USB_DEVICE(0x2C7C, 0x0125) }, /* Quectel EC20(MDM9x07)/EC25/EG25 */
|
+ { USB_DEVICE(0x2C7C, 0x0121) }, /* Quectel EC21 */
|
+ { USB_DEVICE(0x2C7C, 0x0191) }, /* Quectel EG91 */
|
+ { USB_DEVICE(0x2C7C, 0x0195) }, /* Quectel EG95 */
|
+ { USB_DEVICE(0x2C7C, 0x0306) }, /* Quectel EG06/EP06/EM06 */
|
+ { USB_DEVICE(0x2C7C, 0x030B) }, /* Quectel EG065K/EG060K */
|
+ { USB_DEVICE(0x2C7C, 0x0514) }, /* Quectel BL EG060K RNDIS Only */
|
+ { USB_DEVICE(0x2C7C, 0x0512) }, /* Quectel EG12/EP12/EM12/EG16/EG18 */
|
+ { USB_DEVICE(0x2C7C, 0x0296) }, /* Quectel BG96 */
|
+ { USB_DEVICE(0x2C7C, 0x0700) }, /* Quectel BG95/BG77/BG600L-M3/BC69 */
|
+ { USB_DEVICE(0x2C7C, 0x0435) }, /* Quectel AG35 */
|
+ { USB_DEVICE(0x2C7C, 0x0415) }, /* Quectel AG15 */
|
+ { USB_DEVICE(0x2C7C, 0x0452) }, /* Quectel AG520 */
|
+ { USB_DEVICE(0x2C7C, 0x0455) }, /* Quectel AG550 */
|
+ { USB_DEVICE(0x2C7C, 0x0620) }, /* Quectel EG20 */
|
+ { USB_DEVICE(0x2C7C, 0x0800) }, /* Quectel RG500/RM500/RG510/RM510 */
|
+ { USB_DEVICE(0x2C7C, 0x0801) }, /* Quectel RG520/RM520/SG520 */
|
+ { USB_DEVICE(0x2C7C, 0x6026) }, /* Quectel EC200 */
|
+ { USB_DEVICE(0x2C7C, 0x6120) }, /* Quectel UC200 */
|
+ { USB_DEVICE(0x2C7C, 0x6000) }, /* Quectel EC200/UC200 */
|
+ { .match_flags = USB_DEVICE_ID_MATCH_VENDOR, .idVendor = 0x2C7C }, /* Match All Quectel Modules */
|
+#endif
|
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
|
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
|
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_LIGHT) },
|
@@ -1079,10 +1089,6 @@ static const struct usb_device_id option_ids[] = {
|
.driver_info = RSVD(0) | RSVD(1) | RSVD(6) },
|
{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5821E_ESIM),
|
.driver_info = RSVD(0) | RSVD(1) | RSVD(6) },
|
- { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5829E),
|
- .driver_info = RSVD(0) | RSVD(6) },
|
- { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5829E_ESIM),
|
- .driver_info = RSVD(0) | RSVD(6) },
|
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) }, /* ADU-E100, ADU-310 */
|
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) },
|
{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_620UW) },
|
@@ -1139,35 +1145,22 @@ static const struct usb_device_id option_ids[] = {
|
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EG95, 0xff, 0xff, 0xff),
|
.driver_info = NUMEP2 },
|
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EG95, 0xff, 0, 0) },
|
- { USB_DEVICE_INTERFACE_CLASS(QUECTEL_VENDOR_ID, 0x0203, 0xff), /* BG95-M3 */
|
- .driver_info = ZLP },
|
{ USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96),
|
.driver_info = RSVD(4) },
|
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0xff, 0xff),
|
.driver_info = RSVD(1) | RSVD(2) | RSVD(3) | RSVD(4) | NUMEP2 },
|
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0, 0) },
|
- { USB_DEVICE_INTERFACE_CLASS(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM05G, 0xff),
|
- .driver_info = RSVD(6) | ZLP },
|
- { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K, 0xff, 0x00, 0x40) },
|
- { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K, 0xff, 0xff, 0x30) },
|
- { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K, 0xff, 0xff, 0x40) },
|
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM12, 0xff, 0xff, 0xff),
|
.driver_info = RSVD(1) | RSVD(2) | RSVD(3) | RSVD(4) | NUMEP2 },
|
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM12, 0xff, 0, 0) },
|
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, 0x0620, 0xff, 0xff, 0x30) }, /* EM160R-GL */
|
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, 0x0620, 0xff, 0, 0) },
|
- { USB_DEVICE_INTERFACE_CLASS(QUECTEL_VENDOR_ID, 0x0700, 0xff), /* BG95 */
|
- .driver_info = RSVD(3) | ZLP },
|
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500Q, 0xff, 0xff, 0x30) },
|
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500Q, 0xff, 0, 0) },
|
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500Q, 0xff, 0xff, 0x10),
|
.driver_info = ZLP },
|
- { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM520N, 0xff, 0xff, 0x30) },
|
- { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM520N, 0xff, 0, 0x40) },
|
- { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM520N, 0xff, 0, 0) },
|
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200S_CN, 0xff, 0, 0) },
|
{ USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200T, 0xff, 0, 0) },
|
- { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500K, 0xff, 0x00, 0x00) },
|
|
{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) },
|
{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) },
|
@@ -1244,10 +1237,6 @@ static const struct usb_device_id option_ids[] = {
|
.driver_info = NCTRL(0) | RSVD(1) },
|
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1056, 0xff), /* Telit FD980 */
|
.driver_info = NCTRL(2) | RSVD(3) },
|
- { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1057, 0xff), /* Telit FN980 */
|
- .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) },
|
- { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1058, 0xff), /* Telit FN980 (PCIe) */
|
- .driver_info = NCTRL(0) | RSVD(1) },
|
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1060, 0xff), /* Telit LN920 (rmnet) */
|
.driver_info = NCTRL(0) | RSVD(1) | RSVD(2) },
|
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1061, 0xff), /* Telit LN920 (MBIM) */
|
@@ -1264,8 +1253,6 @@ static const struct usb_device_id option_ids[] = {
|
.driver_info = NCTRL(2) | RSVD(3) },
|
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1073, 0xff), /* Telit FN990 (ECM) */
|
.driver_info = NCTRL(0) | RSVD(1) },
|
- { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1075, 0xff), /* Telit FN990 (PCIe) */
|
- .driver_info = RSVD(0) },
|
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910),
|
.driver_info = NCTRL(0) | RSVD(1) | RSVD(3) },
|
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910_DUAL_MODEM),
|
@@ -1300,7 +1287,6 @@ static const struct usb_device_id option_ids[] = {
|
.driver_info = NCTRL(0) | RSVD(1) | RSVD(2) },
|
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1231, 0xff), /* Telit LE910Cx (RNDIS) */
|
.driver_info = NCTRL(2) | RSVD(3) },
|
- { USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x1250, 0xff, 0x00, 0x00) }, /* Telit LE910Cx (rmnet) */
|
{ USB_DEVICE(TELIT_VENDOR_ID, 0x1260),
|
.driver_info = NCTRL(0) | RSVD(1) | RSVD(2) },
|
{ USB_DEVICE(TELIT_VENDOR_ID, 0x1261),
|
@@ -1313,16 +1299,10 @@ static const struct usb_device_id option_ids[] = {
|
.driver_info = NCTRL(2) },
|
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x7011, 0xff), /* Telit LE910-S1 (ECM) */
|
.driver_info = NCTRL(2) },
|
- { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x701a, 0xff), /* Telit LE910R1 (RNDIS) */
|
- .driver_info = NCTRL(2) },
|
- { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x701b, 0xff), /* Telit LE910R1 (ECM) */
|
- .driver_info = NCTRL(2) },
|
{ USB_DEVICE(TELIT_VENDOR_ID, 0x9010), /* Telit SBL FN980 flashing device */
|
.driver_info = NCTRL(0) | ZLP },
|
{ USB_DEVICE(TELIT_VENDOR_ID, 0x9200), /* Telit LE910S1 flashing device */
|
.driver_info = NCTRL(0) | ZLP },
|
- { USB_DEVICE(TELIT_VENDOR_ID, 0x9201), /* Telit LE910R1 flashing device */
|
- .driver_info = NCTRL(0) | ZLP },
|
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */
|
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0002, 0xff, 0xff, 0xff),
|
.driver_info = RSVD(1) },
|
@@ -1695,8 +1675,6 @@ static const struct usb_device_id option_ids[] = {
|
.driver_info = RSVD(2) },
|
{ USB_DEVICE_INTERFACE_CLASS(ZTE_VENDOR_ID, 0x1476, 0xff) }, /* GosunCn ZTE WeLink ME3630 (ECM/NCM mode) */
|
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1481, 0xff, 0x00, 0x00) }, /* ZTE MF871A */
|
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1485, 0xff, 0xff, 0xff), /* ZTE MF286D */
|
- .driver_info = RSVD(5) },
|
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1533, 0xff, 0xff, 0xff) },
|
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1534, 0xff, 0xff, 0xff) },
|
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1535, 0xff, 0xff, 0xff) },
|
@@ -2003,18 +1981,6 @@ static const struct usb_device_id option_ids[] = {
|
.driver_info = RSVD(3)},
|
{ USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV31_RMNET, 0xff),
|
.driver_info = RSVD(0)},
|
- { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV31_2_MBIM, 0xff),
|
- .driver_info = RSVD(3)},
|
- { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV31_2_RMNET, 0xff),
|
- .driver_info = RSVD(0)},
|
- { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV32_WA, 0xff),
|
- .driver_info = RSVD(3)},
|
- { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV32_WA_RMNET, 0xff),
|
- .driver_info = RSVD(0) },
|
- { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV32_WB, 0xff),
|
- .driver_info = RSVD(3)},
|
- { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV32_WB_RMNET, 0xff),
|
- .driver_info = RSVD(0) },
|
{ USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100),
|
.driver_info = RSVD(4) },
|
{ USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD120),
|
@@ -2157,14 +2123,10 @@ static const struct usb_device_id option_ids[] = {
|
.driver_info = RSVD(3) },
|
{ USB_DEVICE(0x1508, 0x1001), /* Fibocom NL668 (IOT version) */
|
.driver_info = RSVD(4) | RSVD(5) | RSVD(6) },
|
- { USB_DEVICE(0x1782, 0x4d10) }, /* Fibocom L610 (AT mode) */
|
- { USB_DEVICE_INTERFACE_CLASS(0x1782, 0x4d11, 0xff) }, /* Fibocom L610 (ECM/RNDIS mode) */
|
{ USB_DEVICE(0x2cb7, 0x0104), /* Fibocom NL678 series */
|
.driver_info = RSVD(4) | RSVD(5) },
|
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0105, 0xff), /* Fibocom NL678 series */
|
.driver_info = RSVD(6) },
|
- { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0106, 0xff) }, /* Fibocom MA510 (ECM mode w/ diag intf.) */
|
- { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x010a, 0xff) }, /* Fibocom MA510 (ECM mode) */
|
{ USB_DEVICE_AND_INTERFACE_INFO(0x2cb7, 0x010b, 0xff, 0xff, 0x30) }, /* Fibocom FG150 Diag */
|
{ USB_DEVICE_AND_INTERFACE_INFO(0x2cb7, 0x010b, 0xff, 0, 0) }, /* Fibocom FG150 AT */
|
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a0, 0xff) }, /* Fibocom NL668-AM/NL652-EU (laptop MBIM) */
|
@@ -2175,7 +2137,6 @@ static const struct usb_device_id option_ids[] = {
|
{ USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1404, 0xff) }, /* GosunCn GM500 RNDIS */
|
{ USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1405, 0xff) }, /* GosunCn GM500 MBIM */
|
{ USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1406, 0xff) }, /* GosunCn GM500 ECM/NCM */
|
- { USB_DEVICE_AND_INTERFACE_INFO(OPPO_VENDOR_ID, OPPO_PRODUCT_R11, 0xff, 0xff, 0x30) },
|
{ } /* Terminating entry */
|
};
|
MODULE_DEVICE_TABLE(usb, option_ids);
|
@@ -2184,7 +2145,26 @@ MODULE_DEVICE_TABLE(usb, option_ids);
|
* recognizes separately, thus num_port=1.
|
*/
|
|
+#if 1 //Added by Quectel
|
+static void cfmakeraw(struct ktermios *t)
|
+{
|
+ t->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
|
+ t->c_oflag &= ~OPOST;
|
+ t->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
|
+ t->c_cflag &= ~(CSIZE|PARENB);
|
+ t->c_cflag |= CS8;
|
+ t->c_cc[VMIN] = 1;
|
+ t->c_cc[VTIME] = 0;
|
+}
|
+
|
+static void option_init_termios(struct tty_struct *tty)
|
+{
|
+ cfmakeraw(&tty->termios);
|
+}
|
+#endif
|
+
|
static struct usb_serial_driver option_1port_device = {
|
+ .init_termios = option_init_termios,
|
.driver = {
|
.owner = THIS_MODULE,
|
.name = "option1",
|
@@ -2209,6 +2189,9 @@ static struct usb_serial_driver option_1port_device = {
|
#ifdef CONFIG_PM
|
.suspend = usb_wwan_suspend,
|
.resume = usb_wwan_resume,
|
+#if 1 //Added by Quectel
|
+ .reset_resume = usb_wwan_resume,
|
+#endif
|
#endif
|
};
|
|
@@ -2233,6 +2216,35 @@ static int option_probe(struct usb_serial *serial,
|
&serial->interface->cur_altsetting->desc;
|
unsigned long device_flags = id->driver_info;
|
|
+#if 1 //Added by Quectel
|
+ //Quectel UC20's interface 4 can be used as USB Network device
|
+ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) && serial->dev->descriptor.idProduct == cpu_to_le16(0x9003)
|
+ && serial->interface->cur_altsetting->desc.bInterfaceNumber >= 4)
|
+ return -ENODEV;
|
+
|
+ //Quectel EC20(MDM9215)'s interface 4 can be used as USB Network device
|
+ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) && serial->dev->descriptor.idProduct == cpu_to_le16(0x9215)
|
+ && serial->interface->cur_altsetting->desc.bInterfaceNumber >= 4)
|
+ return -ENODEV;
|
+
|
+ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x2C7C)) {
|
+ __u16 idProduct = le16_to_cpu(serial->dev->descriptor.idProduct);
|
+ struct usb_interface_descriptor *intf = &serial->interface->cur_altsetting->desc;
|
+
|
+ if (intf->bInterfaceClass != 0xFF || intf->bInterfaceSubClass == 0x42) {
|
+ //ECM, RNDIS, NCM, MBIM, ACM, UAC, ADB
|
+ return -ENODEV;
|
+ }
|
+
|
+ if ((idProduct&0xF000) == 0x0000) {
|
+ //MDM interface 4 is QMI
|
+ if (intf->bInterfaceNumber == 4 && intf->bNumEndpoints == 3
|
+ && intf->bInterfaceSubClass == 0xFF && intf->bInterfaceProtocol == 0xFF)
|
+ return -ENODEV;
|
+ }
|
+ }
|
+#endif
|
+
|
/* Never bind to the CD-Rom emulation interface */
|
if (iface_desc->bInterfaceClass == USB_CLASS_MASS_STORAGE)
|
return -ENODEV;
|
@@ -2346,7 +2358,7 @@ static void option_instat_callback(struct urb *urb)
|
dev_dbg(dev, "%s: error %d\n", __func__, status);
|
|
/* Resubmit urb so we continue receiving IRQ data */
|
- if (status != -ESHUTDOWN && status != -ENOENT) {
|
+ if (status != -ESHUTDOWN && status != -ENOENT && status != -EPROTO) {
|
usb_mark_last_busy(port->serial->dev);
|
err = usb_submit_urb(urb, GFP_ATOMIC);
|
if (err)
|
diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c
|
index f21f25a8c..27e642dbd 100644
|
--- a/drivers/usb/serial/usb_wwan.c
|
+++ b/drivers/usb/serial/usb_wwan.c
|
@@ -227,7 +227,7 @@ static void usb_wwan_indat_callback(struct urb *urb)
|
__func__, status, endpoint);
|
|
/* don't resubmit on fatal errors */
|
- if (status == -ESHUTDOWN || status == -ENOENT)
|
+ if (status == -ESHUTDOWN || status == -ENOENT || status == -EPROTO)
|
return;
|
} else {
|
if (urb->actual_length) {
|
@@ -389,8 +389,7 @@ void usb_wwan_close(struct usb_serial_port *port)
|
|
/*
|
* Need to take susp_lock to make sure port is not already being
|
- * resumed, but no need to hold it due to the tty-port initialized
|
- * flag.
|
+ * resumed, but no need to hold it due to initialized
|
*/
|
spin_lock_irq(&intfdata->susp_lock);
|
if (--intfdata->open_ports == 0)
|
@@ -432,6 +431,19 @@ static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port,
|
usb_sndbulkpipe(serial->dev, endpoint) | dir,
|
buf, len, callback, ctx);
|
|
+#if 1 //Added by Quectel for Zero Packet
|
+ if (dir == USB_DIR_OUT) {
|
+ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) && serial->dev->descriptor.idProduct == cpu_to_le16(0x9090))
|
+ urb->transfer_flags |= URB_ZERO_PACKET;
|
+ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) && serial->dev->descriptor.idProduct == cpu_to_le16(0x9003))
|
+ urb->transfer_flags |= URB_ZERO_PACKET;
|
+ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) && serial->dev->descriptor.idProduct == cpu_to_le16(0x9215))
|
+ urb->transfer_flags |= URB_ZERO_PACKET;
|
+ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x2C7C))
|
+ urb->transfer_flags |= URB_ZERO_PACKET;
|
+ }
|
+#endif
|
+
|
if (intfdata->use_zlp && dir == USB_DIR_OUT)
|
urb->transfer_flags |= URB_ZERO_PACKET;
|
|
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
|
index a8823e317..60479eb03 100644
|
--- a/drivers/video/backlight/pwm_bl.c
|
+++ b/drivers/video/backlight/pwm_bl.c
|
@@ -552,6 +552,8 @@ static int pwm_backlight_probe(struct platform_device *pdev)
|
if (!state.period && (data->pwm_period_ns > 0))
|
state.period = data->pwm_period_ns;
|
|
+ state.enabled = true;/*add for eable default backlight*/
|
+
|
ret = pwm_apply_state(pb->pwm, &state);
|
if (ret) {
|
dev_err(&pdev->dev, "failed to apply initial PWM state: %d\n",
|
diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c
|
index 7e21829f2..d39d9ebf2 100644
|
--- a/sound/soc/fsl/fsl-asoc-card.c
|
+++ b/sound/soc/fsl/fsl-asoc-card.c
|
@@ -27,6 +27,7 @@
|
#include "../codecs/wm8962.h"
|
#include "../codecs/wm8960.h"
|
#include "../codecs/wm8994.h"
|
+#include "../codecs/nau8822.h"
|
|
#define CS427x_SYSCLK_MCLK 0
|
|
@@ -48,6 +49,7 @@ enum fsl_asoc_card_type {
|
CARD_WM8524,
|
CARD_SI476X,
|
CARD_WM8958,
|
+ CARD_NAU8822,
|
};
|
|
/**
|
@@ -59,6 +61,7 @@ enum fsl_asoc_card_type {
|
* @pll_id: PLL id for set_pll()
|
*/
|
struct codec_priv {
|
+ struct clk *mclk; /* add by weihuihong */
|
unsigned long mclk_freq;
|
unsigned long free_freq;
|
u32 mclk_id;
|
@@ -226,6 +229,8 @@ static int fsl_asoc_card_hw_params(struct snd_pcm_substream *substream,
|
|
/* Specific configuration for PLL */
|
if (codec_priv->pll_id && codec_priv->fll_id) {
|
+ if (!IS_ERR(codec_priv->mclk))
|
+ clk_prepare_enable(codec_priv->mclk); /* add by weihuihong for enable mclk for nau8822 */
|
if (priv->sample_format == SNDRV_PCM_FORMAT_S24_LE ||
|
priv->sample_format == SNDRV_PCM_FORMAT_S20_3LE)
|
pll_out = priv->sample_rate * 384;
|
@@ -334,6 +339,7 @@ static int fsl_asoc_card_hw_free(struct snd_pcm_substream *substream)
|
dev_err(dev, "failed to stop FLL: %d\n", ret);
|
return ret;
|
}
|
+ clk_disable_unprepare(codec_priv->mclk);/* add by weihuihong */
|
}
|
|
return 0;
|
@@ -764,6 +770,8 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
|
}
|
}
|
|
+ dev_info(codec_dev, "codec mclk freq is %ld", priv->codec_priv.mclk_freq); /* add by weihuihong */
|
+
|
/* Default sample rate and format, will be updated in hw_params() */
|
priv->sample_rate = 44100;
|
priv->sample_format = SNDRV_PCM_FORMAT_S16_LE;
|
@@ -813,6 +821,15 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
|
priv->codec_priv.pll_id = WM8960_SYSCLK_AUTO;
|
priv->dai_fmt |= SND_SOC_DAIFMT_CBM_CFM;
|
priv->card_type = CARD_WM8960;
|
+ } else if (of_device_is_compatible(np, "fsl,imx-audio-nau8822")) { /* add by weihuihong */
|
+ codec_dai_name = "nau8822-hifi";
|
+ priv->codec_priv.mclk_id = NAU8822_CLK_MCLK;
|
+ priv->codec_priv.fll_id = NAU8822_CLK_PLL;//second clk
|
+ priv->codec_priv.pll_id = NAU8822_CLK_PLL;
|
+ priv->dai_fmt |= SND_SOC_DAIFMT_CBM_CFM;
|
+ priv->card_type = CARD_NAU8822;
|
+ if (codec_dev)
|
+ priv->codec_priv.mclk = devm_clk_get(codec_dev, NULL);
|
} else if (of_device_is_compatible(np, "fsl,imx-audio-ac97")) {
|
codec_dai_name = "ac97-hifi";
|
priv->dai_fmt = SND_SOC_DAIFMT_AC97;
|
@@ -1171,6 +1188,7 @@ static const struct of_device_id fsl_asoc_card_dt_ids[] = {
|
{ .compatible = "fsl,imx-audio-wm8524", },
|
{ .compatible = "fsl,imx-audio-si476x", },
|
{ .compatible = "fsl,imx-audio-wm8958", },
|
+ { .compatible = "fsl,imx-audio-nau8822", },
|
{}
|
};
|
MODULE_DEVICE_TABLE(of, fsl_asoc_card_dt_ids);
|