firmware/br-ext-chip-goke/board/gk7205v200/kernel/patches/00_gk7205v200_kernel-4.9.37...

100393 lines
2.7 MiB
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

diff -urN linux-4.9.37/arch/alpha/kernel/.gitignore linux-4.9.y/arch/alpha/kernel/.gitignore
--- linux-4.9.37/arch/alpha/kernel/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/alpha/kernel/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-vmlinux.lds
diff -urN linux-4.9.37/arch/arc/boot/.gitignore linux-4.9.y/arch/arc/boot/.gitignore
--- linux-4.9.37/arch/arc/boot/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/arc/boot/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,2 +0,0 @@
-*.dtb*
-uImage
diff -urN linux-4.9.37/arch/arc/kernel/.gitignore linux-4.9.y/arch/arc/kernel/.gitignore
--- linux-4.9.37/arch/arc/kernel/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/arc/kernel/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-vmlinux.lds
diff -urN linux-4.9.37/arch/arm/boot/compressed/.gitignore linux-4.9.y/arch/arm/boot/compressed/.gitignore
--- linux-4.9.37/arch/arm/boot/compressed/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/arm/boot/compressed/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,17 +0,0 @@
-ashldi3.S
-bswapsdi2.S
-font.c
-lib1funcs.S
-hyp-stub.S
-piggy_data
-vmlinux
-vmlinux.lds
-
-# borrowed libfdt files
-fdt.c
-fdt.h
-fdt_ro.c
-fdt_rw.c
-fdt_wip.c
-libfdt.h
-libfdt_internal.h
diff -urN linux-4.9.37/arch/arm/boot/compressed/head.S linux-4.9.y/arch/arm/boot/compressed/head.S
--- linux-4.9.37/arch/arm/boot/compressed/head.S 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/arm/boot/compressed/head.S 2021-06-07 13:01:32.000000000 +0300
@@ -218,6 +218,21 @@
addcc r0, r0, pc
cmpcc r4, r0
orrcc r4, r4, #1 @ remember we skipped cache_on
+
+/*TODO all the Cortex-A7 Single Core must fix this bug */
+#if defined(CONFIG_ARCH_GK7205V200) || defined(CONFIG_ARCH_GK7205V300) \
+ || defined(CONFIG_ARCH_GK7202V300) || defined(CONFIG_ARCH_GK7605V100)
+/*
+ * This is a bug on Cortex-A7 MPCORE. see buglist of Cortex-A7
+ * The D-caches are disabled when ACTLR.SMP is set to 0 regardless of the
+ * value of the cache enable bit. so we must set SMP bit of ACTLR register
+ * before enable D cache
+ */
+ mrc p15, 0, r0, c1, c0, 1
+ orr r0, #(1 << 6)
+ mcr p15, 0, r0, c1, c0, 1
+#endif
+
blcs cache_on
restart: adr r0, LC0
diff -urN linux-4.9.37/arch/arm/boot/dts/gk7202v300-demb.dts linux-4.9.y/arch/arm/boot/dts/gk7202v300-demb.dts
--- linux-4.9.37/arch/arm/boot/dts/gk7202v300-demb.dts 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/arch/arm/boot/dts/gk7202v300-demb.dts 2021-06-07 13:01:32.000000000 +0300
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+/dts-v1/;
+#include "gk7202v300.dtsi"
+
+/ {
+ model = "Goke GK7202V300 DEMO Board";
+ compatible = "goke,gk7202v300";
+
+ memory {
+ device_type = "memory";
+ reg = <0x40000000 0x20000000>;
+ };
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&uart1 {
+ status = "disabled";
+};
+
+&uart2 {
+ status = "disabled";
+};
+
+&i2c_bus0 {
+ status = "okay";
+ clock-frequency = <100000>;
+};
+
+&i2c_bus1 {
+ status = "okay";
+ clock-frequency = <100000>;
+};
+
+&i2c_bus2 {
+ status = "okay";
+ clock-frequency = <100000>;
+};
+
+&spi_bus0{
+ status = "okay";
+ num-cs = <1>;
+
+ spidev@0 {
+ compatible = "rohm,dh2228fv";
+ reg = <0>;
+ pl022,interface = <0>;
+ pl022,com-mode = <0>;
+ spi-max-frequency = <50000000>;
+ };
+};
+
+&spi_bus1{
+ status = "okay";
+ num-cs = <2>;
+
+ spidev@0 {
+ compatible = "rohm,dh2228fv";
+ reg = <0>;
+ pl022,interface = <0>;
+ pl022,com-mode = <0>;
+ spi-max-frequency = <50000000>;
+ };
+ spidev@1 {
+ compatible = "rohm,dh2228fv";
+ reg = <1>;
+ pl022,interface = <0>;
+ pl022,com-mode = <0>;
+ spi-max-frequency = <50000000>;
+ };
+};
+
+&dual_timer0 {
+ status = "okay";
+};
+
+&mdio0 {
+ goke,phy-reset-delays-us = <10000 20000 150000>;
+ phy0: ethernet-phy@1 {
+ reg = <1>;
+ };
+};
+
+&femac {
+ mac-address = [00 00 00 00 00 00];
+ phy-mode = "mii";
+ phy-handle = <&phy0>;
+ status = "okay";
+};
+
+&sfc {
+ sfc {
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <160000000>;
+ };
+};
+
+&snfc {
+ nand {
+ compatible = "jedec,spi-nand";
+ reg = <0>;
+ spi-max-frequency = <160000000>;
+ };
+};
+
+&mmc0 {
+ status = "okay";
+};
+
+&mmc1 {
+ status = "okay";
+};
+
+&gpio_chip0 {
+ status = "okay";
+};
+
+&gpio_chip1 {
+ status = "okay";
+};
+
+&gpio_chip2 {
+ status = "okay";
+};
+
+&gpio_chip4 {
+ status = "okay";
+};
+
+&gpio_chip5 {
+ status = "okay";
+};
+
+&gpio_chip6 {
+ status = "okay";
+};
+
+&gpio_chip7 {
+ status = "okay";
+};
+
+&gpio_chip8 {
+ status = "okay";
+};
+
diff -urN linux-4.9.37/arch/arm/boot/dts/gk7202v300.dtsi linux-4.9.y/arch/arm/boot/dts/gk7202v300.dtsi
--- linux-4.9.37/arch/arm/boot/dts/gk7202v300.dtsi 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/arch/arm/boot/dts/gk7202v300.dtsi 2021-06-07 13:01:32.000000000 +0300
@@ -0,0 +1,625 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+#include "skeleton.dtsi"
+#include <dt-bindings/clock/gk7202v300-clock.h>
+/ {
+ aliases {
+ serial0 = &uart0;
+ serial1 = &uart1;
+ serial2 = &uart2;
+ i2c0 = &i2c_bus0;
+ i2c1 = &i2c_bus1;
+ i2c2 = &i2c_bus2;
+ spi0 = &spi_bus0;
+ spi1 = &spi_bus1;
+ gpio0 = &gpio_chip0;
+ gpio1 = &gpio_chip1;
+ gpio2 = &gpio_chip2;
+ gpio4 = &gpio_chip4;
+ gpio5 = &gpio_chip5;
+ gpio6 = &gpio_chip6;
+ gpio7 = &gpio_chip7;
+ gpio8 = &gpio_chip8;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ enable-method = "goke,gk7202v300";
+
+ cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7";
+ clock-frequency = <GK7202V300_FIXED_1000M>;
+ reg = <0>;
+ };
+ };
+
+ pmu {
+ compatible = "arm,armv7-pmu";
+ interrupts = <0 58 4>;
+ };
+
+ clock: clock@12010000 {
+ compatible = "goke,gk7202v300-clock", "syscon";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ #clock-cells = <1>;
+ #reset-cells = <2>;
+ reg = <0x12010000 0x1000>;
+ };
+
+ gic: interrupt-controller@10300000 {
+ compatible = "arm,cortex-a7-gic";
+ #interrupt-cells = <3>;
+ #address-cells = <0>;
+ interrupt-controller;
+ /* gic dist base, gic cpu base , no virtual support */
+ reg = <0x10301000 0x1000>, <0x10302000 0x100>;
+ };
+
+ syscounter {
+ compatible = "arm,armv7-timer";
+ interrupt-parent = <&gic>;
+ interrupts = <1 13 0xf08>,
+ <1 14 0xf08>;
+ clock-frequency = <50000000>;
+ };
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ interrupt-parent = <&gic>;
+ ranges;
+
+ clk_3m: clk_3m {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <3000000>;
+ };
+
+ clk_apb: clk_apb {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <50000000>;
+ };
+
+ pmu {
+ compatible = "arm,cortex-a7-pmu";
+ interrupts = <0 58 4>;
+ };
+
+ sysctrl: system-controller@12020000 {
+ compatible = "goke,sysctrl";
+ reg = <0x12020000 0x1000>;
+ reboot-offset = <0x4>;
+ #clock-cells = <1>;
+ };
+
+ iocfg_ctrl: iocfg-controller@100c0000 {
+ compatible = "syscon";
+ reg = <0x100C0000 0x10000>;
+ };
+
+ iocfg_ctrl2: iocfg-controller2@112c0000 {
+ compatible = "syscon";
+ reg = <0x112C0000 0x10000>;
+ };
+
+#ifdef CONFIG_EDMAC
+ edmac: edma-controller@100B0000 {
+ compatible = "goke,edmac";
+ reg = <0x100B0000 0x1000>;
+ interrupts = <0 38 4>;
+ clocks = <&clock GK7202V300_EDMAC_CLK>, <&clock GK7202V300_EDMAC_AXICLK>;
+ clock-names = "apb_pclk", "axi_aclk";
+ clock-cells = <2>;
+ resets = <&clock 0x194 0>;
+ reset-names = "dma-reset";
+ dma-requests = <32>;
+ dma-channels = <4>;
+ devid = <0>;
+ #dma-cells = <2>;
+ status = "okay";
+ };
+#endif
+ amba {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "arm,amba-bus";
+ ranges;
+
+ dual_timer0: dual_timer@12000000 {
+ compatible = "arm,sp804", "arm,primecell";
+ /* timer0 & timer1 */
+ interrupts = <0 5 4>;
+ reg = <0x12000000 0x1000>;
+ clocks = <&clk_3m>, <&clk_3m>, <&clk_apb>;
+ clock-names = "timer00", "timer01", "apb_pclk";
+ status = "disabled";
+ };
+
+ dual_timer1: dual_timer@12001000 {
+ compatible = "arm,sp804", "arm,primecell";
+ /* timer2 & timer3 */
+ interrupts = <0 6 4>;
+ reg = <0x12001000 0x1000>;
+ clocks = <&clk_3m>, <&clk_3m>, <&clk_apb>;
+ clock-names = "timer10", "timer11", "apb_pclk";
+ status = "disabled";
+ };
+
+ uart0: uart@12040000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x12040000 0x1000>;
+ interrupts = <0 7 4>;
+ clocks = <&clock GK7202V300_UART0_CLK>;
+ clock-names = "apb_pclk";
+ status = "disabled";
+ };
+
+ uart1: uart@12041000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x12041000 0x1000>;
+ interrupts = <0 8 4>;
+ clocks = <&clock GK7202V300_UART1_CLK>;
+ clock-names = "apb_pclk";
+#ifdef CONFIG_EDMAC
+ dmas = <&edmac 19 19>, <&edmac 18 18>;
+ dma-names = "tx","rx";
+#endif
+ status = "disabled";
+ };
+
+ uart2: uart@12042000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x12042000 0x1000>;
+ interrupts = <0 9 4>;
+ clocks = <&clock GK7202V300_UART2_CLK>;
+ clock-names = "apb_pclk";
+#ifdef CONFIG_EDMAC
+ dmas = <&edmac 21 21>, <&edmac 20 20>;
+ dma-names = "tx","rx";
+#endif
+ status = "disabled";
+ };
+ };
+
+ i2c_bus0: i2c@12060000 {
+ compatible = "goke,goke-i2c";
+ reg = <0x12060000 0x1000>;
+ clocks = <&clock GK7202V300_I2C0_CLK>;
+ status = "disabled";
+ };
+
+ i2c_bus1: i2c@12061000 {
+ compatible = "goke,goke-i2c";
+ reg = <0x12061000 0x1000>;
+ clocks = <&clock GK7202V300_I2C1_CLK>;
+ status = "disabled";
+ };
+
+ i2c_bus2: i2c@12062000 {
+ compatible = "goke,goke-i2c";
+ reg = <0x12062000 0x1000>;
+ clocks = <&clock GK7202V300_I2C2_CLK>;
+ status = "disabled";
+ };
+
+ spi_bus0: spi@12070000 {
+ compatible = "arm,pl022", "arm,primecell";
+ arm,primecell-periphid = <0x00041022>;
+ reg = <0x12070000 0x1000>;
+ interrupts = <0 14 4>;
+ clocks = <&clock GK7202V300_SPI0_CLK>;
+ clock-names = "apb_pclk";
+ #address-cells = <1>;
+ #size-cells = <0>;
+#ifdef CONFIG_EDMAC
+ dmas = <&edmac 27 27>, <&edmac 26 26>;
+ dma-names = "tx","rx";
+#endif
+ status = "disabled";
+ };
+
+ spi_bus1: spi@12071000 {
+ compatible = "arm,pl022", "arm,primecell";
+ arm,primecell-periphid = <0x00041022>;
+ reg = <0x12071000 0x1000>, <0x12028000 0x4>;
+ interrupts = <0 15 4>;
+ clocks = <&clock GK7202V300_SPI1_CLK>;
+ clock-names = "apb_pclk";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ num-cs = <2>;
+ spi_cs_sb = <2>;
+ spi_cs_mask_bit = <0x4>;//0100
+#ifdef CONFIG_EDMAC
+ dmas = <&edmac 29 29>, <&edmac 28 28>;
+ dma-names = "tx","rx";
+#endif
+ status = "disabled";
+ };
+
+ mdio0: mdio@10041100 {
+ compatible = "goke,femac-mdio";
+ reg = <0x10041100 0x10>,<0x12028024 0x4>;
+ clocks = <&clock GK7202V300_ETH0_CLK>;
+ clock-names = "mdio";
+ resets = <&clock 0x16c 3>;
+ reset-names = "internal-phy";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ femac: ethernet@10040000 {
+ compatible = "goke,femac";
+ reg = <0x10040000 0x1000>,<0x10041300 0x200>;
+ interrupts = <0 33 4>;
+ clocks = <&clock GK7202V300_ETH0_CLK>;
+ resets = <&clock 0x16c 0>;
+ reset-names = "mac";
+ };
+
+ fmc: flash-memory-controller@10000000 {
+ compatible = "goke,fmc";
+ reg = <0x10000000 0x1000>, <0x14000000 0x10000>;
+ reg-names = "control", "memory";
+ clocks = <&clock GK7202V300_FMC_CLK>;
+ max-dma-size = <0x2000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ sfc:spi-nor@0 {
+ compatible = "goke,fmc-spi-nor";
+ assigned-clocks = <&clock GK7202V300_FMC_CLK>;
+ assigned-clock-rates = <24000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ snfc:spi-nand@0 {
+ compatible = "goke,fmc-spi-nand";
+ assigned-clocks = <&clock GK7202V300_FMC_CLK>;
+ assigned-clock-rates = <24000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+
+ mmc0: sdhci@0x10010000 {
+ compatible = "goke,sdhci";
+ reg = <0x10010000 0x1000>;
+ interrupts = <0 30 4>;
+ clocks = <&clock GK7202V300_MMC0_CLK>;
+ clock-names = "mmc_clk";
+ resets = <&clock 0x1f4 27>, <&clock 0x1f4 29>;
+ reset-names = "crg_reset", "dll_reset";
+ max-frequency = <150000000>;
+ crg_regmap = <&clock>;
+ iocfg_regmap = <&iocfg_ctrl>;
+ bus-width = <4>;
+ cap-mmc-highspeed;
+ cap-mmc-hw-reset;
+ cap-sd-highspeed;
+ mmc-hs200-1_8v;
+ full-pwr-cycle;
+ devid = <0>;
+ status = "enable";
+ };
+
+ mmc1: sdhci@0x10020000 {
+ compatible = "goke,sdhci";
+ reg = <0x10020000 0x1000>;
+ interrupts = <0 31 4>;
+ clocks = <&clock GK7202V300_MMC1_CLK>;
+ clock-names = "mmc_clk";
+ resets = <&clock 0x22c 27>, <&clock 0x22c 29>;
+ reset-names = "crg_reset", "dll_reset";
+ max-frequency = <50000000>;
+ crg_regmap = <&clock>;
+ iocfg_regmap = <&iocfg_ctrl2>;
+ bus-width = <4>;
+ cap-sd-highspeed;
+ full-pwr-cycle;
+ devid = <2>;
+ status = "enable";
+ };
+
+ usb2_phy0: phy2-0 {
+ compatible = "goke,usbp2-phy";
+ reg = <0x100D0000 0x1000>,
+ <0x12010000 0x1000>,
+ <0x100c0000 0x1000>;
+ clocks = <&clock GK7202V300_USB2_PHY_APB_CLK>,
+ <&clock GK7202V300_USB2_PHY_PLL_CLK>,
+ <&clock GK7202V300_USB2_PHY_XO_CLK>;
+ clock-names = "clk_u2phy_apb_ref",
+ "clk_u2phy_pll_ref",
+ "clk_u2phy_xo_ref";
+ resets = <&clock 0x140 0>,
+ <&clock 0x140 1>;
+ reset-names = "phy_por_reset",
+ "phy_tpor_reset";
+ phy_pll_offset = <0x14>;
+ phy_pll_mask = <0x03>;
+ phy_pll_val = <0x00>;
+ crg_offset = <0x140>;
+ crg_defal_mask = <0x0c07>;
+ crg_defal_val = <0x0807>;
+ vbus_offset = <0x7c>;
+ vbus_val = <0x0531>;
+ pwren_offset = <0x80>;
+ pwren_val = <0x1>;
+ ana_cfg_0_eye_val = <0x0433cc23>;
+ ana_cfg_0_offset = <0x00>;
+ ana_cfg_2_eye_val = <0x00320f0f>;
+ ana_cfg_2_offset = <0x08>;
+ ana_cfg_4_eye_val = <0x655>;
+ ana_cfg_4_offset = <0x10>;
+ trim_otp_addr = <0x12028004>;
+ trim_otp_mask = <0x1f>;
+ trim_otp_bit_offset = <0x00>;
+ trim_otp_min = <0x09>;
+ trim_otp_max = <0x1d>;
+ #phy-cells = <0>;
+ };
+
+ usbdrd3_0: usb3-0{
+ compatible = "goke,dwusb2";
+ reg = <0x10030000 0x10000>,
+ <0x12010000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ crg_offset = <0x140>;
+ crg_ctrl_def_mask = <0x3308>;
+ crg_ctrl_def_val = <0x1308>;
+ clocks = <&clock GK7202V300_USB2_BUS_CLK>,
+ <&clock GK7202V300_USB2_REF_CLK>,
+ <&clock GK7202V300_USB2_UTMI_CLK>;
+ clock-names = "usb2_bus_clk",
+ "usb2_ref_clk",
+ "usb2_utmi_clk";
+ resets = <&clock 0x140 3>;
+ reset-names = "vcc_reset";
+ ranges;
+
+ dwc3@0x100e0000 {
+ compatible = "snps,dwc3";
+ reg = <0x10030000 0x10000>;
+ interrupts = <0 39 4>;
+ interrupt-names = "peripheral";
+ phys = <&usb2_phy0>;
+ phy-names = "usb2-phy";
+ maximum-speed = "high-speed";
+ dr_mode = "peripheral";
+ eps_directions = <0x6a>;
+ snps,eps_new_init;
+ eps_map=<0x0 0x1 0x2 0x3 0x4 0x5 0x7>;
+ snps,usb2-lpm-disable;
+ };
+ };
+
+ gpio_chip0: gpio_chip@120b0000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x120b0000 0x1000>;
+ interrupts = <0 16 4>;
+ clocks = <&clock GK7202V300_SYSAPB_CLK>;
+ clock-names = "apb_pclk";
+ #gpio-cells = <2>;
+ status = "disabled";
+ };
+
+ gpio_chip1: gpio_chip@120b1000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x120b1000 0x1000>;
+ interrupts = <0 17 4>;
+ clocks = <&clock GK7202V300_SYSAPB_CLK>;
+ clock-names = "apb_pclk";
+ #gpio-cells = <2>;
+ status = "disabled";
+ };
+
+ gpio_chip2: gpio_chip@120b2000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x120b2000 0x1000>;
+ interrupts = <0 18 4>;
+ clocks = <&clock GK7202V300_SYSAPB_CLK>;
+ clock-names = "apb_pclk";
+ #gpio-cells = <2>;
+ status = "disabled";
+ };
+
+ gpio_chip4: gpio_chip@120b4000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x120b4000 0x1000>;
+ interrupts = <0 20 4>;
+ clocks = <&clock GK7202V300_SYSAPB_CLK>;
+ clock-names = "apb_pclk";
+ #gpio-cells = <2>;
+ status = "disabled";
+ };
+
+ gpio_chip5: gpio_chip@120b5000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x120b5000 0x1000>;
+ interrupts = <0 21 4>;
+ clocks = <&clock GK7202V300_SYSAPB_CLK>;
+ clock-names = "apb_pclk";
+ #gpio-cells = <2>;
+ status = "disabled";
+ };
+
+ gpio_chip6: gpio_chip@120b6000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x120b6000 0x1000>;
+ interrupts = <0 22 4>;
+ clocks = <&clock GK7202V300_SYSAPB_CLK>;
+ clock-names = "apb_pclk";
+ #gpio-cells = <2>;
+ status = "disabled";
+ };
+
+ gpio_chip7: gpio_chip@120b7000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x120b7000 0x1000>;
+ interrupts = <0 23 4>;
+ clocks = <&clock GK7202V300_SYSAPB_CLK>;
+ clock-names = "apb_pclk";
+ #gpio-cells = <2>;
+ status = "disabled";
+ };
+
+ gpio_chip8: gpio_chip@120b8000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x120b8000 0x1000>;
+ interrupts = <0 24 4>;
+ clocks = <&clock GK7202V300_SYSAPB_CLK>;
+ clock-names = "apb_pclk";
+ #gpio-cells = <2>;
+ status = "disabled";
+ };
+
+ rtc: rtc@120e0000 {
+ compatible = "goke,rtc";
+ reg = <0x120e0000 0x1000>;
+ interrupts = <0 0 4>;
+ };
+
+ cipher: cipher@0x10050000 {
+ compatible = "goke,cipher";
+ reg = <0x10050000 0x10000>;
+ reg-names = "cipher";
+ interrupts = <0 34 4>, <0 34 4>;
+ interrupt-names = "cipher", "hash";
+ };
+
+ adc: adc@120a0000 {
+ compatible = "goke,lsadc";
+ reg = <0x120a0000 0x1000>;
+ interrupts = <0 4 4>;
+ interrupt-names = "adc";
+ resets = <&clock 0x1bc 2>;
+ reset-names = "lsadc-crg";
+ status = "okay";
+ };
+
+ wdg: wdg@0x12030000 {
+ compatible = "goke,wdg";
+ reg = <0x12030000 0x1000>;
+ reg-names = "wdg";
+ interrupts = <0 2 4>;
+ interrupt-names = "wdg";
+ };
+ };
+
+ media {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ interrupt-parent = <&gic>;
+ ranges;
+
+ osal: osal {
+ compatible = "goke,osal";
+ };
+
+ sys: sys@12010000 {
+ compatible = "goke,sys";
+ };
+
+ mipi: mipi@0x11240000 {
+ compatible = "goke,mipi";
+ reg = <0x11240000 0x10000>;
+ reg-names = "mipi_rx";
+ interrupts = <0 45 4>;
+ interrupt-names = "mipi_rx";
+ };
+
+ vi: vi@11000000 {
+ compatible = "goke,vi";
+ reg = <0x11000000 0x200000>, <0x11200000 0x40000>;
+ reg-names = "VI_CAP0", "VI_PROC0";
+ interrupts = <0 43 4>, <0 44 4>;
+ interrupt-names = "VI_CAP0", "VI_PROC0";
+ };
+
+ isp: isp@11220000 {
+ compatible = "goke,isp";
+ reg = <0x11220000 0x20000>;
+ reg-names = "ISP";
+ interrupts = <0 43 4>;
+ interrupt-names = "ISP";
+ };
+
+ vpss: vpss@11400000 {
+ compatible = "goke,vpss";
+ reg = <0x11400000 0x10000>;
+ reg-names = "vpss0";
+ interrupts = <0 46 4>;
+ interrupt-names = "vpss0";
+ };
+
+ vo: vo@11280000 {
+ compatible = "goke,vo";
+ reg = <0x11280000 0x40000>;
+ reg-names = "vo";
+ interrupts = <0 40 4>;
+ interrupt-names = "vo";
+ };
+
+ gfbg: gfbg@11280000 {
+ compatible = "goke,gfbg";
+ reg = <0x11280000 0x40000>;
+ reg-names = "gfbg";
+ interrupts = <0 41 4>;
+ interrupt-names = "gfbg";
+ };
+
+ vgs: vgs@11300000 {
+ compatible = "goke,vgs";
+ reg = <0x11300000 0x10000>;
+ reg-names = "vgs0";
+ interrupts = <0 49 4>;
+ interrupt-names = "vgs0";
+ };
+
+ gzip: gzip@11310000 {
+ compatible = "goke,gzip";
+ reg = <0x11310000 0x10000>;
+ reg-names = "gzip";
+ interrupts = <0 50 4>;
+ interrupt-names = "gzip";
+ };
+
+ vedu: vedu@11410000 {
+ compatible = "goke,vedu";
+ reg = <0x11410000 0x10000>, <0x11420000 0x10000>;
+ reg-names = "vedu0", "jpge";
+ interrupts = <0 47 4>, <0 48 4>;
+ interrupt-names = "vedu0","jpge";
+ };
+
+ venc: venc {
+ compatible = "goke,venc";
+ };
+
+ aiao: aiao@100e0000 {
+ compatible = "goke,aiao";
+ reg = <0x100e0000 0x10000>,<0x100f0000 0x10000>;
+ reg-names = "aiao","acodec";
+ interrupts = <0 42 4>;
+ interrupt-names = "AIO";
+ };
+
+ ive: ive@11320000 {
+ compatible = "goke,ive";
+ reg = <0x11320000 0x10000>;
+ reg-names = "ive";
+ interrupts = <0 51 4>;
+ interrupt-names = "ive";
+ };
+ };
+};
diff -urN linux-4.9.37/arch/arm/boot/dts/gk7205v200-demb.dts linux-4.9.y/arch/arm/boot/dts/gk7205v200-demb.dts
--- linux-4.9.37/arch/arm/boot/dts/gk7205v200-demb.dts 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/arch/arm/boot/dts/gk7205v200-demb.dts 2021-06-07 13:01:32.000000000 +0300
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+/dts-v1/;
+#include "gk7205v200.dtsi"
+
+/ {
+ model = "Goke GK7205V200 DEMO Board";
+ compatible = "goke,gk7205v200";
+
+ memory {
+ device_type = "memory";
+ reg = <0x40000000 0x20000000>;
+ };
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&uart1 {
+ status = "disabled";
+};
+
+&uart2 {
+ status = "disabled";
+};
+
+&i2c_bus0 {
+ status = "okay";
+ clock-frequency = <100000>;
+};
+
+&i2c_bus1 {
+ status = "okay";
+ clock-frequency = <100000>;
+};
+
+&i2c_bus2 {
+ status = "okay";
+ clock-frequency = <100000>;
+};
+
+&spi_bus0{
+ status = "okay";
+ num-cs = <1>;
+
+ spidev@0 {
+ compatible = "rohm,dh2228fv";
+ reg = <0>;
+ pl022,interface = <0>;
+ pl022,com-mode = <0>;
+ spi-max-frequency = <50000000>;
+ };
+};
+
+&spi_bus1{
+ status = "okay";
+ num-cs = <2>;
+
+ spidev@0 {
+ compatible = "rohm,dh2228fv";
+ reg = <0>;
+ pl022,interface = <0>;
+ pl022,com-mode = <0>;
+ spi-max-frequency = <50000000>;
+ };
+ spidev@1 {
+ compatible = "rohm,dh2228fv";
+ reg = <1>;
+ pl022,interface = <0>;
+ pl022,com-mode = <0>;
+ spi-max-frequency = <50000000>;
+ };
+};
+
+&dual_timer0 {
+ status = "okay";
+};
+
+&mdio0 {
+ goke,phy-reset-delays-us = <10000 20000 150000>;
+ phy0: ethernet-phy@1 {
+ reg = <1>;
+ };
+};
+
+&femac {
+ mac-address = [00 00 00 00 00 00];
+ phy-mode = "mii";
+ phy-handle = <&phy0>;
+ status = "okay";
+};
+
+&sfc {
+ sfc {
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <160000000>;
+ };
+};
+
+&snfc {
+ nand {
+ compatible = "jedec,spi-nand";
+ reg = <0>;
+ spi-max-frequency = <160000000>;
+ };
+};
+
+&mmc0 {
+ status = "okay";
+};
+
+&mmc1 {
+ status = "okay";
+};
+
+&gpio_chip0 {
+ status = "okay";
+};
+
+&gpio_chip1 {
+ status = "okay";
+};
+
+&gpio_chip2 {
+ status = "okay";
+};
+
+&gpio_chip4 {
+ status = "okay";
+};
+
+&gpio_chip5 {
+ status = "okay";
+};
+
+&gpio_chip6 {
+ status = "okay";
+};
+
+&gpio_chip7 {
+ status = "okay";
+};
+
+&gpio_chip8 {
+ status = "okay";
+};
+
diff -urN linux-4.9.37/arch/arm/boot/dts/gk7205v200.dtsi linux-4.9.y/arch/arm/boot/dts/gk7205v200.dtsi
--- linux-4.9.37/arch/arm/boot/dts/gk7205v200.dtsi 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/arch/arm/boot/dts/gk7205v200.dtsi 2021-06-07 13:01:32.000000000 +0300
@@ -0,0 +1,625 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+#include "skeleton.dtsi"
+#include <dt-bindings/clock/gk7205v200-clock.h>
+/ {
+ aliases {
+ serial0 = &uart0;
+ serial1 = &uart1;
+ serial2 = &uart2;
+ i2c0 = &i2c_bus0;
+ i2c1 = &i2c_bus1;
+ i2c2 = &i2c_bus2;
+ spi0 = &spi_bus0;
+ spi1 = &spi_bus1;
+ gpio0 = &gpio_chip0;
+ gpio1 = &gpio_chip1;
+ gpio2 = &gpio_chip2;
+ gpio4 = &gpio_chip4;
+ gpio5 = &gpio_chip5;
+ gpio6 = &gpio_chip6;
+ gpio7 = &gpio_chip7;
+ gpio8 = &gpio_chip8;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ enable-method = "goke,gk7205v200";
+
+ cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7";
+ clock-frequency = <GK7205V200_FIXED_1000M>;
+ reg = <0>;
+ };
+ };
+
+ pmu {
+ compatible = "arm,armv7-pmu";
+ interrupts = <0 58 4>;
+ };
+
+ clock: clock@12010000 {
+ compatible = "goke,gk7205v200-clock", "syscon";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ #clock-cells = <1>;
+ #reset-cells = <2>;
+ reg = <0x12010000 0x1000>;
+ };
+
+ gic: interrupt-controller@10300000 {
+ compatible = "arm,cortex-a7-gic";
+ #interrupt-cells = <3>;
+ #address-cells = <0>;
+ interrupt-controller;
+ /* gic dist base, gic cpu base , no virtual support */
+ reg = <0x10301000 0x1000>, <0x10302000 0x100>;
+ };
+
+ syscounter {
+ compatible = "arm,armv7-timer";
+ interrupt-parent = <&gic>;
+ interrupts = <1 13 0xf08>,
+ <1 14 0xf08>;
+ clock-frequency = <50000000>;
+ };
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ interrupt-parent = <&gic>;
+ ranges;
+
+ clk_3m: clk_3m {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <3000000>;
+ };
+
+ clk_apb: clk_apb {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <50000000>;
+ };
+
+ pmu {
+ compatible = "arm,cortex-a7-pmu";
+ interrupts = <0 58 4>;
+ };
+
+ sysctrl: system-controller@12020000 {
+ compatible = "goke,sysctrl";
+ reg = <0x12020000 0x1000>;
+ reboot-offset = <0x4>;
+ #clock-cells = <1>;
+ };
+
+ iocfg_ctrl: iocfg-controller@100c0000 {
+ compatible = "syscon";
+ reg = <0x100C0000 0x10000>;
+ };
+
+ iocfg_ctrl2: iocfg-controller2@112c0000 {
+ compatible = "syscon";
+ reg = <0x112C0000 0x10000>;
+ };
+
+#ifdef CONFIG_EDMAC
+ edmac: edma-controller@100B0000 {
+ compatible = "goke,edmac";
+ reg = <0x100B0000 0x1000>;
+ interrupts = <0 38 4>;
+ clocks = <&clock GK7205V200_EDMAC_CLK>, <&clock GK7205V200_EDMAC_AXICLK>;
+ clock-names = "apb_pclk", "axi_aclk";
+ clock-cells = <2>;
+ resets = <&clock 0x194 0>;
+ reset-names = "dma-reset";
+ dma-requests = <32>;
+ dma-channels = <4>;
+ devid = <0>;
+ #dma-cells = <2>;
+ status = "okay";
+ };
+#endif
+ amba {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "arm,amba-bus";
+ ranges;
+
+ dual_timer0: dual_timer@12000000 {
+ compatible = "arm,sp804", "arm,primecell";
+ /* timer0 & timer1 */
+ interrupts = <0 5 4>;
+ reg = <0x12000000 0x1000>;
+ clocks = <&clk_3m>, <&clk_3m>, <&clk_apb>;
+ clock-names = "timer00", "timer01", "apb_pclk";
+ status = "disabled";
+ };
+
+ dual_timer1: dual_timer@12001000 {
+ compatible = "arm,sp804", "arm,primecell";
+ /* timer2 & timer3 */
+ interrupts = <0 6 4>;
+ reg = <0x12001000 0x1000>;
+ clocks = <&clk_3m>, <&clk_3m>, <&clk_apb>;
+ clock-names = "timer10", "timer11", "apb_pclk";
+ status = "disabled";
+ };
+
+ uart0: uart@12040000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x12040000 0x1000>;
+ interrupts = <0 7 4>;
+ clocks = <&clock GK7205V200_UART0_CLK>;
+ clock-names = "apb_pclk";
+ status = "disabled";
+ };
+
+ uart1: uart@12041000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x12041000 0x1000>;
+ interrupts = <0 8 4>;
+ clocks = <&clock GK7205V200_UART1_CLK>;
+ clock-names = "apb_pclk";
+#ifdef CONFIG_EDMAC
+ dmas = <&edmac 19 19>, <&edmac 18 18>;
+ dma-names = "tx","rx";
+#endif
+ status = "disabled";
+ };
+
+ uart2: uart@12042000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x12042000 0x1000>;
+ interrupts = <0 9 4>;
+ clocks = <&clock GK7205V200_UART2_CLK>;
+ clock-names = "apb_pclk";
+#ifdef CONFIG_EDMAC
+ dmas = <&edmac 21 21>, <&edmac 20 20>;
+ dma-names = "tx","rx";
+#endif
+ status = "disabled";
+ };
+ };
+
+ i2c_bus0: i2c@12060000 {
+ compatible = "goke,goke-i2c";
+ reg = <0x12060000 0x1000>;
+ clocks = <&clock GK7205V200_I2C0_CLK>;
+ status = "disabled";
+ };
+
+ i2c_bus1: i2c@12061000 {
+ compatible = "goke,goke-i2c";
+ reg = <0x12061000 0x1000>;
+ clocks = <&clock GK7205V200_I2C1_CLK>;
+ status = "disabled";
+ };
+
+ i2c_bus2: i2c@12062000 {
+ compatible = "goke,goke-i2c";
+ reg = <0x12062000 0x1000>;
+ clocks = <&clock GK7205V200_I2C2_CLK>;
+ status = "disabled";
+ };
+
+ spi_bus0: spi@12070000 {
+ compatible = "arm,pl022", "arm,primecell";
+ arm,primecell-periphid = <0x00041022>;
+ reg = <0x12070000 0x1000>;
+ interrupts = <0 14 4>;
+ clocks = <&clock GK7205V200_SPI0_CLK>;
+ clock-names = "apb_pclk";
+ #address-cells = <1>;
+ #size-cells = <0>;
+#ifdef CONFIG_EDMAC
+ dmas = <&edmac 27 27>, <&edmac 26 26>;
+ dma-names = "tx","rx";
+#endif
+ status = "disabled";
+ };
+
+ spi_bus1: spi@12071000 {
+ compatible = "arm,pl022", "arm,primecell";
+ arm,primecell-periphid = <0x00041022>;
+ reg = <0x12071000 0x1000>, <0x12028000 0x4>;
+ interrupts = <0 15 4>;
+ clocks = <&clock GK7205V200_SPI1_CLK>;
+ clock-names = "apb_pclk";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ num-cs = <2>;
+ spi_cs_sb = <2>;
+ spi_cs_mask_bit = <0x4>;//0100
+#ifdef CONFIG_EDMAC
+ dmas = <&edmac 29 29>, <&edmac 28 28>;
+ dma-names = "tx","rx";
+#endif
+ status = "disabled";
+ };
+
+ mdio0: mdio@10041100 {
+ compatible = "goke,femac-mdio";
+ reg = <0x10041100 0x10>,<0x12028024 0x4>;
+ clocks = <&clock GK7205V200_ETH0_CLK>;
+ clock-names = "mdio";
+ resets = <&clock 0x16c 3>;
+ reset-names = "internal-phy";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ femac: ethernet@10040000 {
+ compatible = "goke,femac";
+ reg = <0x10040000 0x1000>,<0x10041300 0x200>;
+ interrupts = <0 33 4>;
+ clocks = <&clock GK7205V200_ETH0_CLK>;
+ resets = <&clock 0x16c 0>;
+ reset-names = "mac";
+ };
+
+ fmc: flash-memory-controller@10000000 {
+ compatible = "goke,fmc";
+ reg = <0x10000000 0x1000>, <0x14000000 0x10000>;
+ reg-names = "control", "memory";
+ clocks = <&clock GK7205V200_FMC_CLK>;
+ max-dma-size = <0x2000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ sfc:spi-nor@0 {
+ compatible = "goke,fmc-spi-nor";
+ assigned-clocks = <&clock GK7205V200_FMC_CLK>;
+ assigned-clock-rates = <24000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ snfc:spi-nand@0 {
+ compatible = "goke,fmc-spi-nand";
+ assigned-clocks = <&clock GK7205V200_FMC_CLK>;
+ assigned-clock-rates = <24000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+
+ mmc0: sdhci@0x10010000 {
+ compatible = "goke,sdhci";
+ reg = <0x10010000 0x1000>;
+ interrupts = <0 30 4>;
+ clocks = <&clock GK7205V200_MMC0_CLK>;
+ clock-names = "mmc_clk";
+ resets = <&clock 0x1f4 27>, <&clock 0x1f4 29>;
+ reset-names = "crg_reset", "dll_reset";
+ max-frequency = <150000000>;
+ crg_regmap = <&clock>;
+ iocfg_regmap = <&iocfg_ctrl>;
+ bus-width = <4>;
+ cap-mmc-highspeed;
+ cap-mmc-hw-reset;
+ cap-sd-highspeed;
+ mmc-hs200-1_8v;
+ full-pwr-cycle;
+ devid = <0>;
+ status = "enable";
+ };
+
+ mmc1: sdhci@0x10020000 {
+ compatible = "goke,sdhci";
+ reg = <0x10020000 0x1000>;
+ interrupts = <0 31 4>;
+ clocks = <&clock GK7205V200_MMC1_CLK>;
+ clock-names = "mmc_clk";
+ resets = <&clock 0x22c 27>, <&clock 0x22c 29>;
+ reset-names = "crg_reset", "dll_reset";
+ max-frequency = <50000000>;
+ crg_regmap = <&clock>;
+ iocfg_regmap = <&iocfg_ctrl2>;
+ bus-width = <4>;
+ cap-sd-highspeed;
+ full-pwr-cycle;
+ devid = <2>;
+ status = "enable";
+ };
+
+ usb2_phy0: phy2-0 {
+ compatible = "goke,usbp2-phy";
+ reg = <0x100D0000 0x1000>,
+ <0x12010000 0x1000>,
+ <0x100c0000 0x1000>;
+ clocks = <&clock GK7205V200_USB2_PHY_APB_CLK>,
+ <&clock GK7205V200_USB2_PHY_PLL_CLK>,
+ <&clock GK7205V200_USB2_PHY_XO_CLK>;
+ clock-names = "clk_u2phy_apb_ref",
+ "clk_u2phy_pll_ref",
+ "clk_u2phy_xo_ref";
+ resets = <&clock 0x140 0>,
+ <&clock 0x140 1>;
+ reset-names = "phy_por_reset",
+ "phy_tpor_reset";
+ phy_pll_offset = <0x14>;
+ phy_pll_mask = <0x03>;
+ phy_pll_val = <0x00>;
+ crg_offset = <0x140>;
+ crg_defal_mask = <0x0c07>;
+ crg_defal_val = <0x0807>;
+ vbus_offset = <0x7c>;
+ vbus_val = <0x0531>;
+ pwren_offset = <0x80>;
+ pwren_val = <0x01>;
+ ana_cfg_0_eye_val = <0x0433cc23>;
+ ana_cfg_0_offset = <0x00>;
+ ana_cfg_2_eye_val = <0x00320f0f>;
+ ana_cfg_2_offset = <0x08>;
+ ana_cfg_4_eye_val = <0x655>;
+ ana_cfg_4_offset = <0x10>;
+ trim_otp_addr = <0x12028004>;
+ trim_otp_mask = <0x1f>;
+ trim_otp_bit_offset = <0x00>;
+ trim_otp_min = <0x09>;
+ trim_otp_max = <0x1d>;
+ #phy-cells = <0>;
+ };
+
+ usbdrd3_0: usb3-0{
+ compatible = "goke,dwusb2";
+ reg = <0x10030000 0x10000>,
+ <0x12010000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ crg_offset = <0x140>;
+ crg_ctrl_def_mask = <0x3308>;
+ crg_ctrl_def_val = <0x1308>;
+ clocks = <&clock GK7205V200_USB2_BUS_CLK>,
+ <&clock GK7205V200_USB2_REF_CLK>,
+ <&clock GK7205V200_USB2_UTMI_CLK>;
+ clock-names = "usb2_bus_clk",
+ "usb2_ref_clk",
+ "usb2_utmi_clk";
+ resets = <&clock 0x140 3>;
+ reset-names = "vcc_reset";
+ ranges;
+
+ dwc3@0x100e0000 {
+ compatible = "snps,dwc3";
+ reg = <0x10030000 0x10000>;
+ interrupts = <0 39 4>;
+ interrupt-names = "peripheral";
+ phys = <&usb2_phy0>;
+ phy-names = "usb2-phy";
+ maximum-speed = "high-speed";
+ dr_mode = "host";
+ eps_directions = <0x6a>;
+ snps,eps_new_init;
+ eps_map=<0x0 0x1 0x2 0x3 0x4 0x5 0x7>;
+ snps,usb2-lpm-disable;
+ };
+ };
+
+ gpio_chip0: gpio_chip@120b0000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x120b0000 0x1000>;
+ interrupts = <0 16 4>;
+ clocks = <&clock GK7205V200_SYSAPB_CLK>;
+ clock-names = "apb_pclk";
+ #gpio-cells = <2>;
+ status = "disabled";
+ };
+
+ gpio_chip1: gpio_chip@120b1000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x120b1000 0x1000>;
+ interrupts = <0 17 4>;
+ clocks = <&clock GK7205V200_SYSAPB_CLK>;
+ clock-names = "apb_pclk";
+ #gpio-cells = <2>;
+ status = "disabled";
+ };
+
+ gpio_chip2: gpio_chip@120b2000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x120b2000 0x1000>;
+ interrupts = <0 18 4>;
+ clocks = <&clock GK7205V200_SYSAPB_CLK>;
+ clock-names = "apb_pclk";
+ #gpio-cells = <2>;
+ status = "disabled";
+ };
+
+ gpio_chip4: gpio_chip@120b4000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x120b4000 0x1000>;
+ interrupts = <0 20 4>;
+ clocks = <&clock GK7205V200_SYSAPB_CLK>;
+ clock-names = "apb_pclk";
+ #gpio-cells = <2>;
+ status = "disabled";
+ };
+
+ gpio_chip5: gpio_chip@120b5000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x120b5000 0x1000>;
+ interrupts = <0 21 4>;
+ clocks = <&clock GK7205V200_SYSAPB_CLK>;
+ clock-names = "apb_pclk";
+ #gpio-cells = <2>;
+ status = "disabled";
+ };
+
+ gpio_chip6: gpio_chip@120b6000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x120b6000 0x1000>;
+ interrupts = <0 22 4>;
+ clocks = <&clock GK7205V200_SYSAPB_CLK>;
+ clock-names = "apb_pclk";
+ #gpio-cells = <2>;
+ status = "disabled";
+ };
+
+ gpio_chip7: gpio_chip@120b7000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x120b7000 0x1000>;
+ interrupts = <0 23 4>;
+ clocks = <&clock GK7205V200_SYSAPB_CLK>;
+ clock-names = "apb_pclk";
+ #gpio-cells = <2>;
+ status = "disabled";
+ };
+
+ gpio_chip8: gpio_chip@120b8000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x120b8000 0x1000>;
+ interrupts = <0 24 4>;
+ clocks = <&clock GK7205V200_SYSAPB_CLK>;
+ clock-names = "apb_pclk";
+ #gpio-cells = <2>;
+ status = "disabled";
+ };
+
+ rtc: rtc@120e0000 {
+ compatible = "goke,rtc";
+ reg = <0x120e0000 0x1000>;
+ interrupts = <0 0 4>;
+ };
+
+ cipher: cipher@0x10050000 {
+ compatible = "goke,cipher";
+ reg = <0x10050000 0x10000>;
+ reg-names = "cipher";
+ interrupts = <0 34 4>, <0 34 4>;
+ interrupt-names = "cipher", "hash";
+ };
+
+ adc: adc@120a0000 {
+ compatible = "goke,lsadc";
+ reg = <0x120a0000 0x1000>;
+ interrupts = <0 4 4>;
+ interrupt-names = "adc";
+ resets = <&clock 0x1bc 2>;
+ reset-names = "lsadc-crg";
+ status = "okay";
+ };
+
+ wdg: wdg@0x12030000 {
+ compatible = "goke,wdg";
+ reg = <0x12030000 0x1000>;
+ reg-names = "wdg";
+ interrupts = <0 2 4>;
+ interrupt-names = "wdg";
+ };
+ };
+
+ media {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ interrupt-parent = <&gic>;
+ ranges;
+
+ osal: osal {
+ compatible = "goke,osal";
+ };
+
+ sys: sys@12010000 {
+ compatible = "goke,sys";
+ };
+
+ mipi: mipi@0x11240000 {
+ compatible = "goke,mipi";
+ reg = <0x11240000 0x10000>;
+ reg-names = "mipi_rx";
+ interrupts = <0 45 4>;
+ interrupt-names = "mipi_rx";
+ };
+
+ vi: vi@11000000 {
+ compatible = "goke,vi";
+ reg = <0x11000000 0x200000>, <0x11200000 0x40000>;
+ reg-names = "VI_CAP0", "VI_PROC0";
+ interrupts = <0 43 4>, <0 44 4>;
+ interrupt-names = "VI_CAP0", "VI_PROC0";
+ };
+
+ isp: isp@11220000 {
+ compatible = "goke,isp";
+ reg = <0x11220000 0x20000>;
+ reg-names = "ISP";
+ interrupts = <0 43 4>;
+ interrupt-names = "ISP";
+ };
+
+ vpss: vpss@11400000 {
+ compatible = "goke,vpss";
+ reg = <0x11400000 0x10000>;
+ reg-names = "vpss0";
+ interrupts = <0 46 4>;
+ interrupt-names = "vpss0";
+ };
+
+ vo: vo@11280000 {
+ compatible = "goke,vo";
+ reg = <0x11280000 0x40000>;
+ reg-names = "vo";
+ interrupts = <0 40 4>;
+ interrupt-names = "vo";
+ };
+
+ gfbg: gfbg@11280000 {
+ compatible = "goke,gfbg";
+ reg = <0x11280000 0x40000>;
+ reg-names = "gfbg";
+ interrupts = <0 41 4>;
+ interrupt-names = "gfbg";
+ };
+
+ vgs: vgs@11300000 {
+ compatible = "goke,vgs";
+ reg = <0x11300000 0x10000>;
+ reg-names = "vgs0";
+ interrupts = <0 49 4>;
+ interrupt-names = "vgs0";
+ };
+
+ gzip: gzip@11310000 {
+ compatible = "goke,gzip";
+ reg = <0x11310000 0x10000>;
+ reg-names = "gzip";
+ interrupts = <0 50 4>;
+ interrupt-names = "gzip";
+ };
+
+ vedu: vedu@11410000 {
+ compatible = "goke,vedu";
+ reg = <0x11410000 0x10000>, <0x11420000 0x10000>;
+ reg-names = "vedu0", "jpge";
+ interrupts = <0 47 4>, <0 48 4>;
+ interrupt-names = "vedu0","jpge";
+ };
+
+ venc: venc {
+ compatible = "goke,venc";
+ };
+
+ aiao: aiao@100e0000 {
+ compatible = "goke,aiao";
+ reg = <0x100e0000 0x10000>,<0x100f0000 0x10000>;
+ reg-names = "aiao","acodec";
+ interrupts = <0 42 4>;
+ interrupt-names = "AIO";
+ };
+
+ ive: ive@11320000 {
+ compatible = "goke,ive";
+ reg = <0x11320000 0x10000>;
+ reg-names = "ive";
+ interrupts = <0 51 4>;
+ interrupt-names = "ive";
+ };
+ };
+};
diff -urN linux-4.9.37/arch/arm/boot/dts/gk7205v300-demb.dts linux-4.9.y/arch/arm/boot/dts/gk7205v300-demb.dts
--- linux-4.9.37/arch/arm/boot/dts/gk7205v300-demb.dts 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/arch/arm/boot/dts/gk7205v300-demb.dts 2021-06-07 13:01:32.000000000 +0300
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+/dts-v1/;
+#include "gk7205v300.dtsi"
+
+/ {
+ model = "Goke GK7205V300 DEMO Board";
+ compatible = "goke,gk7205v300";
+
+ memory {
+ device_type = "memory";
+ reg = <0x40000000 0x20000000>;
+ };
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&uart1 {
+ status = "disabled";
+};
+
+&uart2 {
+ status = "disabled";
+};
+
+&i2c_bus0 {
+ status = "okay";
+ clock-frequency = <100000>;
+};
+
+&i2c_bus1 {
+ status = "okay";
+ clock-frequency = <100000>;
+};
+
+&i2c_bus2 {
+ status = "okay";
+ clock-frequency = <100000>;
+};
+
+&spi_bus0{
+ status = "okay";
+ num-cs = <1>;
+
+ spidev@0 {
+ compatible = "rohm,dh2228fv";
+ reg = <0>;
+ pl022,interface = <0>;
+ pl022,com-mode = <0>;
+ spi-max-frequency = <50000000>;
+ };
+};
+
+&spi_bus1{
+ status = "okay";
+ num-cs = <2>;
+
+ spidev@0 {
+ compatible = "rohm,dh2228fv";
+ reg = <0>;
+ pl022,interface = <0>;
+ pl022,com-mode = <0>;
+ spi-max-frequency = <50000000>;
+ };
+ spidev@1 {
+ compatible = "rohm,dh2228fv";
+ reg = <1>;
+ pl022,interface = <0>;
+ pl022,com-mode = <0>;
+ spi-max-frequency = <50000000>;
+ };
+};
+
+&dual_timer0 {
+ status = "okay";
+};
+
+&mdio0 {
+ goke,phy-reset-delays-us = <10000 20000 150000>;
+ phy0: ethernet-phy@1 {
+ reg = <1>;
+ };
+};
+
+&femac {
+ mac-address = [00 00 00 00 00 00];
+ phy-mode = "mii";
+ phy-handle = <&phy0>;
+ status = "okay";
+};
+
+&sfc {
+ sfc {
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <160000000>;
+ };
+};
+
+&snfc {
+ nand {
+ compatible = "jedec,spi-nand";
+ reg = <0>;
+ spi-max-frequency = <160000000>;
+ };
+};
+
+&mmc0 {
+ status = "okay";
+};
+
+&mmc1 {
+ status = "okay";
+};
+
+&gpio_chip0 {
+ status = "okay";
+};
+
+&gpio_chip1 {
+ status = "okay";
+};
+
+&gpio_chip2 {
+ status = "okay";
+};
+
+&gpio_chip3 {
+ status = "okay";
+};
+
+&gpio_chip4 {
+ status = "okay";
+};
+
+&gpio_chip5 {
+ status = "okay";
+};
+
+&gpio_chip6 {
+ status = "okay";
+};
+
+&gpio_chip7 {
+ status = "okay";
+};
+
+&gpio_chip8 {
+ status = "okay";
+};
+
+&gpio_chip9 {
+ status = "okay";
+};
+
diff -urN linux-4.9.37/arch/arm/boot/dts/gk7205v300.dtsi linux-4.9.y/arch/arm/boot/dts/gk7205v300.dtsi
--- linux-4.9.37/arch/arm/boot/dts/gk7205v300.dtsi 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/arch/arm/boot/dts/gk7205v300.dtsi 2021-06-07 13:01:32.000000000 +0300
@@ -0,0 +1,644 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+#include "skeleton.dtsi"
+#include <dt-bindings/clock/gk7205v300-clock.h>
+/ {
+ aliases {
+ serial0 = &uart0;
+ serial1 = &uart1;
+ serial2 = &uart2;
+ i2c0 = &i2c_bus0;
+ i2c1 = &i2c_bus1;
+ i2c2 = &i2c_bus2;
+ spi0 = &spi_bus0;
+ spi1 = &spi_bus1;
+ gpio0 = &gpio_chip0;
+ gpio1 = &gpio_chip1;
+ gpio2 = &gpio_chip2;
+ gpio3 = &gpio_chip3;
+ gpio4 = &gpio_chip4;
+ gpio5 = &gpio_chip5;
+ gpio6 = &gpio_chip6;
+ gpio7 = &gpio_chip7;
+ gpio8 = &gpio_chip8;
+ gpio9 = &gpio_chip9;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ enable-method = "goke,gk7205v300";
+
+ cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7";
+ clock-frequency = <GK7205V300_FIXED_1000M>;
+ reg = <0>;
+ };
+ };
+
+ pmu {
+ compatible = "arm,armv7-pmu";
+ interrupts = <0 58 4>;
+ };
+
+ clock: clock@12010000 {
+ compatible = "goke,gk7205v300-clock", "syscon";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ #clock-cells = <1>;
+ #reset-cells = <2>;
+ reg = <0x12010000 0x1000>;
+ };
+
+ gic: interrupt-controller@10300000 {
+ compatible = "arm,cortex-a7-gic";
+ #interrupt-cells = <3>;
+ #address-cells = <0>;
+ interrupt-controller;
+ /* gic dist base, gic cpu base , no virtual support */
+ reg = <0x10301000 0x1000>, <0x10302000 0x100>;
+ };
+
+ syscounter {
+ compatible = "arm,armv7-timer";
+ interrupt-parent = <&gic>;
+ interrupts = <1 13 0xf08>,
+ <1 14 0xf08>;
+ clock-frequency = <50000000>;
+ };
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ interrupt-parent = <&gic>;
+ ranges;
+
+ clk_3m: clk_3m {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <3000000>;
+ };
+
+ clk_apb: clk_apb {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <50000000>;
+ };
+
+ pmu {
+ compatible = "arm,cortex-a7-pmu";
+ interrupts = <0 58 4>;
+ };
+
+ sysctrl: system-controller@12020000 {
+ compatible = "goke,sysctrl";
+ reg = <0x12020000 0x1000>;
+ reboot-offset = <0x4>;
+ #clock-cells = <1>;
+ };
+
+ iocfg_ctrl: iocfg-controller@100c0000 {
+ compatible = "syscon";
+ reg = <0x100C0000 0x10000>;
+ };
+
+#ifdef CONFIG_EDMAC
+ edmac: edma-controller@100B0000 {
+ compatible = "goke,edmac";
+ reg = <0x100B0000 0x1000>;
+ interrupts = <0 38 4>;
+ clocks = <&clock GK7205V300_EDMAC_CLK>, <&clock GK7205V300_EDMAC_AXICLK>;
+ clock-names = "apb_pclk", "axi_aclk";
+ clock-cells = <2>;
+ resets = <&clock 0x194 0>;
+ reset-names = "dma-reset";
+ dma-requests = <32>;
+ dma-channels = <4>;
+ devid = <0>;
+ #dma-cells = <2>;
+ status = "okay";
+ };
+#endif
+ amba {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "arm,amba-bus";
+ ranges;
+
+ dual_timer0: dual_timer@12000000 {
+ compatible = "arm,sp804", "arm,primecell";
+ /* timer0 & timer1 */
+ interrupts = <0 5 4>;
+ reg = <0x12000000 0x1000>;
+ clocks = <&clk_3m>, <&clk_3m>, <&clk_apb>;
+ clock-names = "timer00", "timer01", "apb_pclk";
+ status = "disabled";
+ };
+
+ dual_timer1: dual_timer@12001000 {
+ compatible = "arm,sp804", "arm,primecell";
+ /* timer2 & timer3 */
+ interrupts = <0 6 4>;
+ reg = <0x12001000 0x1000>;
+ clocks = <&clk_3m>, <&clk_3m>, <&clk_apb>;
+ clock-names = "timer10", "timer11", "apb_pclk";
+ status = "disabled";
+ };
+
+ uart0: uart@12040000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x12040000 0x1000>;
+ interrupts = <0 7 4>;
+ clocks = <&clock GK7205V300_UART0_CLK>;
+ clock-names = "apb_pclk";
+ status = "disabled";
+ };
+
+ uart1: uart@12041000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x12041000 0x1000>;
+ interrupts = <0 8 4>;
+ clocks = <&clock GK7205V300_UART1_CLK>;
+ clock-names = "apb_pclk";
+#ifdef CONFIG_EDMAC
+ dmas = <&edmac 19 19>, <&edmac 18 18>;
+ dma-names = "tx","rx";
+#endif
+ status = "disabled";
+ };
+
+ uart2: uart@12042000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x12042000 0x1000>;
+ interrupts = <0 9 4>;
+ clocks = <&clock GK7205V300_UART2_CLK>;
+ clock-names = "apb_pclk";
+#ifdef CONFIG_EDMAC
+ dmas = <&edmac 21 21>, <&edmac 20 20>;
+ dma-names = "tx","rx";
+#endif
+ status = "disabled";
+ };
+ };
+
+ i2c_bus0: i2c@12060000 {
+ compatible = "goke,goke-i2c";
+ reg = <0x12060000 0x1000>;
+ clocks = <&clock GK7205V300_I2C0_CLK>;
+ status = "disabled";
+ };
+
+ i2c_bus1: i2c@12061000 {
+ compatible = "goke,goke-i2c";
+ reg = <0x12061000 0x1000>;
+ clocks = <&clock GK7205V300_I2C1_CLK>;
+ status = "disabled";
+ };
+
+ i2c_bus2: i2c@12062000 {
+ compatible = "goke,goke-i2c";
+ reg = <0x12062000 0x1000>;
+ clocks = <&clock GK7205V300_I2C2_CLK>;
+ status = "disabled";
+ };
+
+ spi_bus0: spi@12070000 {
+ compatible = "arm,pl022", "arm,primecell";
+ arm,primecell-periphid = <0x00041022>;
+ reg = <0x12070000 0x1000>;
+ interrupts = <0 14 4>;
+ clocks = <&clock GK7205V300_SPI0_CLK>;
+ clock-names = "apb_pclk";
+ #address-cells = <1>;
+ #size-cells = <0>;
+#ifdef CONFIG_EDMAC
+ dmas = <&edmac 27 27>, <&edmac 26 26>;
+ dma-names = "tx","rx";
+#endif
+ status = "disabled";
+ };
+
+ spi_bus1: spi@12071000 {
+ compatible = "arm,pl022", "arm,primecell";
+ arm,primecell-periphid = <0x00041022>;
+ reg = <0x12071000 0x1000>, <0x12028000 0x4>;
+ interrupts = <0 15 4>;
+ clocks = <&clock GK7205V300_SPI1_CLK>;
+ clock-names = "apb_pclk";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ num-cs = <2>;
+ spi_cs_sb = <2>;
+ spi_cs_mask_bit = <0x4>;//0100
+#ifdef CONFIG_EDMAC
+ dmas = <&edmac 29 29>, <&edmac 28 28>;
+ dma-names = "tx","rx";
+#endif
+ status = "disabled";
+ };
+
+ mdio0: mdio@10041100 {
+ compatible = "goke,femac-mdio";
+ reg = <0x10041100 0x10>,<0x12028024 0x4>;
+ clocks = <&clock GK7205V300_ETH0_CLK>;
+ clock-names = "mdio";
+ resets = <&clock 0x16c 3>;
+ reset-names = "internal-phy";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ femac: ethernet@10040000 {
+ compatible = "goke,femac";
+ reg = <0x10040000 0x1000>,<0x10041300 0x200>;
+ interrupts = <0 33 4>;
+ clocks = <&clock GK7205V300_ETH0_CLK>;
+ resets = <&clock 0x16c 0>;
+ reset-names = "mac";
+ };
+
+ fmc: flash-memory-controller@10000000 {
+ compatible = "goke,fmc";
+ reg = <0x10000000 0x1000>, <0x14000000 0x10000>;
+ reg-names = "control", "memory";
+ clocks = <&clock GK7205V300_FMC_CLK>;
+ max-dma-size = <0x2000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ sfc:spi-nor@0 {
+ compatible = "goke,fmc-spi-nor";
+ assigned-clocks = <&clock GK7205V300_FMC_CLK>;
+ assigned-clock-rates = <24000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ snfc:spi-nand@0 {
+ compatible = "goke,fmc-spi-nand";
+ assigned-clocks = <&clock GK7205V300_FMC_CLK>;
+ assigned-clock-rates = <24000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+
+ mmc0: sdhci@0x10010000 {
+ compatible = "goke,sdhci";
+ reg = <0x10010000 0x1000>;
+ interrupts = <0 30 4>;
+ clocks = <&clock GK7205V300_MMC0_CLK>;
+ clock-names = "mmc_clk";
+ resets = <&clock 0x1f4 27>, <&clock 0x1f4 29>;
+ reset-names = "crg_reset", "dll_reset";
+ max-frequency = <90000000>;
+ crg_regmap = <&clock>;
+ iocfg_regmap = <&iocfg_ctrl>;
+ bus-width = <8>;
+ cap-mmc-highspeed;
+ cap-mmc-hw-reset;
+ cap-sd-highspeed;
+ mmc-hs200-1_8v;
+ mmc-hs400-1_8v;
+ mmc-hs400-enhanced-strobe;
+ full-pwr-cycle;
+ devid = <0>;
+ status = "enable";
+ };
+
+ mmc1: sdhci@0x10020000 {
+ compatible = "goke,sdhci";
+ reg = <0x10020000 0x1000>;
+ interrupts = <0 31 4>;
+ clocks = <&clock GK7205V300_MMC1_CLK>;
+ clock-names = "mmc_clk";
+ resets = <&clock 0x22c 27>, <&clock 0x22c 29>;
+ reset-names = "crg_reset", "dll_reset";
+ max-frequency = <50000000>;
+ crg_regmap = <&clock>;
+ iocfg_regmap = <&iocfg_ctrl>;
+ bus-width = <4>;
+ cap-sd-highspeed;
+ full-pwr-cycle;
+ devid = <2>;
+ status = "enable";
+ };
+
+ usb2_phy0: phy2-0 {
+ compatible = "goke,usbp2-phy";
+ reg = <0x100D0000 0x1000>,
+ <0x12010000 0x1000>,
+ <0x100c0000 0x1000>;
+ clocks = <&clock GK7205V300_USB2_PHY_APB_CLK>,
+ <&clock GK7205V300_USB2_PHY_PLL_CLK>,
+ <&clock GK7205V300_USB2_PHY_XO_CLK>;
+ clock-names = "clk_u2phy_apb_ref",
+ "clk_u2phy_pll_ref",
+ "clk_u2phy_xo_ref";
+ resets = <&clock 0x140 0>,
+ <&clock 0x140 1>;
+ reset-names = "phy_por_reset",
+ "phy_tpor_reset";
+ phy_pll_offset = <0x14>;
+ phy_pll_mask = <0x03>;
+ phy_pll_val = <0x00>;
+ crg_offset = <0x140>;
+ crg_defal_mask = <0x0c07>;
+ crg_defal_val = <0x0807>;
+ vbus_offset = <0x7c>;
+ vbus_val = <0x0431>;
+ pwren_offset = <0x80>;
+ pwren_val = <0x1>;
+ ana_cfg_0_eye_val = <0x0433cc23>;
+ ana_cfg_0_offset = <0x00>;
+ ana_cfg_2_eye_val = <0x00320f0f>;
+ ana_cfg_2_offset = <0x08>;
+ ana_cfg_4_eye_val = <0x655>;
+ ana_cfg_4_offset = <0x10>;
+ trim_otp_addr = <0x12028004>;
+ trim_otp_mask = <0x1f>;
+ trim_otp_bit_offset = <0x00>;
+ trim_otp_min = <0x09>;
+ trim_otp_max = <0x1d>;
+ #phy-cells = <0>;
+ };
+
+ usbdrd3_0: usb3-0{
+ compatible = "goke,dwusb2";
+ reg = <0x10030000 0x10000>,
+ <0x12010000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ crg_offset = <0x140>;
+ crg_ctrl_def_mask = <0x3308>;
+ crg_ctrl_def_val = <0x1308>;
+ clocks = <&clock GK7205V300_USB2_BUS_CLK>,
+ <&clock GK7205V300_USB2_REF_CLK>,
+ <&clock GK7205V300_USB2_UTMI_CLK>;
+ clock-names = "usb2_bus_clk",
+ "usb2_ref_clk",
+ "usb2_utmi_clk";
+ resets = <&clock 0x140 3>;
+ reset-names = "vcc_reset";
+ ranges;
+
+ dwc3@0x100e0000 {
+ compatible = "snps,dwc3";
+ reg = <0x10030000 0x10000>;
+ interrupts = <0 39 4>;
+ interrupt-names = "peripheral";
+ phys = <&usb2_phy0>;
+ phy-names = "usb2-phy";
+ maximum-speed = "high-speed";
+ dr_mode = "host";
+ eps_directions = <0x6a>;
+ snps,eps_new_init;
+ eps_map=<0x0 0x1 0x2 0x3 0x4 0x5 0x7>;
+ snps,usb2-lpm-disable;
+ };
+ };
+
+ gpio_chip0: gpio_chip@120b0000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x120b0000 0x1000>;
+ interrupts = <0 16 4>;
+ clocks = <&clock GK7205V300_SYSAPB_CLK>;
+ clock-names = "apb_pclk";
+ #gpio-cells = <2>;
+ status = "disabled";
+ };
+
+ gpio_chip1: gpio_chip@120b1000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x120b1000 0x1000>;
+ interrupts = <0 17 4>;
+ clocks = <&clock GK7205V300_SYSAPB_CLK>;
+ clock-names = "apb_pclk";
+ #gpio-cells = <2>;
+ status = "disabled";
+ };
+
+ gpio_chip2: gpio_chip@120b2000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x120b2000 0x1000>;
+ interrupts = <0 18 4>;
+ clocks = <&clock GK7205V300_SYSAPB_CLK>;
+ clock-names = "apb_pclk";
+ #gpio-cells = <2>;
+ status = "disabled";
+ };
+
+ gpio_chip3: gpio_chip@120b3000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x120b3000 0x1000>;
+ interrupts = <0 19 4>;
+ clocks = <&clock GK7205V300_SYSAPB_CLK>;
+ clock-names = "apb_pclk";
+ #gpio-cells = <2>;
+ status = "disabled";
+ };
+
+ gpio_chip4: gpio_chip@120b4000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x120b4000 0x1000>;
+ interrupts = <0 20 4>;
+ clocks = <&clock GK7205V300_SYSAPB_CLK>;
+ clock-names = "apb_pclk";
+ #gpio-cells = <2>;
+ status = "disabled";
+ };
+
+ gpio_chip5: gpio_chip@120b5000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x120b5000 0x1000>;
+ interrupts = <0 21 4>;
+ clocks = <&clock GK7205V300_SYSAPB_CLK>;
+ clock-names = "apb_pclk";
+ #gpio-cells = <2>;
+ status = "disabled";
+ };
+
+ gpio_chip6: gpio_chip@120b6000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x120b6000 0x1000>;
+ interrupts = <0 22 4>;
+ clocks = <&clock GK7205V300_SYSAPB_CLK>;
+ clock-names = "apb_pclk";
+ #gpio-cells = <2>;
+ status = "disabled";
+ };
+
+ gpio_chip7: gpio_chip@120b7000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x120b7000 0x1000>;
+ interrupts = <0 23 4>;
+ clocks = <&clock GK7205V300_SYSAPB_CLK>;
+ clock-names = "apb_pclk";
+ #gpio-cells = <2>;
+ status = "disabled";
+ };
+
+ gpio_chip8: gpio_chip@120b8000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x120b8000 0x1000>;
+ interrupts = <0 24 4>;
+ clocks = <&clock GK7205V300_SYSAPB_CLK>;
+ clock-names = "apb_pclk";
+ #gpio-cells = <2>;
+ status = "disabled";
+ };
+
+ gpio_chip9: gpio_chip@120b9000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x120b9000 0x1000>;
+ interrupts = <0 25 4>;
+ clocks = <&clock GK7205V300_SYSAPB_CLK>;
+ clock-names = "apb_pclk";
+ #gpio-cells = <2>;
+ status = "disabled";
+ };
+
+ rtc: rtc@120e0000 {
+ compatible = "goke,rtc";
+ reg = <0x120e0000 0x1000>;
+ interrupts = <0 0 4>;
+ };
+
+ cipher: cipher@0x10050000 {
+ compatible = "goke,cipher";
+ reg = <0x10050000 0x10000>;
+ reg-names = "cipher";
+ interrupts = <0 34 4>, <0 34 4>;
+ interrupt-names = "cipher", "hash";
+ };
+
+ adc: adc@120a0000 {
+ compatible = "goke,lsadc";
+ reg = <0x120a0000 0x1000>;
+ interrupts = <0 4 4>;
+ interrupt-names = "adc";
+ resets = <&clock 0x1bc 2>;
+ reset-names = "lsadc-crg";
+ status = "okay";
+ };
+
+ wdg: wdg@0x12030000 {
+ compatible = "goke,wdg";
+ reg = <0x12030000 0x1000>;
+ reg-names = "wdg";
+ interrupts = <0 2 4>;
+ interrupt-names = "wdg";
+ };
+ };
+
+ media {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ interrupt-parent = <&gic>;
+ ranges;
+
+ osal: osal {
+ compatible = "goke,osal";
+ };
+
+ sys: sys@12010000 {
+ compatible = "goke,sys";
+ };
+
+ mipi: mipi@0x11240000 {
+ compatible = "goke,mipi";
+ reg = <0x11240000 0x10000>;
+ reg-names = "mipi_rx";
+ interrupts = <0 45 4>;
+ interrupt-names = "mipi_rx";
+ };
+
+ vi: vi@11000000 {
+ compatible = "goke,vi";
+ reg = <0x11000000 0x200000>, <0x11200000 0x40000>;
+ reg-names = "VI_CAP0", "VI_PROC0";
+ interrupts = <0 43 4>, <0 44 4>;
+ interrupt-names = "VI_CAP0", "VI_PROC0";
+ };
+
+ isp: isp@11220000 {
+ compatible = "goke,isp";
+ reg = <0x11220000 0x20000>;
+ reg-names = "ISP";
+ interrupts = <0 43 4>;
+ interrupt-names = "ISP";
+ };
+
+ vpss: vpss@11400000 {
+ compatible = "goke,vpss";
+ reg = <0x11400000 0x10000>;
+ reg-names = "vpss0";
+ interrupts = <0 46 4>;
+ interrupt-names = "vpss0";
+ };
+
+ vo: vo@11280000 {
+ compatible = "goke,vo";
+ reg = <0x11280000 0x40000>;
+ reg-names = "vo";
+ interrupts = <0 40 4>;
+ interrupt-names = "vo";
+ };
+
+ gfbg: gfbg@11280000 {
+ compatible = "goke,gfbg";
+ reg = <0x11280000 0x40000>;
+ reg-names = "gfbg";
+ interrupts = <0 41 4>;
+ interrupt-names = "gfbg";
+ };
+
+ vgs: vgs@11300000 {
+ compatible = "goke,vgs";
+ reg = <0x11300000 0x10000>;
+ reg-names = "vgs0";
+ interrupts = <0 49 4>;
+ interrupt-names = "vgs0";
+ };
+
+ gzip: gzip@11310000 {
+ compatible = "goke,gzip";
+ reg = <0x11310000 0x10000>;
+ reg-names = "gzip";
+ interrupts = <0 50 4>;
+ interrupt-names = "gzip";
+ };
+
+ vedu: vedu@11410000 {
+ compatible = "goke,vedu";
+ reg = <0x11410000 0x10000>, <0x11420000 0x10000>;
+ reg-names = "vedu0", "jpge";
+ interrupts = <0 47 4>, <0 48 4>;
+ interrupt-names = "vedu0","jpge";
+ };
+
+ venc: venc {
+ compatible = "goke,venc";
+ };
+
+ aiao: aiao@100e0000 {
+ compatible = "goke,aiao";
+ reg = <0x100e0000 0x10000>,<0x100f0000 0x10000>;
+ reg-names = "aiao","acodec";
+ interrupts = <0 42 4>;
+ interrupt-names = "AIO";
+ };
+
+ ive: ive@11320000 {
+ compatible = "goke,ive";
+ reg = <0x11320000 0x10000>;
+ reg-names = "ive";
+ interrupts = <0 51 4>;
+ interrupt-names = "ive";
+ };
+ };
+};
diff -urN linux-4.9.37/arch/arm/boot/dts/gk7605v100-demb.dts linux-4.9.y/arch/arm/boot/dts/gk7605v100-demb.dts
--- linux-4.9.37/arch/arm/boot/dts/gk7605v100-demb.dts 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/arch/arm/boot/dts/gk7605v100-demb.dts 2021-06-07 13:01:32.000000000 +0300
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+/dts-v1/;
+#include "gk7605v100.dtsi"
+
+/ {
+ model = "Goke GK7605V100 DEMO Board";
+ compatible = "goke,gk7605v100";
+
+ memory {
+ device_type = "memory";
+ reg = <0x40000000 0x20000000>;
+ };
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&uart1 {
+ status = "disabled";
+};
+
+&uart2 {
+ status = "disabled";
+};
+
+&i2c_bus0 {
+ status = "okay";
+ clock-frequency = <100000>;
+};
+
+&i2c_bus1 {
+ status = "okay";
+ clock-frequency = <100000>;
+};
+
+&i2c_bus2 {
+ status = "okay";
+ clock-frequency = <100000>;
+};
+
+&spi_bus0{
+ status = "okay";
+ num-cs = <1>;
+
+ spidev@0 {
+ compatible = "rohm,dh2228fv";
+ reg = <0>;
+ pl022,interface = <0>;
+ pl022,com-mode = <0>;
+ spi-max-frequency = <50000000>;
+ };
+};
+
+&spi_bus1{
+ status = "okay";
+ num-cs = <2>;
+
+ spidev@0 {
+ compatible = "rohm,dh2228fv";
+ reg = <0>;
+ pl022,interface = <0>;
+ pl022,com-mode = <0>;
+ spi-max-frequency = <50000000>;
+ };
+ spidev@1 {
+ compatible = "rohm,dh2228fv";
+ reg = <1>;
+ pl022,interface = <0>;
+ pl022,com-mode = <0>;
+ spi-max-frequency = <50000000>;
+ };
+};
+
+&dual_timer0 {
+ status = "okay";
+};
+
+&mdio0 {
+ goke,phy-reset-delays-us = <10000 20000 150000>;
+ phy0: ethernet-phy@1 {
+ reg = <1>;
+ };
+};
+
+&femac {
+ mac-address = [00 00 00 00 00 00];
+ phy-mode = "mii";
+ phy-handle = <&phy0>;
+ status = "okay";
+};
+
+&sfc {
+ sfc {
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <160000000>;
+ };
+};
+
+&snfc {
+ nand {
+ compatible = "jedec,spi-nand";
+ reg = <0>;
+ spi-max-frequency = <160000000>;
+ };
+};
+
+&mmc0 {
+ status = "okay";
+};
+
+&mmc1 {
+ status = "okay";
+};
+
+&gpio_chip0 {
+ status = "okay";
+};
+
+&gpio_chip1 {
+ status = "okay";
+};
+
+&gpio_chip2 {
+ status = "okay";
+};
+
+&gpio_chip3 {
+ status = "okay";
+};
+
+&gpio_chip4 {
+ status = "okay";
+};
+
+&gpio_chip5 {
+ status = "okay";
+};
+
+&gpio_chip6 {
+ status = "okay";
+};
+
+&gpio_chip7 {
+ status = "okay";
+};
+
+&gpio_chip8 {
+ status = "okay";
+};
+
+&gpio_chip9 {
+ status = "okay";
+};
+
diff -urN linux-4.9.37/arch/arm/boot/dts/gk7605v100.dtsi linux-4.9.y/arch/arm/boot/dts/gk7605v100.dtsi
--- linux-4.9.37/arch/arm/boot/dts/gk7605v100.dtsi 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/arch/arm/boot/dts/gk7605v100.dtsi 2021-06-07 13:01:32.000000000 +0300
@@ -0,0 +1,644 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+#include "skeleton.dtsi"
+#include <dt-bindings/clock/gk7605v100-clock.h>
+/ {
+ aliases {
+ serial0 = &uart0;
+ serial1 = &uart1;
+ serial2 = &uart2;
+ i2c0 = &i2c_bus0;
+ i2c1 = &i2c_bus1;
+ i2c2 = &i2c_bus2;
+ spi0 = &spi_bus0;
+ spi1 = &spi_bus1;
+ gpio0 = &gpio_chip0;
+ gpio1 = &gpio_chip1;
+ gpio2 = &gpio_chip2;
+ gpio3 = &gpio_chip3;
+ gpio4 = &gpio_chip4;
+ gpio5 = &gpio_chip5;
+ gpio6 = &gpio_chip6;
+ gpio7 = &gpio_chip7;
+ gpio8 = &gpio_chip8;
+ gpio9 = &gpio_chip9;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ enable-method = "goke,gk7605v100";
+
+ cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7";
+ clock-frequency = <GK7605V100_FIXED_1000M>;
+ reg = <0>;
+ };
+ };
+
+ pmu {
+ compatible = "arm,armv7-pmu";
+ interrupts = <0 58 4>;
+ };
+
+ clock: clock@12010000 {
+ compatible = "goke,gk7605v100-clock", "syscon";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ #clock-cells = <1>;
+ #reset-cells = <2>;
+ reg = <0x12010000 0x1000>;
+ };
+
+ gic: interrupt-controller@10300000 {
+ compatible = "arm,cortex-a7-gic";
+ #interrupt-cells = <3>;
+ #address-cells = <0>;
+ interrupt-controller;
+ /* gic dist base, gic cpu base , no virtual support */
+ reg = <0x10301000 0x1000>, <0x10302000 0x100>;
+ };
+
+ syscounter {
+ compatible = "arm,armv7-timer";
+ interrupt-parent = <&gic>;
+ interrupts = <1 13 0xf08>,
+ <1 14 0xf08>;
+ clock-frequency = <50000000>;
+ };
+
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ interrupt-parent = <&gic>;
+ ranges;
+
+ clk_3m: clk_3m {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <3000000>;
+ };
+
+ clk_apb: clk_apb {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <50000000>;
+ };
+
+ pmu {
+ compatible = "arm,cortex-a7-pmu";
+ interrupts = <0 58 4>;
+ };
+
+ sysctrl: system-controller@12020000 {
+ compatible = "goke,sysctrl";
+ reg = <0x12020000 0x1000>;
+ reboot-offset = <0x4>;
+ #clock-cells = <1>;
+ };
+
+ iocfg_ctrl: iocfg-controller@100c0000 {
+ compatible = "syscon";
+ reg = <0x100C0000 0x10000>;
+ };
+
+#ifdef CONFIG_EDMAC
+ edmac: edma-controller@100B0000 {
+ compatible = "goke,edmac";
+ reg = <0x100B0000 0x1000>;
+ interrupts = <0 38 4>;
+ clocks = <&clock GK7605V100_EDMAC_CLK>, <&clock GK7605V100_EDMAC_AXICLK>;
+ clock-names = "apb_pclk", "axi_aclk";
+ clock-cells = <2>;
+ resets = <&clock 0x194 0>;
+ reset-names = "dma-reset";
+ dma-requests = <32>;
+ dma-channels = <4>;
+ devid = <0>;
+ #dma-cells = <2>;
+ status = "okay";
+ };
+#endif
+ amba {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "arm,amba-bus";
+ ranges;
+
+ dual_timer0: dual_timer@12000000 {
+ compatible = "arm,sp804", "arm,primecell";
+ /* timer0 & timer1 */
+ interrupts = <0 5 4>;
+ reg = <0x12000000 0x1000>;
+ clocks = <&clk_3m>, <&clk_3m>, <&clk_apb>;
+ clock-names = "timer00", "timer01", "apb_pclk";
+ status = "disabled";
+ };
+
+ dual_timer1: dual_timer@12001000 {
+ compatible = "arm,sp804", "arm,primecell";
+ /* timer2 & timer3 */
+ interrupts = <0 6 4>;
+ reg = <0x12001000 0x1000>;
+ clocks = <&clk_3m>, <&clk_3m>, <&clk_apb>;
+ clock-names = "timer10", "timer11", "apb_pclk";
+ status = "disabled";
+ };
+
+ uart0: uart@12040000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x12040000 0x1000>;
+ interrupts = <0 7 4>;
+ clocks = <&clock GK7605V100_UART0_CLK>;
+ clock-names = "apb_pclk";
+ status = "disabled";
+ };
+
+ uart1: uart@12041000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x12041000 0x1000>;
+ interrupts = <0 8 4>;
+ clocks = <&clock GK7605V100_UART1_CLK>;
+ clock-names = "apb_pclk";
+#ifdef CONFIG_EDMAC
+ dmas = <&edmac 19 19>, <&edmac 18 18>;
+ dma-names = "tx","rx";
+#endif
+ status = "disabled";
+ };
+
+ uart2: uart@12042000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x12042000 0x1000>;
+ interrupts = <0 9 4>;
+ clocks = <&clock GK7605V100_UART2_CLK>;
+ clock-names = "apb_pclk";
+#ifdef CONFIG_EDMAC
+ dmas = <&edmac 21 21>, <&edmac 20 20>;
+ dma-names = "tx","rx";
+#endif
+ status = "disabled";
+ };
+ };
+
+ i2c_bus0: i2c@12060000 {
+ compatible = "goke,goke-i2c";
+ reg = <0x12060000 0x1000>;
+ clocks = <&clock GK7605V100_I2C0_CLK>;
+ status = "disabled";
+ };
+
+ i2c_bus1: i2c@12061000 {
+ compatible = "goke,goke-i2c";
+ reg = <0x12061000 0x1000>;
+ clocks = <&clock GK7605V100_I2C1_CLK>;
+ status = "disabled";
+ };
+
+ i2c_bus2: i2c@12062000 {
+ compatible = "goke,goke-i2c";
+ reg = <0x12062000 0x1000>;
+ clocks = <&clock GK7605V100_I2C2_CLK>;
+ status = "disabled";
+ };
+
+ spi_bus0: spi@12070000 {
+ compatible = "arm,pl022", "arm,primecell";
+ arm,primecell-periphid = <0x00041022>;
+ reg = <0x12070000 0x1000>;
+ interrupts = <0 14 4>;
+ clocks = <&clock GK7605V100_SPI0_CLK>;
+ clock-names = "apb_pclk";
+ #address-cells = <1>;
+ #size-cells = <0>;
+#ifdef CONFIG_EDMAC
+ dmas = <&edmac 27 27>, <&edmac 26 26>;
+ dma-names = "tx","rx";
+#endif
+ status = "disabled";
+ };
+
+ spi_bus1: spi@12071000 {
+ compatible = "arm,pl022", "arm,primecell";
+ arm,primecell-periphid = <0x00041022>;
+ reg = <0x12071000 0x1000>, <0x12028000 0x4>;
+ interrupts = <0 15 4>;
+ clocks = <&clock GK7605V100_SPI1_CLK>;
+ clock-names = "apb_pclk";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ num-cs = <2>;
+ spi_cs_sb = <2>;
+ spi_cs_mask_bit = <0x4>;//0100
+#ifdef CONFIG_EDMAC
+ dmas = <&edmac 29 29>, <&edmac 28 28>;
+ dma-names = "tx","rx";
+#endif
+ status = "disabled";
+ };
+
+ mdio0: mdio@10041100 {
+ compatible = "goke,femac-mdio";
+ reg = <0x10041100 0x10>,<0x12028024 0x4>;
+ clocks = <&clock GK7605V100_ETH0_CLK>;
+ clock-names = "mdio";
+ resets = <&clock 0x16c 3>;
+ reset-names = "internal-phy";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ femac: ethernet@10040000 {
+ compatible = "goke,femac";
+ reg = <0x10040000 0x1000>,<0x10041300 0x200>;
+ interrupts = <0 33 4>;
+ clocks = <&clock GK7605V100_ETH0_CLK>;
+ resets = <&clock 0x16c 0>;
+ reset-names = "mac";
+ };
+
+ fmc: flash-memory-controller@10000000 {
+ compatible = "goke,fmc";
+ reg = <0x10000000 0x1000>, <0x14000000 0x10000>;
+ reg-names = "control", "memory";
+ clocks = <&clock GK7605V100_FMC_CLK>;
+ max-dma-size = <0x2000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ sfc:spi-nor@0 {
+ compatible = "goke,fmc-spi-nor";
+ assigned-clocks = <&clock GK7605V100_FMC_CLK>;
+ assigned-clock-rates = <24000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ snfc:spi-nand@0 {
+ compatible = "goke,fmc-spi-nand";
+ assigned-clocks = <&clock GK7605V100_FMC_CLK>;
+ assigned-clock-rates = <24000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+
+ mmc0: sdhci@0x10010000 {
+ compatible = "goke,sdhci";
+ reg = <0x10010000 0x1000>;
+ interrupts = <0 30 4>;
+ clocks = <&clock GK7605V100_MMC0_CLK>;
+ clock-names = "mmc_clk";
+ resets = <&clock 0x1f4 27>, <&clock 0x1f4 29>;
+ reset-names = "crg_reset", "dll_reset";
+ max-frequency = <90000000>;
+ crg_regmap = <&clock>;
+ iocfg_regmap = <&iocfg_ctrl>;
+ bus-width = <8>;
+ cap-mmc-highspeed;
+ cap-mmc-hw-reset;
+ cap-sd-highspeed;
+ mmc-hs200-1_8v;
+ mmc-hs400-1_8v;
+ mmc-hs400-enhanced-strobe;
+ full-pwr-cycle;
+ devid = <0>;
+ status = "enable";
+ };
+
+ mmc1: sdhci@0x10020000 {
+ compatible = "goke,sdhci";
+ reg = <0x10020000 0x1000>;
+ interrupts = <0 31 4>;
+ clocks = <&clock GK7605V100_MMC1_CLK>;
+ clock-names = "mmc_clk";
+ resets = <&clock 0x22c 27>, <&clock 0x22c 29>;
+ reset-names = "crg_reset", "dll_reset";
+ max-frequency = <50000000>;
+ crg_regmap = <&clock>;
+ iocfg_regmap = <&iocfg_ctrl>;
+ bus-width = <4>;
+ cap-sd-highspeed;
+ full-pwr-cycle;
+ devid = <2>;
+ status = "enable";
+ };
+
+ usb2_phy0: phy2-0 {
+ compatible = "goke,usbp2-phy";
+ reg = <0x100D0000 0x1000>,
+ <0x12010000 0x1000>,
+ <0x100c0000 0x1000>;
+ clocks = <&clock GK7605V100_USB2_PHY_APB_CLK>,
+ <&clock GK7605V100_USB2_PHY_PLL_CLK>,
+ <&clock GK7605V100_USB2_PHY_XO_CLK>;
+ clock-names = "clk_u2phy_apb_ref",
+ "clk_u2phy_pll_ref",
+ "clk_u2phy_xo_ref";
+ resets = <&clock 0x140 0>,
+ <&clock 0x140 1>;
+ reset-names = "phy_por_reset",
+ "phy_tpor_reset";
+ phy_pll_offset = <0x14>;
+ phy_pll_mask = <0x03>;
+ phy_pll_val = <0x00>;
+ crg_offset = <0x140>;
+ crg_defal_mask = <0x0c07>;
+ crg_defal_val = <0x0807>;
+ vbus_offset = <0x7c>;
+ vbus_val = <0x0431>;
+ pwren_offset = <0x80>;
+ pwren_val = <0x1>;
+ ana_cfg_0_eye_val = <0x0433cc23>;
+ ana_cfg_0_offset = <0x00>;
+ ana_cfg_2_eye_val = <0x00320f0f>;
+ ana_cfg_2_offset = <0x08>;
+ ana_cfg_4_eye_val = <0x655>;
+ ana_cfg_4_offset = <0x10>;
+ trim_otp_addr = <0x12028004>;
+ trim_otp_mask = <0x1f>;
+ trim_otp_bit_offset = <0x00>;
+ trim_otp_min = <0x09>;
+ trim_otp_max = <0x1d>;
+ #phy-cells = <0>;
+ };
+
+ usbdrd3_0: usb3-0{
+ compatible = "goke,dwusb2";
+ reg = <0x10030000 0x10000>,
+ <0x12010000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ crg_offset = <0x140>;
+ crg_ctrl_def_mask = <0x3308>;
+ crg_ctrl_def_val = <0x1308>;
+ clocks = <&clock GK7605V100_USB2_BUS_CLK>,
+ <&clock GK7605V100_USB2_REF_CLK>,
+ <&clock GK7605V100_USB2_UTMI_CLK>;
+ clock-names = "usb2_bus_clk",
+ "usb2_ref_clk",
+ "usb2_utmi_clk";
+ resets = <&clock 0x140 3>;
+ reset-names = "vcc_reset";
+ ranges;
+
+ dwc3@0x100e0000 {
+ compatible = "snps,dwc3";
+ reg = <0x10030000 0x10000>;
+ interrupts = <0 39 4>;
+ interrupt-names = "peripheral";
+ phys = <&usb2_phy0>;
+ phy-names = "usb2-phy";
+ maximum-speed = "high-speed";
+ dr_mode = "host";
+ eps_directions = <0x6a>;
+ snps,eps_new_init;
+ eps_map=<0x0 0x1 0x2 0x3 0x4 0x5 0x7>;
+ snps,usb2-lpm-disable;
+ };
+ };
+
+ gpio_chip0: gpio_chip@120b0000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x120b0000 0x1000>;
+ interrupts = <0 16 4>;
+ clocks = <&clock GK7605V100_SYSAPB_CLK>;
+ clock-names = "apb_pclk";
+ #gpio-cells = <2>;
+ status = "disabled";
+ };
+
+ gpio_chip1: gpio_chip@120b1000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x120b1000 0x1000>;
+ interrupts = <0 17 4>;
+ clocks = <&clock GK7605V100_SYSAPB_CLK>;
+ clock-names = "apb_pclk";
+ #gpio-cells = <2>;
+ status = "disabled";
+ };
+
+ gpio_chip2: gpio_chip@120b2000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x120b2000 0x1000>;
+ interrupts = <0 18 4>;
+ clocks = <&clock GK7605V100_SYSAPB_CLK>;
+ clock-names = "apb_pclk";
+ #gpio-cells = <2>;
+ status = "disabled";
+ };
+
+ gpio_chip3: gpio_chip@120b3000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x120b3000 0x1000>;
+ interrupts = <0 19 4>;
+ clocks = <&clock GK7605V100_SYSAPB_CLK>;
+ clock-names = "apb_pclk";
+ #gpio-cells = <2>;
+ status = "disabled";
+ };
+
+ gpio_chip4: gpio_chip@120b4000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x120b4000 0x1000>;
+ interrupts = <0 20 4>;
+ clocks = <&clock GK7605V100_SYSAPB_CLK>;
+ clock-names = "apb_pclk";
+ #gpio-cells = <2>;
+ status = "disabled";
+ };
+
+ gpio_chip5: gpio_chip@120b5000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x120b5000 0x1000>;
+ interrupts = <0 21 4>;
+ clocks = <&clock GK7605V100_SYSAPB_CLK>;
+ clock-names = "apb_pclk";
+ #gpio-cells = <2>;
+ status = "disabled";
+ };
+
+ gpio_chip6: gpio_chip@120b6000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x120b6000 0x1000>;
+ interrupts = <0 22 4>;
+ clocks = <&clock GK7605V100_SYSAPB_CLK>;
+ clock-names = "apb_pclk";
+ #gpio-cells = <2>;
+ status = "disabled";
+ };
+
+ gpio_chip7: gpio_chip@120b7000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x120b7000 0x1000>;
+ interrupts = <0 23 4>;
+ clocks = <&clock GK7605V100_SYSAPB_CLK>;
+ clock-names = "apb_pclk";
+ #gpio-cells = <2>;
+ status = "disabled";
+ };
+
+ gpio_chip8: gpio_chip@120b8000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x120b8000 0x1000>;
+ interrupts = <0 24 4>;
+ clocks = <&clock GK7605V100_SYSAPB_CLK>;
+ clock-names = "apb_pclk";
+ #gpio-cells = <2>;
+ status = "disabled";
+ };
+
+ gpio_chip9: gpio_chip@120b9000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0x120b9000 0x1000>;
+ interrupts = <0 25 4>;
+ clocks = <&clock GK7605V100_SYSAPB_CLK>;
+ clock-names = "apb_pclk";
+ #gpio-cells = <2>;
+ status = "disabled";
+ };
+
+ rtc: rtc@120e0000 {
+ compatible = "goke,rtc";
+ reg = <0x120e0000 0x1000>;
+ interrupts = <0 0 4>;
+ };
+
+ cipher: cipher@0x10050000 {
+ compatible = "goke,cipher";
+ reg = <0x10050000 0x10000>;
+ reg-names = "cipher";
+ interrupts = <0 34 4>, <0 34 4>;
+ interrupt-names = "cipher", "hash";
+ };
+
+ adc: adc@120a0000 {
+ compatible = "goke,lsadc";
+ reg = <0x120a0000 0x1000>;
+ interrupts = <0 4 4>;
+ interrupt-names = "adc";
+ resets = <&clock 0x1bc 2>;
+ reset-names = "lsadc-crg";
+ status = "okay";
+ };
+
+ wdg: wdg@0x12030000 {
+ compatible = "goke,wdg";
+ reg = <0x12030000 0x1000>;
+ reg-names = "wdg";
+ interrupts = <0 2 4>;
+ interrupt-names = "wdg";
+ };
+ };
+
+ media {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ interrupt-parent = <&gic>;
+ ranges;
+
+ osal: osal {
+ compatible = "goke,osal";
+ };
+
+ sys: sys@12010000 {
+ compatible = "goke,sys";
+ };
+
+ mipi: mipi@0x11240000 {
+ compatible = "goke,mipi";
+ reg = <0x11240000 0x10000>;
+ reg-names = "mipi_rx";
+ interrupts = <0 45 4>;
+ interrupt-names = "mipi_rx";
+ };
+
+ vi: vi@11000000 {
+ compatible = "goke,vi";
+ reg = <0x11000000 0x200000>, <0x11200000 0x40000>;
+ reg-names = "VI_CAP0", "VI_PROC0";
+ interrupts = <0 43 4>, <0 44 4>;
+ interrupt-names = "VI_CAP0", "VI_PROC0";
+ };
+
+ isp: isp@11220000 {
+ compatible = "goke,isp";
+ reg = <0x11220000 0x20000>;
+ reg-names = "ISP";
+ interrupts = <0 43 4>;
+ interrupt-names = "ISP";
+ };
+
+ vpss: vpss@11400000 {
+ compatible = "goke,vpss";
+ reg = <0x11400000 0x10000>;
+ reg-names = "vpss0";
+ interrupts = <0 46 4>;
+ interrupt-names = "vpss0";
+ };
+
+ vo: vo@11280000 {
+ compatible = "goke,vo";
+ reg = <0x11280000 0x40000>;
+ reg-names = "vo";
+ interrupts = <0 40 4>;
+ interrupt-names = "vo";
+ };
+
+ gfbg: gfbg@11280000 {
+ compatible = "goke,gfbg";
+ reg = <0x11280000 0x40000>;
+ reg-names = "gfbg";
+ interrupts = <0 41 4>;
+ interrupt-names = "gfbg";
+ };
+
+ vgs: vgs@11300000 {
+ compatible = "goke,vgs";
+ reg = <0x11300000 0x10000>;
+ reg-names = "vgs0";
+ interrupts = <0 49 4>;
+ interrupt-names = "vgs0";
+ };
+
+ gzip: gzip@11310000 {
+ compatible = "goke,gzip";
+ reg = <0x11310000 0x10000>;
+ reg-names = "gzip";
+ interrupts = <0 50 4>;
+ interrupt-names = "gzip";
+ };
+
+ vedu: vedu@11410000 {
+ compatible = "goke,vedu";
+ reg = <0x11410000 0x10000>, <0x11420000 0x10000>;
+ reg-names = "vedu0", "jpge";
+ interrupts = <0 47 4>, <0 48 4>;
+ interrupt-names = "vedu0","jpge";
+ };
+
+ venc: venc {
+ compatible = "goke,venc";
+ };
+
+ aiao: aiao@100e0000 {
+ compatible = "goke,aiao";
+ reg = <0x100e0000 0x10000>,<0x100f0000 0x10000>;
+ reg-names = "aiao","acodec";
+ interrupts = <0 42 4>;
+ interrupt-names = "AIO";
+ };
+
+ ive: ive@11320000 {
+ compatible = "goke,ive";
+ reg = <0x11320000 0x10000>;
+ reg-names = "ive";
+ interrupts = <0 51 4>;
+ interrupt-names = "ive";
+ };
+ };
+};
diff -urN linux-4.9.37/arch/arm/boot/dts/Makefile linux-4.9.y/arch/arm/boot/dts/Makefile
--- linux-4.9.37/arch/arm/boot/dts/Makefile 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/arm/boot/dts/Makefile 2021-06-07 13:01:32.000000000 +0300
@@ -174,6 +174,14 @@
hi3519-demb.dtb
dtb-$(CONFIG_ARCH_HIX5HD2) += \
hisi-x5hd2-dkb.dtb
+dtb-$(CONFIG_ARCH_GK7205V200) += \
+ gk7205v200-demb.dtb
+dtb-$(CONFIG_ARCH_GK7205V300) += \
+ gk7205v300-demb.dtb
+dtb-$(CONFIG_ARCH_GK7202V300) += \
+ gk7202v300-demb.dtb
+dtb-$(CONFIG_ARCH_GK7605V100) += \
+ gk7605v100-demb.dtb
dtb-$(CONFIG_ARCH_INTEGRATOR) += \
integratorap.dtb \
integratorcp.dtb
diff -urN linux-4.9.37/arch/arm/boot/.gitignore linux-4.9.y/arch/arm/boot/.gitignore
--- linux-4.9.37/arch/arm/boot/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/arm/boot/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,6 +0,0 @@
-Image
-zImage
-xipImage
-bootpImage
-uImage
-*.dtb
diff -urN linux-4.9.37/arch/arm/boot/Makefile linux-4.9.y/arch/arm/boot/Makefile
--- linux-4.9.37/arch/arm/boot/Makefile 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/arm/boot/Makefile 2021-06-07 13:01:32.000000000 +0300
@@ -16,6 +16,8 @@
ifneq ($(MACHINE),)
include $(MACHINE)/Makefile.boot
endif
+include $(srctree)/arch/arm/mach-goke/Makefile.boot
+include $(srctree)/arch/arm/boot/dts/Makefile
# Note: the following conditions must always be true:
# ZRELADDR == virt_to_phys(PAGE_OFFSET + TEXT_OFFSET)
@@ -24,10 +26,12 @@
ZRELADDR := $(zreladdr-y)
PARAMS_PHYS := $(params_phys-y)
INITRD_PHYS := $(initrd_phys-y)
+DTB_OBJS ?= $(dtb-y)
+DTB_OBJS_FULL := $(addprefix $(obj)/dts/,$(DTB_OBJS))
export ZRELADDR INITRD_PHYS PARAMS_PHYS
-targets := Image zImage xipImage bootpImage uImage
+targets := Image zImage xipImage bootpImage uImage zImage-dtb
ifeq ($(CONFIG_XIP_KERNEL),y)
@@ -55,6 +59,10 @@
$(obj)/zImage: $(obj)/compressed/vmlinux FORCE
$(call if_changed,objcopy)
+$(obj)/zImage-dtb: $(obj)/zImage $(DTB_OBJS_FULL) FORCE
+ @cat $(obj)/zImage $(DTB_OBJS_FULL) > $@
+ @$(kecho) ' Kernel: $@ is ready'
+
endif
ifneq ($(LOADADDR),)
@@ -75,7 +83,7 @@
false; \
fi
-$(obj)/uImage: $(obj)/zImage FORCE
+$(obj)/uImage: $(obj)/zImage-dtb FORCE
@$(check_for_multiple_loadaddr)
$(call if_changed,uimage)
diff -urN linux-4.9.37/arch/arm/configs/gk7202v300_emmc_defconfig linux-4.9.y/arch/arm/configs/gk7202v300_emmc_defconfig
--- linux-4.9.37/arch/arm/configs/gk7202v300_emmc_defconfig 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/arch/arm/configs/gk7202v300_emmc_defconfig 2021-06-07 13:01:32.000000000 +0300
@@ -0,0 +1,2858 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/arm 4.9.37 Kernel Configuration
+#
+CONFIG_ARM=y
+CONFIG_ARM_HAS_SG_CHAIN=y
+CONFIG_MIGHT_HAVE_PCI=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_ARM_PATCH_PHYS_VIRT=y
+CONFIG_GENERIC_BUG=y
+CONFIG_PGTABLE_LEVELS=2
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_IRQ_WORK=y
+CONFIG_BUILDTIME_EXTABLE_SORT=y
+
+#
+# General setup
+#
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+# CONFIG_COMPILE_TEST is not set
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_HAVE_KERNEL_LZ4=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_XZ is not set
+# CONFIG_KERNEL_LZO is not set
+# CONFIG_KERNEL_LZ4 is not set
+CONFIG_DEFAULT_HOSTNAME="(none)"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_CROSS_MEMORY_ATTACH=y
+CONFIG_FHANDLE=y
+CONFIG_USELIB=y
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_ARCH_AUDITSYSCALL=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_IRQ_DOMAIN_HIERARCHY=y
+CONFIG_HANDLE_DOMAIN_IRQ=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_ARCH_CLOCKSOURCE_DATA=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+
+#
+# Timers subsystem
+#
+CONFIG_HZ_PERIODIC=y
+# CONFIG_NO_HZ_IDLE is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set
+# CONFIG_IRQ_TIME_ACCOUNTING is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TINY_RCU=y
+# CONFIG_RCU_EXPERT is not set
+CONFIG_SRCU=y
+# CONFIG_TASKS_RCU is not set
+# CONFIG_RCU_STALL_COMMON is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_RCU_EXPEDITE_BOOT is not set
+# CONFIG_BUILD_BIN2C is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_NMI_LOG_BUF_SHIFT=13
+CONFIG_GENERIC_SCHED_CLOCK=y
+CONFIG_CGROUPS=y
+# CONFIG_MEMCG is not set
+# CONFIG_BLK_CGROUP is not set
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUP_PIDS is not set
+CONFIG_CGROUP_FREEZER=y
+# CONFIG_CPUSETS is not set
+# CONFIG_CGROUP_DEVICE is not set
+# CONFIG_CGROUP_CPUACCT is not set
+# CONFIG_CGROUP_DEBUG is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+CONFIG_NAMESPACES=y
+CONFIG_UTS_NS=y
+CONFIG_IPC_NS=y
+# CONFIG_USER_NS is not set
+CONFIG_PID_NS=y
+CONFIG_NET_NS=y
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_RD_XZ is not set
+# CONFIG_RD_LZO is not set
+CONFIG_RD_LZ4=y
+CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_HAVE_UID16=y
+CONFIG_BPF=y
+# CONFIG_EXPERT is not set
+CONFIG_UID16=y
+CONFIG_MULTIUSER=y
+# CONFIG_SGETMASK_SYSCALL is not set
+CONFIG_SYSFS_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set
+CONFIG_KALLSYMS_BASE_RELATIVE=y
+CONFIG_PRINTK=y
+CONFIG_PRINTK_NMI=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+# CONFIG_BPF_SYSCALL is not set
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_ADVISE_SYSCALLS=y
+# CONFIG_USERFAULTFD is not set
+CONFIG_MEMBARRIER=y
+# CONFIG_EMBEDDED is not set
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLAB_FREELIST_RANDOM is not set
+# CONFIG_SYSTEM_DATA_VERIFICATION is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+# CONFIG_JUMP_LABEL is not set
+# CONFIG_UPROBES is not set
+# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_ARCH_USE_BUILTIN_BSWAP=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_NMI=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_IDLE_POLL_SETUP=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_HAVE_GCC_PLUGINS=y
+# CONFIG_GCC_PLUGINS is not set
+CONFIG_HAVE_CC_STACKPROTECTOR=y
+CONFIG_CC_STACKPROTECTOR=y
+# CONFIG_CC_STACKPROTECTOR_NONE is not set
+# CONFIG_CC_STACKPROTECTOR_REGULAR is not set
+CONFIG_CC_STACKPROTECTOR_STRONG=y
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_MODULES_USE_ELF_REL=y
+CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_HAVE_ARCH_MMAP_RND_BITS=y
+CONFIG_HAVE_EXIT_THREAD=y
+CONFIG_ARCH_MMAP_RND_BITS_MIN=8
+CONFIG_ARCH_MMAP_RND_BITS_MAX=16
+CONFIG_ARCH_MMAP_RND_BITS=8
+# CONFIG_HAVE_ARCH_HASH is not set
+# CONFIG_ISA_BUS_API is not set
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_OLD_SIGACTION=y
+# CONFIG_CPU_NO_EFFICIENT_FFS is not set
+# CONFIG_HAVE_ARCH_VMAP_STACK is not set
+
+#
+# GCOV-based kernel profiling
+#
+CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_MODULE_SIG is not set
+# CONFIG_MODULE_COMPRESS is not set
+# CONFIG_TRIM_UNUSED_KSYMS is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+CONFIG_BLK_DEV_BSG=y
+# CONFIG_BLK_DEV_BSGLIB is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+CONFIG_BLK_CMDLINE_PARSER=y
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_AIX_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_CMDLINE_PARTITION=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+CONFIG_INLINE_READ_UNLOCK=y
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+CONFIG_INLINE_WRITE_UNLOCK=y
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+CONFIG_MMU=y
+CONFIG_ARCH_MULTIPLATFORM=y
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_LPC32XX is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C24XX is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP1 is not set
+
+#
+# Multiple platform selection
+#
+
+#
+# CPU Core family selection
+#
+# CONFIG_ARCH_MULTI_V6 is not set
+CONFIG_ARCH_MULTI_V7=y
+CONFIG_ARCH_MULTI_V6_V7=y
+# CONFIG_ARCH_MULTI_CPU_AUTO is not set
+# CONFIG_ARCH_VIRT is not set
+# CONFIG_ARCH_MVEBU is not set
+# CONFIG_ARCH_ALPINE is not set
+# CONFIG_ARCH_ARTPEC is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_BCM is not set
+# CONFIG_ARCH_BERLIN is not set
+# CONFIG_ARCH_DIGICOLOR is not set
+# CONFIG_ARCH_HIGHBANK is not set
+# CONFIG_ARCH_HISI is not set
+CONFIG_ARCH_GOKE=y
+
+#
+# Goke platform type
+#
+# CONFIG_ARCH_GK7205V200 is not set
+# CONFIG_ARCH_GK7205V300 is not set
+CONFIG_ARCH_GK7202V300=y
+# CONFIG_ARCH_GK7605V100 is not set
+# CONFIG_GOKE_MC is not set
+CONFIG_BSP_ZRELADDR=0x40008000
+CONFIG_BSP_PARAMS_PHYS=0x00000100
+CONFIG_BSP_INITRD_PHYS=0x00800000
+# CONFIG_ARCH_KEYSTONE is not set
+# CONFIG_ARCH_MESON is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_MEDIATEK is not set
+
+#
+# TI OMAP/AM/DM/DRA Family
+#
+# CONFIG_ARCH_OMAP3 is not set
+# CONFIG_ARCH_OMAP4 is not set
+# CONFIG_SOC_OMAP5 is not set
+# CONFIG_SOC_AM33XX is not set
+# CONFIG_SOC_AM43XX is not set
+# CONFIG_SOC_DRA7XX is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_QCOM is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_ROCKCHIP is not set
+# CONFIG_ARCH_SOCFPGA is not set
+# CONFIG_PLAT_SPEAR is not set
+# CONFIG_ARCH_STI is not set
+# CONFIG_ARCH_S5PV210 is not set
+# CONFIG_ARCH_EXYNOS is not set
+# CONFIG_ARCH_RENESAS is not set
+# CONFIG_ARCH_SUNXI is not set
+# CONFIG_ARCH_SIRF is not set
+# CONFIG_ARCH_TANGO is not set
+# CONFIG_ARCH_TEGRA is not set
+# CONFIG_ARCH_UNIPHIER is not set
+# CONFIG_ARCH_U8500 is not set
+# CONFIG_ARCH_VEXPRESS is not set
+# CONFIG_ARCH_WM8850 is not set
+# CONFIG_ARCH_ZX is not set
+# CONFIG_ARCH_ZYNQ is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_V7=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_LPAE is not set
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+CONFIG_ARM_THUMB=y
+# CONFIG_ARM_THUMBEE is not set
+CONFIG_ARM_VIRT_EXT=y
+# CONFIG_SWP_EMULATE is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_KUSER_HELPERS=y
+CONFIG_VDSO=y
+CONFIG_MIGHT_HAVE_CACHE_L2X0=y
+# CONFIG_CACHE_L2X0 is not set
+CONFIG_ARM_L1_CACHE_SHIFT_6=y
+CONFIG_ARM_L1_CACHE_SHIFT=6
+CONFIG_ARM_DMA_MEM_BUFFERABLE=y
+# CONFIG_DEBUG_RODATA is not set
+CONFIG_MULTI_IRQ_HANDLER=y
+# CONFIG_ARM_ERRATA_430973 is not set
+# CONFIG_ARM_ERRATA_720789 is not set
+# CONFIG_ARM_ERRATA_754322 is not set
+# CONFIG_ARM_ERRATA_775420 is not set
+# CONFIG_ARM_ERRATA_773022 is not set
+# CONFIG_ARM_ERRATA_818325_852422 is not set
+# CONFIG_ARM_ERRATA_821420 is not set
+# CONFIG_ARM_ERRATA_825619 is not set
+# CONFIG_ARM_ERRATA_852421 is not set
+# CONFIG_ARM_ERRATA_852423 is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS_GENERIC is not set
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_HAVE_SMP=y
+# CONFIG_SMP is not set
+CONFIG_HAVE_ARM_ARCH_TIMER=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_3G_OPT is not set
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_ARM_PSCI is not set
+CONFIG_ARCH_NR_GPIO=0
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ_FIXED=0
+CONFIG_HZ_100=y
+# CONFIG_HZ_200 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_500 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
+# CONFIG_SCHED_HRTICK is not set
+# CONFIG_THUMB2_KERNEL is not set
+CONFIG_ARM_PATCH_IDIV=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_HAVE_ARCH_PFN_VALID=y
+# CONFIG_HIGHMEM is not set
+# CONFIG_CPU_SW_DOMAIN_PAN is not set
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+# CONFIG_ARM_MODULE_PLTS is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_NO_BOOTMEM=y
+# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_COMPACTION=y
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NEED_PER_CPU_KM=y
+# CONFIG_CLEANCACHE is not set
+# CONFIG_CMA is not set
+# CONFIG_ZPOOL is not set
+# CONFIG_ZBUD is not set
+# CONFIG_ZSMALLOC is not set
+CONFIG_GENERIC_EARLY_IOREMAP=y
+# CONFIG_IDLE_PAGE_TRACKING is not set
+CONFIG_FRAME_VECTOR=y
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+# CONFIG_SECCOMP is not set
+CONFIG_SWIOTLB=y
+CONFIG_IOMMU_HELPER=y
+# CONFIG_PARAVIRT is not set
+# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set
+# CONFIG_XEN is not set
+
+#
+# Boot options
+#
+CONFIG_USE_OF=y
+CONFIG_ATAGS=y
+# CONFIG_DEPRECATED_PARAM_STRUCT is not set
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER=y
+# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set
+CONFIG_CMDLINE=""
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_AUTO_ZRELADDR=y
+# CONFIG_EFI is not set
+
+#
+# CPU Power Management
+#
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# CPU Idle
+#
+# CONFIG_CPU_IDLE is not set
+# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+# CONFIG_KERNEL_MODE_NEON is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_ELFCORE=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
+CONFIG_BINFMT_SCRIPT=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_COREDUMP=y
+
+#
+# Power management options
+#
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_PM_SLEEP=y
+# CONFIG_PM_AUTOSLEEP is not set
+# CONFIG_PM_WAKELOCKS is not set
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_APM_EMULATION is not set
+CONFIG_PM_CLK=y
+# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_CPU_PM=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARM_CPU_SUSPEND=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_DIAG is not set
+CONFIG_UNIX=y
+# CONFIG_UNIX_DIAG is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_ALGO=y
+CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+# CONFIG_IP_FIB_TRIE_STATS is not set
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
+# CONFIG_NET_IP_TUNNEL is not set
+CONFIG_IP_MROUTE=y
+# CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_NET_UDP_TUNNEL is not set
+# CONFIG_NET_FOU is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_INET_UDP_DIAG is not set
+# CONFIG_INET_DIAG_DESTROY is not set
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BIC=m
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+# CONFIG_TCP_CONG_HSTCP is not set
+# CONFIG_TCP_CONG_HYBLA is not set
+# CONFIG_TCP_CONG_VEGAS is not set
+# CONFIG_TCP_CONG_NV is not set
+# CONFIG_TCP_CONG_SCALABLE is not set
+# CONFIG_TCP_CONG_LP is not set
+# CONFIG_TCP_CONG_VENO is not set
+# CONFIG_TCP_CONG_YEAH is not set
+# CONFIG_TCP_CONG_ILLINOIS is not set
+# CONFIG_TCP_CONG_DCTCP is not set
+# CONFIG_TCP_CONG_CDG is not set
+# CONFIG_TCP_CONG_BBR is not set
+CONFIG_DEFAULT_CUBIC=y
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NET_PTP_CLASSIFY is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+CONFIG_DNS_RESOLVER=y
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+# CONFIG_VSOCKETS is not set
+# CONFIG_NETLINK_DIAG is not set
+# CONFIG_MPLS is not set
+# CONFIG_HSR is not set
+# CONFIG_NET_SWITCHDEV is not set
+# CONFIG_NET_L3_MASTER_DEV is not set
+# CONFIG_NET_NCSI is not set
+# CONFIG_SOCK_CGROUP_DATA is not set
+# CONFIG_CGROUP_NET_PRIO is not set
+# CONFIG_CGROUP_NET_CLASSID is not set
+CONFIG_NET_RX_BUSY_POLL=y
+CONFIG_BQL=y
+# CONFIG_BPF_JIT is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_AF_KCM is not set
+# CONFIG_STREAM_PARSER is not set
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_CFG80211=m
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+CONFIG_CFG80211_DEFAULT_PS=y
+# CONFIG_CFG80211_INTERNAL_REGDB is not set
+CONFIG_CFG80211_CRDA_SUPPORT=y
+CONFIG_CFG80211_WEXT=y
+# CONFIG_LIB80211 is not set
+CONFIG_MAC80211=m
+CONFIG_MAC80211_HAS_RC=y
+CONFIG_MAC80211_RC_MINSTREL=y
+CONFIG_MAC80211_RC_MINSTREL_HT=y
+# CONFIG_MAC80211_RC_MINSTREL_VHT is not set
+CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y
+CONFIG_MAC80211_RC_DEFAULT="minstrel_ht"
+CONFIG_MAC80211_MESH=y
+# CONFIG_MAC80211_MESSAGE_TRACING is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+CONFIG_MAC80211_STA_HASH_MAX_SIZE=0
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+# CONFIG_LWTUNNEL is not set
+# CONFIG_DST_CACHE is not set
+# CONFIG_NET_DEVLINK is not set
+CONFIG_MAY_USE_DEVLINK=y
+CONFIG_HAVE_CBPF_JIT=y
+
+#
+# Device Drivers
+#
+CONFIG_ARM_AMBA=y
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set
+CONFIG_ALLOW_DEV_COREDUMP=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+CONFIG_REGMAP=y
+CONFIG_REGMAP_I2C=y
+CONFIG_REGMAP_SPI=y
+CONFIG_REGMAP_MMIO=y
+CONFIG_DMA_SHARED_BUFFER=y
+# CONFIG_FENCE_TRACE is not set
+
+#
+# Bus devices
+#
+# CONFIG_BRCMSTB_GISB_ARB is not set
+# CONFIG_VEXPRESS_CONFIG is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+CONFIG_MTD_OF_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
+# CONFIG_MTD_OOPS is not set
+# CONFIG_MTD_PARTITIONED_MASTER is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SST25L is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOCG3 is not set
+CONFIG_MTD_NAND_ECC=y
+# CONFIG_MTD_NAND_ECC_SMC is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_ECC_BCH is not set
+# CONFIG_MTD_SM_COMMON is not set
+# CONFIG_MTD_NAND_DENALI_DT is not set
+# CONFIG_MTD_NAND_GPIO is not set
+# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_DOCG4 is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_BRCMNAND is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_NAND_HISI504 is not set
+# CONFIG_MTD_NAND_MTK is not set
+CONFIG_MTD_SPI_NAND_GOKE=y
+# CONFIG_GOKE_NAND_ECC_STATUS_REPORT is not set
+# CONFIG_GOKE_NAND_FS_MAY_NO_YAFFS2 is not set
+CONFIG_MTD_SPI_NAND_FMC100=y
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR & LPDDR2 PCM memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_LPDDR2_NVM is not set
+CONFIG_MTD_SPI_NOR=y
+# CONFIG_MTD_MT81xx_NOR is not set
+# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
+# CONFIG_SPI_CADENCE_QUADSPI is not set
+CONFIG_SPI_GOKE_SFC=y
+# CONFIG_CLOSE_SPI_8PIN_4IO is not set
+CONFIG_GOKE_SPI_BLOCK_PROTECT=y
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_LIMIT=20
+# CONFIG_MTD_UBI_FASTMAP is not set
+# CONFIG_MTD_UBI_GLUEBI is not set
+# CONFIG_MTD_UBI_BLOCK is not set
+CONFIG_DTC=y
+CONFIG_OF=y
+# CONFIG_OF_UNITTEST is not set
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_RESERVED_MEM=y
+# CONFIG_OF_OVERLAY is not set
+CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_NULL_BLK is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_DRBD is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=65536
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MG_DISK is not set
+# CONFIG_BLK_DEV_RBD is not set
+# CONFIG_NVME_TARGET is not set
+
+#
+# Misc devices
+#
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_DUMMY_IRQ is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_APDS9802ALS is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_ISL29020 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_BH1770 is not set
+# CONFIG_SENSORS_APDS990X is not set
+# CONFIG_HMC6352 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_TI_DAC7512 is not set
+# CONFIG_USB_SWITCH_FSA9480 is not set
+# CONFIG_LATTICE_ECP3_CONFIG is not set
+# CONFIG_SRAM is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_EEPROM_93XX46 is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+# CONFIG_SENSORS_LIS3_SPI is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
+
+#
+# Altera FPGA firmware download module
+#
+# CONFIG_ALTERA_STAPL is not set
+
+#
+# Intel MIC Bus Driver
+#
+
+#
+# SCIF Bus Driver
+#
+
+#
+# VOP Bus Driver
+#
+
+#
+# Intel MIC Host Driver
+#
+
+#
+# Intel MIC Card Driver
+#
+
+#
+# SCIF Driver
+#
+
+#
+# Intel MIC Coprocessor State Management (COSM) Drivers
+#
+
+#
+# VOP Driver
+#
+# CONFIG_ECHO is not set
+# CONFIG_CXL_BASE is not set
+# CONFIG_CXL_AFU_DRIVER_OPS is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+CONFIG_SCSI_NETLINK=y
+# CONFIG_SCSI_MQ_DEFAULT is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+CONFIG_SCSI_FC_ATTRS=y
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_ISCSI_BOOT_SYSFS is not set
+# CONFIG_SCSI_UFSHCD is not set
+# CONFIG_LIBFC is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_TARGET_CORE is not set
+# CONFIG_NETDEVICES is not set
+# CONFIG_NVM is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+# CONFIG_INPUT_MATRIXKMAP is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ADP5588 is not set
+# CONFIG_KEYBOARD_ADP5589 is not set
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_QT1070 is not set
+# CONFIG_KEYBOARD_QT2160 is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_KEYBOARD_GPIO_POLLED is not set
+# CONFIG_KEYBOARD_TCA6416 is not set
+# CONFIG_KEYBOARD_TCA8418 is not set
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_LM8333 is not set
+# CONFIG_KEYBOARD_MAX7359 is not set
+# CONFIG_KEYBOARD_MCS is not set
+# CONFIG_KEYBOARD_MPR121 is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_SAMSUNG is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_OMAP4 is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_CAP11XX is not set
+# CONFIG_KEYBOARD_BCM is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_BYD=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_CYPRESS=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_SENTELIC is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+CONFIG_MOUSE_PS2_FOCALTECH=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_CYAPA is not set
+# CONFIG_MOUSE_ELAN_I2C is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+# CONFIG_MOUSE_SYNAPTICS_I2C is not set
+# CONFIG_MOUSE_SYNAPTICS_USB is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_AD714X is not set
+# CONFIG_INPUT_ATMEL_CAPTOUCH is not set
+# CONFIG_INPUT_BMA150 is not set
+# CONFIG_INPUT_E3X0_BUTTON is not set
+# CONFIG_INPUT_MMA8450 is not set
+# CONFIG_INPUT_MPU3050 is not set
+# CONFIG_INPUT_GP2A is not set
+# CONFIG_INPUT_GPIO_BEEPER is not set
+# CONFIG_INPUT_GPIO_TILT_POLLED is not set
+# CONFIG_INPUT_GPIO_DECODER is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_KXTJ9 is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
+CONFIG_INPUT_UINPUT=y
+# CONFIG_INPUT_PCF8574 is not set
+# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
+# CONFIG_INPUT_ADXL34X is not set
+# CONFIG_INPUT_CMA3000 is not set
+# CONFIG_INPUT_DRV260X_HAPTICS is not set
+# CONFIG_INPUT_DRV2665_HAPTICS is not set
+# CONFIG_INPUT_DRV2667_HAPTICS is not set
+# CONFIG_RMI4_CORE is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_AMBAKMI is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_ALTERA_PS2 is not set
+# CONFIG_SERIO_PS2MULT is not set
+# CONFIG_SERIO_ARC_PS2 is not set
+# CONFIG_SERIO_APBPS2 is not set
+# CONFIG_USERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_TTY=y
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_VT_CONSOLE_SLEEP=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVMEM=y
+# CONFIG_DEVKMEM is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_EARLYCON=y
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_AMBA_PL010 is not set
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set
+# CONFIG_SERIAL_MAX3100 is not set
+# CONFIG_SERIAL_MAX310X is not set
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_SCCNXP is not set
+# CONFIG_SERIAL_SC16IS7XX is not set
+# CONFIG_SERIAL_BCM63XX is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_IFX6X60 is not set
+# CONFIG_SERIAL_XILINX_PS_UART is not set
+# CONFIG_SERIAL_ARC is not set
+# CONFIG_SERIAL_FSL_LPUART is not set
+# CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set
+# CONFIG_SERIAL_ST_ASC is not set
+# CONFIG_SERIAL_STM32 is not set
+# CONFIG_HVC_DCC is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_XILLYBUS is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MUX=y
+
+#
+# Multiplexer I2C Chip support
+#
+# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set
+# CONFIG_I2C_MUX_GPIO is not set
+# CONFIG_I2C_MUX_PCA9541 is not set
+# CONFIG_I2C_MUX_PCA954x is not set
+# CONFIG_I2C_MUX_PINCTRL is not set
+# CONFIG_I2C_MUX_REG is not set
+# CONFIG_I2C_DEMUX_PINCTRL is not set
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_CBUS_GPIO is not set
+# CONFIG_I2C_DESIGNWARE_PLATFORM is not set
+# CONFIG_I2C_EMEV2 is not set
+# CONFIG_I2C_GPIO is not set
+CONFIG_I2C_GOKE=y
+# CONFIG_I2C_NOMADIK is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_PXA_PCI is not set
+# CONFIG_I2C_RK3X is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_DIOLAN_U2C is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_ROBOTFUZZ_OSIF is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+CONFIG_DMA_MSG_MIN_LEN=5
+CONFIG_DMA_MSG_MAX_LEN=4090
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_SLAVE is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_ALTERA is not set
+# CONFIG_SPI_AXI_SPI_ENGINE is not set
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_CADENCE is not set
+# CONFIG_SPI_DESIGNWARE is not set
+# CONFIG_SPI_GPIO is not set
+# CONFIG_SPI_FSL_SPI is not set
+# CONFIG_SPI_OC_TINY is not set
+CONFIG_SPI_PL022=y
+# CONFIG_SPI_PXA2XX_PCI is not set
+# CONFIG_SPI_ROCKCHIP is not set
+# CONFIG_SPI_SC18IS602 is not set
+# CONFIG_SPI_XCOMM is not set
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_ZYNQMP_GQSPI is not set
+
+#
+# SPI Protocol Masters
+#
+CONFIG_SPI_SPIDEV=y
+# CONFIG_SPI_LOOPBACK_TEST is not set
+# CONFIG_SPI_TLE62X0 is not set
+# CONFIG_SPMI is not set
+# CONFIG_HSI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+# CONFIG_PTP_1588_CLOCK is not set
+
+#
+# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
+#
+CONFIG_PINCTRL=y
+
+#
+# Pin controllers
+#
+CONFIG_PINMUX=y
+CONFIG_PINCONF=y
+CONFIG_GENERIC_PINCONF=y
+# CONFIG_DEBUG_PINCTRL is not set
+# CONFIG_PINCTRL_AMD is not set
+CONFIG_PINCTRL_SINGLE=y
+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
+CONFIG_GPIOLIB=y
+CONFIG_OF_GPIO=y
+CONFIG_GPIOLIB_IRQCHIP=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO drivers
+#
+# CONFIG_GPIO_74XX_MMIO is not set
+# CONFIG_GPIO_ALTERA is not set
+# CONFIG_GPIO_DWAPB is not set
+# CONFIG_GPIO_EM is not set
+# CONFIG_GPIO_GENERIC_PLATFORM is not set
+# CONFIG_GPIO_GRGPIO is not set
+# CONFIG_GPIO_MOCKUP is not set
+# CONFIG_GPIO_MPC8XXX is not set
+CONFIG_GPIO_PL061=y
+# CONFIG_GPIO_SYSCON is not set
+# CONFIG_GPIO_XILINX is not set
+# CONFIG_GPIO_ZEVIO is not set
+# CONFIG_GPIO_ZX is not set
+
+#
+# I2C GPIO expanders
+#
+# CONFIG_GPIO_ADP5588 is not set
+# CONFIG_GPIO_ADNP is not set
+# CONFIG_GPIO_MAX7300 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_SX150X is not set
+# CONFIG_GPIO_TPIC2810 is not set
+# CONFIG_GPIO_TS4900 is not set
+
+#
+# MFD GPIO expanders
+#
+# CONFIG_HTC_EGPIO is not set
+
+#
+# SPI GPIO expanders
+#
+# CONFIG_GPIO_74X164 is not set
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MC33880 is not set
+# CONFIG_GPIO_PISOSR is not set
+
+#
+# SPI or I2C GPIO expanders
+#
+# CONFIG_GPIO_MCP23S08 is not set
+
+#
+# USB GPIO expanders
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_AVS is not set
+CONFIG_POWER_RESET=y
+# CONFIG_POWER_RESET_BRCMKONA is not set
+# CONFIG_POWER_RESET_BRCMSTB is not set
+CONFIG_POWER_RESET_GOKE=y
+# CONFIG_POWER_RESET_GPIO is not set
+# CONFIG_POWER_RESET_GPIO_RESTART is not set
+# CONFIG_POWER_RESET_LTC2952 is not set
+# CONFIG_POWER_RESET_RESTART is not set
+# CONFIG_POWER_RESET_VERSATILE is not set
+# CONFIG_POWER_RESET_SYSCON is not set
+# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set
+# CONFIG_SYSCON_REBOOT_MODE is not set
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_TEST_POWER is not set
+# CONFIG_BATTERY_DS2780 is not set
+# CONFIG_BATTERY_DS2781 is not set
+# CONFIG_BATTERY_DS2782 is not set
+# CONFIG_BATTERY_SBS is not set
+# CONFIG_BATTERY_BQ27XXX is not set
+# CONFIG_BATTERY_MAX17040 is not set
+# CONFIG_BATTERY_MAX17042 is not set
+# CONFIG_CHARGER_MAX8903 is not set
+# CONFIG_CHARGER_LP8727 is not set
+# CONFIG_CHARGER_GPIO is not set
+# CONFIG_CHARGER_BQ2415X is not set
+# CONFIG_CHARGER_BQ24190 is not set
+# CONFIG_CHARGER_BQ24257 is not set
+# CONFIG_CHARGER_BQ24735 is not set
+# CONFIG_CHARGER_BQ25890 is not set
+# CONFIG_CHARGER_SMB347 is not set
+# CONFIG_BATTERY_GAUGE_LTC2941 is not set
+# CONFIG_CHARGER_RT9455 is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+CONFIG_MFD_CORE=y
+# CONFIG_MFD_ACT8945A is not set
+# CONFIG_MFD_AS3711 is not set
+# CONFIG_MFD_AS3722 is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_AAT2870_CORE is not set
+# CONFIG_MFD_ATMEL_FLEXCOM is not set
+# CONFIG_MFD_ATMEL_HLCDC is not set
+# CONFIG_MFD_BCM590XX is not set
+# CONFIG_MFD_AXP20X_I2C is not set
+# CONFIG_MFD_CROS_EC is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_DA9052_SPI is not set
+# CONFIG_MFD_DA9052_I2C is not set
+# CONFIG_MFD_DA9055 is not set
+# CONFIG_MFD_DA9062 is not set
+# CONFIG_MFD_DA9063 is not set
+# CONFIG_MFD_DA9150 is not set
+# CONFIG_MFD_DLN2 is not set
+# CONFIG_MFD_EXYNOS_LPASS is not set
+# CONFIG_MFD_MC13XXX_SPI is not set
+# CONFIG_MFD_MC13XXX_I2C is not set
+# CONFIG_MFD_HI6421_PMIC is not set
+CONFIG_MFD_GOKE_FMC=y
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_HTC_I2CPLD is not set
+# CONFIG_INTEL_SOC_PMIC is not set
+# CONFIG_MFD_KEMPLD is not set
+# CONFIG_MFD_88PM800 is not set
+# CONFIG_MFD_88PM805 is not set
+# CONFIG_MFD_88PM860X is not set
+# CONFIG_MFD_MAX14577 is not set
+# CONFIG_MFD_MAX77620 is not set
+# CONFIG_MFD_MAX77686 is not set
+# CONFIG_MFD_MAX77693 is not set
+# CONFIG_MFD_MAX77843 is not set
+# CONFIG_MFD_MAX8907 is not set
+# CONFIG_MFD_MAX8925 is not set
+# CONFIG_MFD_MAX8997 is not set
+# CONFIG_MFD_MAX8998 is not set
+# CONFIG_MFD_MT6397 is not set
+# CONFIG_MFD_MENF21BMC is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_MFD_VIPERBOARD is not set
+# CONFIG_MFD_RETU is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_PM8921_CORE is not set
+# CONFIG_MFD_RT5033 is not set
+# CONFIG_MFD_RTSX_USB is not set
+# CONFIG_MFD_RC5T583 is not set
+# CONFIG_MFD_RK808 is not set
+# CONFIG_MFD_RN5T618 is not set
+# CONFIG_MFD_SEC_CORE is not set
+# CONFIG_MFD_SI476X_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_SKY81452 is not set
+# CONFIG_MFD_SMSC is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_MFD_STMPE is not set
+CONFIG_MFD_SYSCON=y
+# CONFIG_MFD_TI_AM335X_TSCADC is not set
+# CONFIG_MFD_LP3943 is not set
+# CONFIG_MFD_LP8788 is not set
+# CONFIG_MFD_PALMAS is not set
+# CONFIG_TPS6105X is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TPS6507X is not set
+# CONFIG_MFD_TPS65086 is not set
+# CONFIG_MFD_TPS65090 is not set
+# CONFIG_MFD_TPS65217 is not set
+# CONFIG_MFD_TI_LP873X is not set
+# CONFIG_MFD_TPS65218 is not set
+# CONFIG_MFD_TPS6586X is not set
+# CONFIG_MFD_TPS65910 is not set
+# CONFIG_MFD_TPS65912_I2C is not set
+# CONFIG_MFD_TPS65912_SPI is not set
+# CONFIG_MFD_TPS80031 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_TWL6040_CORE is not set
+# CONFIG_MFD_WL1273_CORE is not set
+# CONFIG_MFD_LM3533 is not set
+# CONFIG_MFD_TC3589X is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_MFD_ARIZONA_I2C is not set
+# CONFIG_MFD_ARIZONA_SPI is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X_I2C is not set
+# CONFIG_MFD_WM831X_SPI is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8994 is not set
+# CONFIG_REGULATOR is not set
+CONFIG_MEDIA_SUPPORT=y
+
+#
+# Multimedia core support
+#
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set
+# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set
+# CONFIG_MEDIA_RADIO_SUPPORT is not set
+# CONFIG_MEDIA_SDR_SUPPORT is not set
+# CONFIG_MEDIA_RC_SUPPORT is not set
+# CONFIG_MEDIA_CONTROLLER is not set
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L2=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEOBUF2_CORE=y
+CONFIG_VIDEOBUF2_MEMOPS=y
+CONFIG_VIDEOBUF2_VMALLOC=y
+# CONFIG_TTPCI_EEPROM is not set
+
+#
+# Media drivers
+#
+CONFIG_MEDIA_USB_SUPPORT=y
+
+#
+# Webcam devices
+#
+CONFIG_USB_VIDEO_CLASS=y
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+CONFIG_USB_GSPCA=m
+# CONFIG_USB_M5602 is not set
+# CONFIG_USB_STV06XX is not set
+# CONFIG_USB_GL860 is not set
+# CONFIG_USB_GSPCA_BENQ is not set
+# CONFIG_USB_GSPCA_CONEX is not set
+# CONFIG_USB_GSPCA_CPIA1 is not set
+# CONFIG_USB_GSPCA_DTCS033 is not set
+# CONFIG_USB_GSPCA_ETOMS is not set
+# CONFIG_USB_GSPCA_FINEPIX is not set
+# CONFIG_USB_GSPCA_JEILINJ is not set
+# CONFIG_USB_GSPCA_JL2005BCD is not set
+# CONFIG_USB_GSPCA_KINECT is not set
+# CONFIG_USB_GSPCA_KONICA is not set
+# CONFIG_USB_GSPCA_MARS is not set
+# CONFIG_USB_GSPCA_MR97310A is not set
+# CONFIG_USB_GSPCA_NW80X is not set
+# CONFIG_USB_GSPCA_OV519 is not set
+# CONFIG_USB_GSPCA_OV534 is not set
+# CONFIG_USB_GSPCA_OV534_9 is not set
+# CONFIG_USB_GSPCA_PAC207 is not set
+# CONFIG_USB_GSPCA_PAC7302 is not set
+# CONFIG_USB_GSPCA_PAC7311 is not set
+# CONFIG_USB_GSPCA_SE401 is not set
+# CONFIG_USB_GSPCA_SN9C2028 is not set
+# CONFIG_USB_GSPCA_SN9C20X is not set
+# CONFIG_USB_GSPCA_SONIXB is not set
+# CONFIG_USB_GSPCA_SONIXJ is not set
+# CONFIG_USB_GSPCA_SPCA500 is not set
+# CONFIG_USB_GSPCA_SPCA501 is not set
+# CONFIG_USB_GSPCA_SPCA505 is not set
+# CONFIG_USB_GSPCA_SPCA506 is not set
+# CONFIG_USB_GSPCA_SPCA508 is not set
+# CONFIG_USB_GSPCA_SPCA561 is not set
+# CONFIG_USB_GSPCA_SPCA1528 is not set
+# CONFIG_USB_GSPCA_SQ905 is not set
+# CONFIG_USB_GSPCA_SQ905C is not set
+# CONFIG_USB_GSPCA_SQ930X is not set
+# CONFIG_USB_GSPCA_STK014 is not set
+# CONFIG_USB_GSPCA_STK1135 is not set
+# CONFIG_USB_GSPCA_STV0680 is not set
+# CONFIG_USB_GSPCA_SUNPLUS is not set
+# CONFIG_USB_GSPCA_T613 is not set
+# CONFIG_USB_GSPCA_TOPRO is not set
+# CONFIG_USB_GSPCA_TOUPTEK is not set
+# CONFIG_USB_GSPCA_TV8532 is not set
+# CONFIG_USB_GSPCA_VC032X is not set
+# CONFIG_USB_GSPCA_VICAM is not set
+# CONFIG_USB_GSPCA_XIRLINK_CIT is not set
+# CONFIG_USB_GSPCA_ZC3XX is not set
+# CONFIG_USB_PWC is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_USB_ZR364XX is not set
+# CONFIG_USB_STKWEBCAM is not set
+# CONFIG_USB_S2255 is not set
+
+#
+# Webcam, TV (analog/digital) USB devices
+#
+# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_V4L_PLATFORM_DRIVERS is not set
+# CONFIG_V4L_MEM2MEM_DRIVERS is not set
+# CONFIG_V4L_TEST_DRIVERS is not set
+
+#
+# Supported MMC/SDIO adapters
+#
+# CONFIG_CYPRESS_FIRMWARE is not set
+
+#
+# Media ancillary drivers (tuners, sensors, i2c, spi, frontends)
+#
+CONFIG_MEDIA_SUBDRV_AUTOSELECT=y
+
+#
+# Audio decoders, processors and mixers
+#
+
+#
+# RDS decoders
+#
+
+#
+# Video decoders
+#
+
+#
+# Video and audio decoders
+#
+
+#
+# Video encoders
+#
+
+#
+# Camera sensor devices
+#
+
+#
+# Flash devices
+#
+
+#
+# Video improvement chips
+#
+
+#
+# Audio/Video compression chips
+#
+
+#
+# Miscellaneous helper chips
+#
+
+#
+# Sensors used on soc_camera driver
+#
+
+#
+# Tools to develop new frontends
+#
+# CONFIG_DVB_DUMMY_FE is not set
+
+#
+# Graphics support
+#
+# CONFIG_IMX_IPUV3_CORE is not set
+# CONFIG_DRM is not set
+
+#
+# ACP (Audio CoProcessor) Configuration
+#
+
+#
+# Frame buffer Devices
+#
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB_CMDLINE=y
+CONFIG_FB_NOTIFY=y
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_ARMCLCD is not set
+# CONFIG_FB_OPENCORES is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_SMSCUFX is not set
+# CONFIG_FB_UDL is not set
+# CONFIG_FB_IBM_GXT4500 is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_FB_AUO_K190X is not set
+# CONFIG_FB_SIMPLE is not set
+# CONFIG_FB_SSD1307 is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+# CONFIG_LOGO is not set
+# CONFIG_SOUND is not set
+
+#
+# HID support
+#
+CONFIG_HID=y
+# CONFIG_HID_BATTERY_STRENGTH is not set
+# CONFIG_HIDRAW is not set
+# CONFIG_UHID is not set
+CONFIG_HID_GENERIC=y
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_ACRUX is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_APPLEIR is not set
+# CONFIG_HID_AUREAL is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_BETOP_FF is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_CMEDIA is not set
+# CONFIG_HID_CP2112 is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EMS_FF is not set
+# CONFIG_HID_ELECOM is not set
+# CONFIG_HID_ELO is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_GEMBIRD is not set
+# CONFIG_HID_GFRM is not set
+# CONFIG_HID_HOLTEK is not set
+# CONFIG_HID_KEYTOUCH is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_UCLOGIC is not set
+# CONFIG_HID_WALTOP is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_ICADE is not set
+# CONFIG_HID_TWINHAN is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LCPOWER is not set
+# CONFIG_HID_LENOVO is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MAGICMOUSE is not set
+CONFIG_HID_MICROSOFT=y
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_MULTITOUCH is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_ORTEK is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PENMOUNT is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_PICOLCD is not set
+# CONFIG_HID_PLANTRONICS is not set
+# CONFIG_HID_PRIMAX is not set
+# CONFIG_HID_ROCCAT is not set
+# CONFIG_HID_SAITEK is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SPEEDLINK is not set
+# CONFIG_HID_STEELSERIES is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_RMI is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TIVO is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_WACOM is not set
+# CONFIG_HID_XINMO is not set
+# CONFIG_HID_ZEROPLUS is not set
+# CONFIG_HID_ZYDACRON is not set
+# CONFIG_HID_SENSOR_HUB is not set
+# CONFIG_HID_ALPS is not set
+
+#
+# USB HID support
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# I2C HID support
+#
+# CONFIG_I2C_HID is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_COMMON=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB=y
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEFAULT_PERSIST=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_PLATFORM=y
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+# CONFIG_USB_FOTG210_HCD is not set
+# CONFIG_USB_MAX3421_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HCD_TEST_MODE is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_REALTEK is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_STORAGE_ENE_UB6250 is not set
+# CONFIG_USB_UAS is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USBIP_CORE is not set
+# CONFIG_USB_MUSB_HDRC is not set
+CONFIG_USB_DWC3=y
+# CONFIG_USB_DWC3_HOST is not set
+# CONFIG_USB_DWC3_GADGET is not set
+CONFIG_USB_DWC3_DUAL_ROLE=y
+
+#
+# Platform Glue Driver Support
+#
+CONFIG_USB_DWC3_OF_SIMPLE=y
+# CONFIG_USB_DWC2 is not set
+# CONFIG_USB_CHIPIDEA is not set
+# CONFIG_USB_ISP1760 is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_EHSET_TEST_FIXTURE is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_YUREX is not set
+# CONFIG_USB_EZUSB_FX2 is not set
+# CONFIG_USB_HSIC_USB3503 is not set
+# CONFIG_USB_HSIC_USB4604 is not set
+# CONFIG_USB_LINK_LAYER_TEST is not set
+
+#
+# USB Physical Layer drivers
+#
+# CONFIG_USB_PHY is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_USB_ISP1301 is not set
+# CONFIG_USB_ULPI is not set
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2
+
+#
+# USB Peripheral Controller
+#
+# CONFIG_USB_FUSB300 is not set
+# CONFIG_USB_FOTG210_UDC is not set
+# CONFIG_USB_GR_UDC is not set
+# CONFIG_USB_R8A66597 is not set
+# CONFIG_USB_PXA27X is not set
+# CONFIG_USB_MV_UDC is not set
+# CONFIG_USB_MV_U3D is not set
+# CONFIG_USB_M66592 is not set
+# CONFIG_USB_BDC_UDC is not set
+# CONFIG_USB_NET2272 is not set
+# CONFIG_USB_GADGET_XILINX is not set
+# CONFIG_USB_DUMMY_HCD is not set
+CONFIG_USB_LIBCOMPOSITE=y
+CONFIG_USB_U_ETHER=y
+CONFIG_USB_F_ECM=y
+CONFIG_USB_F_RNDIS=y
+CONFIG_USB_CONFIGFS=y
+# CONFIG_USB_CONFIGFS_SERIAL is not set
+# CONFIG_USB_CONFIGFS_ACM is not set
+# CONFIG_USB_CONFIGFS_OBEX is not set
+# CONFIG_USB_CONFIGFS_NCM is not set
+CONFIG_USB_CONFIGFS_ECM=y
+# CONFIG_USB_CONFIGFS_ECM_SUBSET is not set
+CONFIG_USB_CONFIGFS_RNDIS=y
+# CONFIG_USB_CONFIGFS_EEM is not set
+# CONFIG_USB_CONFIGFS_MASS_STORAGE is not set
+# CONFIG_USB_CONFIGFS_F_LB_SS is not set
+# CONFIG_USB_CONFIGFS_F_FS is not set
+# CONFIG_USB_CONFIGFS_F_HID is not set
+# CONFIG_USB_CONFIGFS_F_UVC is not set
+# CONFIG_USB_CONFIGFS_F_PRINTER is not set
+# CONFIG_USB_ULPI_BUS is not set
+# CONFIG_UWB is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_PWRSEQ_EMMC=y
+CONFIG_PWRSEQ_SIMPLE=y
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_MINORS=8
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_ARMMMCI is not set
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+# CONFIG_MMC_SDHCI_OF_ARASAN is not set
+# CONFIG_MMC_SDHCI_OF_AT91 is not set
+CONFIG_MMC_SDHCI_GOKE=y
+# CONFIG_MMC_SDHCI_F_SDH30 is not set
+# CONFIG_MMC_SPI is not set
+# CONFIG_MMC_DW is not set
+# CONFIG_MMC_VUB300 is not set
+# CONFIG_MMC_USHC is not set
+# CONFIG_MMC_USDHI6ROL0 is not set
+# CONFIG_MMC_MTK is not set
+# CONFIG_MMC_CQ_HCI is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_EDAC_ATOMIC_SCRUB=y
+CONFIG_EDAC_SUPPORT=y
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+CONFIG_RTC_SYSTOHC=y
+CONFIG_RTC_SYSTOHC_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_ABB5ZES3 is not set
+# CONFIG_RTC_DRV_ABX80X is not set
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_HYM8563 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_ISL12022 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8523 is not set
+# CONFIG_RTC_DRV_PCF85063 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_BQ32K is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8010 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+# CONFIG_RTC_DRV_EM3027 is not set
+# CONFIG_RTC_DRV_RV8803 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T93 is not set
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1302 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1343 is not set
+# CONFIG_RTC_DRV_DS1347 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6916 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RX4581 is not set
+# CONFIG_RTC_DRV_RX6110 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
+# CONFIG_RTC_DRV_MCP795 is not set
+CONFIG_RTC_I2C_AND_SPI=y
+
+#
+# SPI and I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS3232 is not set
+# CONFIG_RTC_DRV_PCF2127 is not set
+# CONFIG_RTC_DRV_RV3029C2 is not set
+
+#
+# Platform RTC drivers
+#
+CONFIG_RTC_DRV_GOKE=y
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1685_FAMILY is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_DS2404 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+# CONFIG_RTC_DRV_ZYNQMP is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_PL030 is not set
+# CONFIG_RTC_DRV_PL031 is not set
+# CONFIG_RTC_DRV_SNVS is not set
+
+#
+# HID Sensor RTC drivers
+#
+# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set
+# CONFIG_DMADEVICES is not set
+
+#
+# DMABUF options
+#
+# CONFIG_SYNC_FILE is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+# CONFIG_VIRT_DRIVERS is not set
+
+#
+# Virtio drivers
+#
+# CONFIG_VIRTIO_MMIO is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_STAGING is not set
+# CONFIG_GOLDFISH is not set
+# CONFIG_CHROME_PLATFORMS is not set
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_COMMON_CLK=y
+
+#
+# Common Clock Framework
+#
+# CONFIG_COMMON_CLK_SI5351 is not set
+# CONFIG_COMMON_CLK_SI514 is not set
+# CONFIG_COMMON_CLK_SI570 is not set
+# CONFIG_COMMON_CLK_CDCE706 is not set
+# CONFIG_COMMON_CLK_CDCE925 is not set
+# CONFIG_COMMON_CLK_CS2000_CP is not set
+# CONFIG_CLK_QORIQ is not set
+# CONFIG_COMMON_CLK_NXP is not set
+# CONFIG_COMMON_CLK_PXA is not set
+# CONFIG_COMMON_CLK_PIC32 is not set
+CONFIG_COMMON_CLK_GK7202V300=y
+CONFIG_RESET_GOKE=y
+
+#
+# Hardware Spinlock drivers
+#
+
+#
+# Clock Source drivers
+#
+CONFIG_CLKSRC_OF=y
+CONFIG_CLKSRC_PROBE=y
+CONFIG_CLKSRC_MMIO=y
+CONFIG_ARM_ARCH_TIMER=y
+CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y
+# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS is not set
+CONFIG_ARM_TIMER_SP804=y
+# CONFIG_ATMEL_PIT is not set
+# CONFIG_SH_TIMER_CMT is not set
+# CONFIG_SH_TIMER_MTU2 is not set
+# CONFIG_SH_TIMER_TMU is not set
+# CONFIG_EM_TIMER_STI is not set
+# CONFIG_MAILBOX is not set
+# CONFIG_IOMMU_SUPPORT is not set
+
+#
+# Remoteproc drivers
+#
+# CONFIG_STE_MODEM_RPROC is not set
+
+#
+# Rpmsg drivers
+#
+
+#
+# SOC (System On Chip) specific Drivers
+#
+
+#
+# Broadcom SoC drivers
+#
+# CONFIG_SOC_BRCMSTB is not set
+# CONFIG_SUNXI_SRAM is not set
+# CONFIG_SOC_TI is not set
+# CONFIG_PM_DEVFREQ is not set
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
+# CONFIG_IIO is not set
+# CONFIG_PWM is not set
+CONFIG_IRQCHIP=y
+CONFIG_ARM_GIC=y
+CONFIG_ARM_GIC_MAX_NR=1
+# CONFIG_IPACK_BUS is not set
+CONFIG_RESET_CONTROLLER=y
+# CONFIG_RESET_ATH79 is not set
+# CONFIG_RESET_BERLIN is not set
+# CONFIG_RESET_LPC18XX is not set
+# CONFIG_RESET_MESON is not set
+# CONFIG_RESET_PISTACHIO is not set
+# CONFIG_RESET_SOCFPGA is not set
+# CONFIG_RESET_STM32 is not set
+# CONFIG_RESET_SUNXI is not set
+# CONFIG_TI_SYSCON_RESET is not set
+# CONFIG_RESET_ZYNQ is not set
+# CONFIG_FMC is not set
+
+#
+# PHY Subsystem
+#
+CONFIG_GENERIC_PHY=y
+# CONFIG_PHY_PXA_28NM_HSIC is not set
+# CONFIG_PHY_PXA_28NM_USB2 is not set
+# CONFIG_BCM_KONA_USB2_PHY is not set
+CONFIG_PHY_GOKE_USBP2=y
+# CONFIG_USB_MODE_OPTION is not set
+# CONFIG_POWERCAP is not set
+# CONFIG_MCB is not set
+
+#
+# Performance monitor support
+#
+# CONFIG_RAS is not set
+
+#
+# Android
+#
+# CONFIG_ANDROID is not set
+# CONFIG_NVMEM is not set
+# CONFIG_STM is not set
+# CONFIG_INTEL_TH is not set
+
+#
+# FPGA Configuration Support
+#
+# CONFIG_FPGA is not set
+
+#
+# goke driver support
+#
+
+#
+# Firmware Drivers
+#
+# CONFIG_FIRMWARE_MEMMAP is not set
+# CONFIG_FW_CFG_SYSFS is not set
+CONFIG_HAVE_ARM_SMCCC=y
+
+#
+# File systems
+#
+CONFIG_DCACHE_WORD_ACCESS=y
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_USE_FOR_EXT2=y
+# CONFIG_EXT4_FS_POSIX_ACL is not set
+# CONFIG_EXT4_FS_SECURITY is not set
+# CONFIG_EXT4_ENCRYPTION is not set
+# CONFIG_EXT4_DEBUG is not set
+CONFIG_JBD2=y
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+# CONFIG_F2FS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_EXPORTFS=y
+# CONFIG_EXPORTFS_BLOCK_OPS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_MANDATORY_FILE_LOCKING=y
+# CONFIG_FS_ENCRYPTION is not set
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_QUOTACTL is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+# CONFIG_OVERLAY_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_FAT_DEFAULT_UTF8 is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_PROC_CHILDREN is not set
+CONFIG_KERNFS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_TMPFS_XATTR=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=y
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ORANGEFS_FS is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_YAFFS_FS=y
+CONFIG_YAFFS_YAFFS1=y
+# CONFIG_YAFFS_9BYTE_TAGS is not set
+# CONFIG_YAFFS_DOES_ECC is not set
+CONFIG_YAFFS_YAFFS2=y
+CONFIG_YAFFS_AUTO_YAFFS2=y
+# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set
+# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
+# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set
+# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set
+# CONFIG_YAFFS_DISABLE_BACKGROUND is not set
+# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set
+CONFIG_YAFFS_XATTR=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+# CONFIG_JFFS2_LZMA is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_UBIFS_FS=y
+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_ATIME_SUPPORT is not set
+# CONFIG_LOGFS is not set
+CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX6FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_PSTORE is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V2=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+# CONFIG_NFS_SWAP is not set
+# CONFIG_NFS_V4_1 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFS_USE_LEGACY_DNS is not set
+CONFIG_NFS_USE_KERNEL_DNS=y
+# CONFIG_NFSD is not set
+CONFIG_GRACE_PERIOD=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_ACL_SUPPORT=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_DEBUG is not set
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=y
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+# CONFIG_NLS_MAC_ROMAN is not set
+# CONFIG_NLS_MAC_CELTIC is not set
+# CONFIG_NLS_MAC_CENTEURO is not set
+# CONFIG_NLS_MAC_CROATIAN is not set
+# CONFIG_NLS_MAC_CYRILLIC is not set
+# CONFIG_NLS_MAC_GAELIC is not set
+# CONFIG_NLS_MAC_GREEK is not set
+# CONFIG_NLS_MAC_ICELAND is not set
+# CONFIG_NLS_MAC_INUIT is not set
+# CONFIG_NLS_MAC_ROMANIAN is not set
+# CONFIG_NLS_MAC_TURKISH is not set
+CONFIG_NLS_UTF8=y
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+
+#
+# printk and dmesg options
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
+# CONFIG_BOOT_PRINTK_DELAY is not set
+
+#
+# Compile-time checks and compiler options
+#
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_READABLE_ASM is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_PAGE_OWNER is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_SECTION_MISMATCH_WARN_ONLY=y
+CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_DEBUG_KERNEL=y
+
+#
+# Memory Debugging
+#
+# CONFIG_PAGE_EXTENSION is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_PAGE_POISONING is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_SHIRQ is not set
+
+#
+# Debug Lockups and Hangs
+#
+# CONFIG_LOCKUP_DETECTOR is not set
+# CONFIG_DETECT_HUNG_TASK is not set
+# CONFIG_WQ_WATCHDOG is not set
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+CONFIG_PANIC_TIMEOUT=0
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHED_INFO is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_SCHED_STACK_END_CHECK is not set
+# CONFIG_DEBUG_TIMEKEEPING is not set
+# CONFIG_TIMER_STATS is not set
+
+#
+# Lock Debugging (spinlocks, mutexes, etc...)
+#
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_ATOMIC_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_LOCK_TORTURE_TEST is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_PI_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+
+#
+# RCU Debugging
+#
+# CONFIG_PROVE_RCU is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_TORTURE_TEST is not set
+# CONFIG_RCU_PERF_TEST is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_TRACE is not set
+# CONFIG_RCU_EQS_DEBUG is not set
+# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_NOTIFIER_ERROR_INJECTION is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+
+#
+# Runtime Testing
+#
+# CONFIG_TEST_LIST_SORT is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_RBTREE_TEST is not set
+# CONFIG_INTERVAL_TREE_TEST is not set
+# CONFIG_PERCPU_TEST is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_TEST_HEXDUMP is not set
+# CONFIG_TEST_STRING_HELPERS is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_TEST_PRINTF is not set
+# CONFIG_TEST_BITMAP is not set
+# CONFIG_TEST_UUID is not set
+# CONFIG_TEST_RHASHTABLE is not set
+# CONFIG_TEST_HASH is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_TEST_LKM is not set
+# CONFIG_TEST_USER_COPY is not set
+# CONFIG_TEST_BPF is not set
+# CONFIG_TEST_FIRMWARE is not set
+# CONFIG_TEST_UDELAY is not set
+# CONFIG_MEMTEST is not set
+# CONFIG_TEST_STATIC_KEYS is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set
+# CONFIG_UBSAN is not set
+CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
+CONFIG_STRICT_DEVMEM=y
+# CONFIG_IO_STRICT_DEVMEM is not set
+# CONFIG_ARM_PTDUMP is not set
+# CONFIG_ARM_UNWIND is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_LL is not set
+CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
+# CONFIG_DEBUG_UART_8250 is not set
+CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
+# CONFIG_PID_IN_CONTEXTIDR is not set
+# CONFIG_DEBUG_SET_MODULE_RONX is not set
+# CONFIG_CORESIGHT is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_PERSISTENT_KEYRINGS is not set
+# CONFIG_ENCRYPTED_KEYS is not set
+# CONFIG_KEY_DH_OPERATIONS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y
+CONFIG_HAVE_ARCH_HARDENED_USERCOPY=y
+# CONFIG_HARDENED_USERCOPY is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_RNG_DEFAULT=m
+CONFIG_CRYPTO_AKCIPHER2=y
+CONFIG_CRYPTO_KPP2=y
+# CONFIG_CRYPTO_RSA is not set
+# CONFIG_CRYPTO_DH is not set
+# CONFIG_CRYPTO_ECDH is not set
+CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_USER is not set
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_NULL2=y
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_MCRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+# CONFIG_CRYPTO_CHACHA20POLY1305 is not set
+CONFIG_CRYPTO_SEQIV=m
+CONFIG_CRYPTO_ECHAINIV=m
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+CONFIG_CRYPTO_CTR=m
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+# CONFIG_CRYPTO_KEYWRAP is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_CMAC is not set
+CONFIG_CRYPTO_HMAC=m
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_CRC32 is not set
+CONFIG_CRYPTO_CRCT10DIF=y
+CONFIG_CRYPTO_GHASH=m
+# CONFIG_CRYPTO_POLY1305 is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=y
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_SHA3 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_CHACHA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_LZO=y
+# CONFIG_CRYPTO_842 is not set
+# CONFIG_CRYPTO_LZ4 is not set
+# CONFIG_CRYPTO_LZ4HC is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_DRBG_MENU=m
+CONFIG_CRYPTO_DRBG_HMAC=y
+# CONFIG_CRYPTO_DRBG_HASH is not set
+# CONFIG_CRYPTO_DRBG_CTR is not set
+CONFIG_CRYPTO_DRBG=m
+CONFIG_CRYPTO_JITTERENTROPY=m
+# CONFIG_CRYPTO_USER_API_HASH is not set
+# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
+# CONFIG_CRYPTO_USER_API_RNG is not set
+# CONFIG_CRYPTO_USER_API_AEAD is not set
+# CONFIG_CRYPTO_HW is not set
+# CONFIG_ASYMMETRIC_KEY_TYPE is not set
+
+#
+# Certificates for signature checking
+#
+# CONFIG_ARM_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_HAVE_ARCH_BITREVERSE=y
+CONFIG_RATIONAL=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_NET_UTILS=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IO=y
+CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=y
+# CONFIG_CRC8 is not set
+# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set
+# CONFIG_RANDOM32_SELFTEST is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_LZ4_DECOMPRESS=y
+CONFIG_XZ_DEC=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_BCJ=y
+# CONFIG_XZ_DEC_TEST is not set
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_LZ4=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_ASSOCIATIVE_ARRAY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_HAS_DMA=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
+# CONFIG_IRQ_POLL is not set
+CONFIG_LIBFDT=y
+CONFIG_OID_REGISTRY=y
+# CONFIG_SG_SPLIT is not set
+CONFIG_SG_POOL=y
+CONFIG_ARCH_HAS_SG_CHAIN=y
+CONFIG_SBITMAP=y
+# CONFIG_VIRTUALIZATION is not set
diff -urN linux-4.9.37/arch/arm/configs/gk7202v300_full_defconfig linux-4.9.y/arch/arm/configs/gk7202v300_full_defconfig
--- linux-4.9.37/arch/arm/configs/gk7202v300_full_defconfig 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/arch/arm/configs/gk7202v300_full_defconfig 2021-06-07 13:01:32.000000000 +0300
@@ -0,0 +1,2858 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/arm 4.9.37 Kernel Configuration
+#
+CONFIG_ARM=y
+CONFIG_ARM_HAS_SG_CHAIN=y
+CONFIG_MIGHT_HAVE_PCI=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_ARM_PATCH_PHYS_VIRT=y
+CONFIG_GENERIC_BUG=y
+CONFIG_PGTABLE_LEVELS=2
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_IRQ_WORK=y
+CONFIG_BUILDTIME_EXTABLE_SORT=y
+
+#
+# General setup
+#
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+# CONFIG_COMPILE_TEST is not set
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_HAVE_KERNEL_LZ4=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_XZ is not set
+# CONFIG_KERNEL_LZO is not set
+# CONFIG_KERNEL_LZ4 is not set
+CONFIG_DEFAULT_HOSTNAME="(none)"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_CROSS_MEMORY_ATTACH=y
+CONFIG_FHANDLE=y
+CONFIG_USELIB=y
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_ARCH_AUDITSYSCALL=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_IRQ_DOMAIN_HIERARCHY=y
+CONFIG_HANDLE_DOMAIN_IRQ=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_ARCH_CLOCKSOURCE_DATA=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+
+#
+# Timers subsystem
+#
+CONFIG_HZ_PERIODIC=y
+# CONFIG_NO_HZ_IDLE is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set
+# CONFIG_IRQ_TIME_ACCOUNTING is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TINY_RCU=y
+# CONFIG_RCU_EXPERT is not set
+CONFIG_SRCU=y
+# CONFIG_TASKS_RCU is not set
+# CONFIG_RCU_STALL_COMMON is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_RCU_EXPEDITE_BOOT is not set
+# CONFIG_BUILD_BIN2C is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_NMI_LOG_BUF_SHIFT=13
+CONFIG_GENERIC_SCHED_CLOCK=y
+CONFIG_CGROUPS=y
+# CONFIG_MEMCG is not set
+# CONFIG_BLK_CGROUP is not set
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUP_PIDS is not set
+CONFIG_CGROUP_FREEZER=y
+# CONFIG_CPUSETS is not set
+# CONFIG_CGROUP_DEVICE is not set
+# CONFIG_CGROUP_CPUACCT is not set
+# CONFIG_CGROUP_DEBUG is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+CONFIG_NAMESPACES=y
+CONFIG_UTS_NS=y
+CONFIG_IPC_NS=y
+# CONFIG_USER_NS is not set
+CONFIG_PID_NS=y
+CONFIG_NET_NS=y
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_RD_XZ is not set
+# CONFIG_RD_LZO is not set
+CONFIG_RD_LZ4=y
+CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_HAVE_UID16=y
+CONFIG_BPF=y
+# CONFIG_EXPERT is not set
+CONFIG_UID16=y
+CONFIG_MULTIUSER=y
+# CONFIG_SGETMASK_SYSCALL is not set
+CONFIG_SYSFS_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set
+CONFIG_KALLSYMS_BASE_RELATIVE=y
+CONFIG_PRINTK=y
+CONFIG_PRINTK_NMI=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+# CONFIG_BPF_SYSCALL is not set
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_ADVISE_SYSCALLS=y
+# CONFIG_USERFAULTFD is not set
+CONFIG_MEMBARRIER=y
+# CONFIG_EMBEDDED is not set
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLAB_FREELIST_RANDOM is not set
+# CONFIG_SYSTEM_DATA_VERIFICATION is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+# CONFIG_JUMP_LABEL is not set
+# CONFIG_UPROBES is not set
+# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_ARCH_USE_BUILTIN_BSWAP=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_NMI=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_IDLE_POLL_SETUP=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_HAVE_GCC_PLUGINS=y
+# CONFIG_GCC_PLUGINS is not set
+CONFIG_HAVE_CC_STACKPROTECTOR=y
+CONFIG_CC_STACKPROTECTOR=y
+# CONFIG_CC_STACKPROTECTOR_NONE is not set
+# CONFIG_CC_STACKPROTECTOR_REGULAR is not set
+CONFIG_CC_STACKPROTECTOR_STRONG=y
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_MODULES_USE_ELF_REL=y
+CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_HAVE_ARCH_MMAP_RND_BITS=y
+CONFIG_HAVE_EXIT_THREAD=y
+CONFIG_ARCH_MMAP_RND_BITS_MIN=8
+CONFIG_ARCH_MMAP_RND_BITS_MAX=16
+CONFIG_ARCH_MMAP_RND_BITS=8
+# CONFIG_HAVE_ARCH_HASH is not set
+# CONFIG_ISA_BUS_API is not set
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_OLD_SIGACTION=y
+# CONFIG_CPU_NO_EFFICIENT_FFS is not set
+# CONFIG_HAVE_ARCH_VMAP_STACK is not set
+
+#
+# GCOV-based kernel profiling
+#
+CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_MODULE_SIG is not set
+# CONFIG_MODULE_COMPRESS is not set
+# CONFIG_TRIM_UNUSED_KSYMS is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+CONFIG_BLK_DEV_BSG=y
+# CONFIG_BLK_DEV_BSGLIB is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+CONFIG_BLK_CMDLINE_PARSER=y
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_AIX_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_CMDLINE_PARTITION=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+CONFIG_INLINE_READ_UNLOCK=y
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+CONFIG_INLINE_WRITE_UNLOCK=y
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+CONFIG_MMU=y
+CONFIG_ARCH_MULTIPLATFORM=y
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_LPC32XX is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C24XX is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP1 is not set
+
+#
+# Multiple platform selection
+#
+
+#
+# CPU Core family selection
+#
+# CONFIG_ARCH_MULTI_V6 is not set
+CONFIG_ARCH_MULTI_V7=y
+CONFIG_ARCH_MULTI_V6_V7=y
+# CONFIG_ARCH_MULTI_CPU_AUTO is not set
+# CONFIG_ARCH_VIRT is not set
+# CONFIG_ARCH_MVEBU is not set
+# CONFIG_ARCH_ALPINE is not set
+# CONFIG_ARCH_ARTPEC is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_BCM is not set
+# CONFIG_ARCH_BERLIN is not set
+# CONFIG_ARCH_DIGICOLOR is not set
+# CONFIG_ARCH_HIGHBANK is not set
+# CONFIG_ARCH_HISI is not set
+CONFIG_ARCH_GOKE=y
+
+#
+# Goke platform type
+#
+# CONFIG_ARCH_GK7205V200 is not set
+# CONFIG_ARCH_GK7205V300 is not set
+CONFIG_ARCH_GK7202V300=y
+# CONFIG_ARCH_GK7605V100 is not set
+# CONFIG_GOKE_MC is not set
+CONFIG_BSP_ZRELADDR=0x40008000
+CONFIG_BSP_PARAMS_PHYS=0x00000100
+CONFIG_BSP_INITRD_PHYS=0x00800000
+# CONFIG_ARCH_KEYSTONE is not set
+# CONFIG_ARCH_MESON is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_MEDIATEK is not set
+
+#
+# TI OMAP/AM/DM/DRA Family
+#
+# CONFIG_ARCH_OMAP3 is not set
+# CONFIG_ARCH_OMAP4 is not set
+# CONFIG_SOC_OMAP5 is not set
+# CONFIG_SOC_AM33XX is not set
+# CONFIG_SOC_AM43XX is not set
+# CONFIG_SOC_DRA7XX is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_QCOM is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_ROCKCHIP is not set
+# CONFIG_ARCH_SOCFPGA is not set
+# CONFIG_PLAT_SPEAR is not set
+# CONFIG_ARCH_STI is not set
+# CONFIG_ARCH_S5PV210 is not set
+# CONFIG_ARCH_EXYNOS is not set
+# CONFIG_ARCH_RENESAS is not set
+# CONFIG_ARCH_SUNXI is not set
+# CONFIG_ARCH_SIRF is not set
+# CONFIG_ARCH_TANGO is not set
+# CONFIG_ARCH_TEGRA is not set
+# CONFIG_ARCH_UNIPHIER is not set
+# CONFIG_ARCH_U8500 is not set
+# CONFIG_ARCH_VEXPRESS is not set
+# CONFIG_ARCH_WM8850 is not set
+# CONFIG_ARCH_ZX is not set
+# CONFIG_ARCH_ZYNQ is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_V7=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_LPAE is not set
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+CONFIG_ARM_THUMB=y
+# CONFIG_ARM_THUMBEE is not set
+CONFIG_ARM_VIRT_EXT=y
+# CONFIG_SWP_EMULATE is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_KUSER_HELPERS=y
+CONFIG_VDSO=y
+CONFIG_MIGHT_HAVE_CACHE_L2X0=y
+# CONFIG_CACHE_L2X0 is not set
+CONFIG_ARM_L1_CACHE_SHIFT_6=y
+CONFIG_ARM_L1_CACHE_SHIFT=6
+CONFIG_ARM_DMA_MEM_BUFFERABLE=y
+# CONFIG_DEBUG_RODATA is not set
+CONFIG_MULTI_IRQ_HANDLER=y
+# CONFIG_ARM_ERRATA_430973 is not set
+# CONFIG_ARM_ERRATA_720789 is not set
+# CONFIG_ARM_ERRATA_754322 is not set
+# CONFIG_ARM_ERRATA_775420 is not set
+# CONFIG_ARM_ERRATA_773022 is not set
+# CONFIG_ARM_ERRATA_818325_852422 is not set
+# CONFIG_ARM_ERRATA_821420 is not set
+# CONFIG_ARM_ERRATA_825619 is not set
+# CONFIG_ARM_ERRATA_852421 is not set
+# CONFIG_ARM_ERRATA_852423 is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS_GENERIC is not set
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_HAVE_SMP=y
+# CONFIG_SMP is not set
+CONFIG_HAVE_ARM_ARCH_TIMER=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_3G_OPT is not set
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_ARM_PSCI is not set
+CONFIG_ARCH_NR_GPIO=0
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ_FIXED=0
+CONFIG_HZ_100=y
+# CONFIG_HZ_200 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_500 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
+# CONFIG_SCHED_HRTICK is not set
+# CONFIG_THUMB2_KERNEL is not set
+CONFIG_ARM_PATCH_IDIV=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_HAVE_ARCH_PFN_VALID=y
+# CONFIG_HIGHMEM is not set
+# CONFIG_CPU_SW_DOMAIN_PAN is not set
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+# CONFIG_ARM_MODULE_PLTS is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_NO_BOOTMEM=y
+# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_COMPACTION=y
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NEED_PER_CPU_KM=y
+# CONFIG_CLEANCACHE is not set
+# CONFIG_CMA is not set
+# CONFIG_ZPOOL is not set
+# CONFIG_ZBUD is not set
+# CONFIG_ZSMALLOC is not set
+CONFIG_GENERIC_EARLY_IOREMAP=y
+# CONFIG_IDLE_PAGE_TRACKING is not set
+CONFIG_FRAME_VECTOR=y
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+# CONFIG_SECCOMP is not set
+CONFIG_SWIOTLB=y
+CONFIG_IOMMU_HELPER=y
+# CONFIG_PARAVIRT is not set
+# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set
+# CONFIG_XEN is not set
+
+#
+# Boot options
+#
+CONFIG_USE_OF=y
+CONFIG_ATAGS=y
+# CONFIG_DEPRECATED_PARAM_STRUCT is not set
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER=y
+# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set
+CONFIG_CMDLINE=""
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_AUTO_ZRELADDR=y
+# CONFIG_EFI is not set
+
+#
+# CPU Power Management
+#
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# CPU Idle
+#
+# CONFIG_CPU_IDLE is not set
+# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+# CONFIG_KERNEL_MODE_NEON is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_ELFCORE=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
+CONFIG_BINFMT_SCRIPT=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_COREDUMP=y
+
+#
+# Power management options
+#
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_PM_SLEEP=y
+# CONFIG_PM_AUTOSLEEP is not set
+# CONFIG_PM_WAKELOCKS is not set
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_APM_EMULATION is not set
+CONFIG_PM_CLK=y
+# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_CPU_PM=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARM_CPU_SUSPEND=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_DIAG is not set
+CONFIG_UNIX=y
+# CONFIG_UNIX_DIAG is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_ALGO=y
+CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+# CONFIG_IP_FIB_TRIE_STATS is not set
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
+# CONFIG_NET_IP_TUNNEL is not set
+CONFIG_IP_MROUTE=y
+# CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_NET_UDP_TUNNEL is not set
+# CONFIG_NET_FOU is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_INET_UDP_DIAG is not set
+# CONFIG_INET_DIAG_DESTROY is not set
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BIC=m
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+# CONFIG_TCP_CONG_HSTCP is not set
+# CONFIG_TCP_CONG_HYBLA is not set
+# CONFIG_TCP_CONG_VEGAS is not set
+# CONFIG_TCP_CONG_NV is not set
+# CONFIG_TCP_CONG_SCALABLE is not set
+# CONFIG_TCP_CONG_LP is not set
+# CONFIG_TCP_CONG_VENO is not set
+# CONFIG_TCP_CONG_YEAH is not set
+# CONFIG_TCP_CONG_ILLINOIS is not set
+# CONFIG_TCP_CONG_DCTCP is not set
+# CONFIG_TCP_CONG_CDG is not set
+# CONFIG_TCP_CONG_BBR is not set
+CONFIG_DEFAULT_CUBIC=y
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NET_PTP_CLASSIFY is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+CONFIG_DNS_RESOLVER=y
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+# CONFIG_VSOCKETS is not set
+# CONFIG_NETLINK_DIAG is not set
+# CONFIG_MPLS is not set
+# CONFIG_HSR is not set
+# CONFIG_NET_SWITCHDEV is not set
+# CONFIG_NET_L3_MASTER_DEV is not set
+# CONFIG_NET_NCSI is not set
+# CONFIG_SOCK_CGROUP_DATA is not set
+# CONFIG_CGROUP_NET_PRIO is not set
+# CONFIG_CGROUP_NET_CLASSID is not set
+CONFIG_NET_RX_BUSY_POLL=y
+CONFIG_BQL=y
+# CONFIG_BPF_JIT is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_AF_KCM is not set
+# CONFIG_STREAM_PARSER is not set
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_CFG80211=m
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+CONFIG_CFG80211_DEFAULT_PS=y
+# CONFIG_CFG80211_INTERNAL_REGDB is not set
+CONFIG_CFG80211_CRDA_SUPPORT=y
+CONFIG_CFG80211_WEXT=y
+# CONFIG_LIB80211 is not set
+CONFIG_MAC80211=m
+CONFIG_MAC80211_HAS_RC=y
+CONFIG_MAC80211_RC_MINSTREL=y
+CONFIG_MAC80211_RC_MINSTREL_HT=y
+# CONFIG_MAC80211_RC_MINSTREL_VHT is not set
+CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y
+CONFIG_MAC80211_RC_DEFAULT="minstrel_ht"
+CONFIG_MAC80211_MESH=y
+# CONFIG_MAC80211_MESSAGE_TRACING is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+CONFIG_MAC80211_STA_HASH_MAX_SIZE=0
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+# CONFIG_LWTUNNEL is not set
+# CONFIG_DST_CACHE is not set
+# CONFIG_NET_DEVLINK is not set
+CONFIG_MAY_USE_DEVLINK=y
+CONFIG_HAVE_CBPF_JIT=y
+
+#
+# Device Drivers
+#
+CONFIG_ARM_AMBA=y
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set
+CONFIG_ALLOW_DEV_COREDUMP=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+CONFIG_REGMAP=y
+CONFIG_REGMAP_I2C=y
+CONFIG_REGMAP_SPI=y
+CONFIG_REGMAP_MMIO=y
+CONFIG_DMA_SHARED_BUFFER=y
+# CONFIG_FENCE_TRACE is not set
+
+#
+# Bus devices
+#
+# CONFIG_BRCMSTB_GISB_ARB is not set
+# CONFIG_VEXPRESS_CONFIG is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+CONFIG_MTD_OF_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
+# CONFIG_MTD_OOPS is not set
+# CONFIG_MTD_PARTITIONED_MASTER is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SST25L is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOCG3 is not set
+CONFIG_MTD_NAND_ECC=y
+# CONFIG_MTD_NAND_ECC_SMC is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_ECC_BCH is not set
+# CONFIG_MTD_SM_COMMON is not set
+# CONFIG_MTD_NAND_DENALI_DT is not set
+# CONFIG_MTD_NAND_GPIO is not set
+# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_DOCG4 is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_BRCMNAND is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_NAND_HISI504 is not set
+# CONFIG_MTD_NAND_MTK is not set
+CONFIG_MTD_SPI_NAND_GOKE=y
+# CONFIG_GOKE_NAND_ECC_STATUS_REPORT is not set
+# CONFIG_GOKE_NAND_FS_MAY_NO_YAFFS2 is not set
+CONFIG_MTD_SPI_NAND_FMC100=y
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR & LPDDR2 PCM memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_LPDDR2_NVM is not set
+CONFIG_MTD_SPI_NOR=y
+# CONFIG_MTD_MT81xx_NOR is not set
+# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
+# CONFIG_SPI_CADENCE_QUADSPI is not set
+CONFIG_SPI_GOKE_SFC=y
+# CONFIG_CLOSE_SPI_8PIN_4IO is not set
+CONFIG_GOKE_SPI_BLOCK_PROTECT=y
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_LIMIT=20
+# CONFIG_MTD_UBI_FASTMAP is not set
+# CONFIG_MTD_UBI_GLUEBI is not set
+# CONFIG_MTD_UBI_BLOCK is not set
+CONFIG_DTC=y
+CONFIG_OF=y
+# CONFIG_OF_UNITTEST is not set
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_RESERVED_MEM=y
+# CONFIG_OF_OVERLAY is not set
+CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_NULL_BLK is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_DRBD is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=65536
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MG_DISK is not set
+# CONFIG_BLK_DEV_RBD is not set
+# CONFIG_NVME_TARGET is not set
+
+#
+# Misc devices
+#
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_DUMMY_IRQ is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_APDS9802ALS is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_ISL29020 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_BH1770 is not set
+# CONFIG_SENSORS_APDS990X is not set
+# CONFIG_HMC6352 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_TI_DAC7512 is not set
+# CONFIG_USB_SWITCH_FSA9480 is not set
+# CONFIG_LATTICE_ECP3_CONFIG is not set
+# CONFIG_SRAM is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_EEPROM_93XX46 is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+# CONFIG_SENSORS_LIS3_SPI is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
+
+#
+# Altera FPGA firmware download module
+#
+# CONFIG_ALTERA_STAPL is not set
+
+#
+# Intel MIC Bus Driver
+#
+
+#
+# SCIF Bus Driver
+#
+
+#
+# VOP Bus Driver
+#
+
+#
+# Intel MIC Host Driver
+#
+
+#
+# Intel MIC Card Driver
+#
+
+#
+# SCIF Driver
+#
+
+#
+# Intel MIC Coprocessor State Management (COSM) Drivers
+#
+
+#
+# VOP Driver
+#
+# CONFIG_ECHO is not set
+# CONFIG_CXL_BASE is not set
+# CONFIG_CXL_AFU_DRIVER_OPS is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+CONFIG_SCSI_NETLINK=y
+# CONFIG_SCSI_MQ_DEFAULT is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+CONFIG_SCSI_FC_ATTRS=y
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_ISCSI_BOOT_SYSFS is not set
+# CONFIG_SCSI_UFSHCD is not set
+# CONFIG_LIBFC is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_TARGET_CORE is not set
+# CONFIG_NETDEVICES is not set
+# CONFIG_NVM is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+# CONFIG_INPUT_MATRIXKMAP is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ADP5588 is not set
+# CONFIG_KEYBOARD_ADP5589 is not set
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_QT1070 is not set
+# CONFIG_KEYBOARD_QT2160 is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_KEYBOARD_GPIO_POLLED is not set
+# CONFIG_KEYBOARD_TCA6416 is not set
+# CONFIG_KEYBOARD_TCA8418 is not set
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_LM8333 is not set
+# CONFIG_KEYBOARD_MAX7359 is not set
+# CONFIG_KEYBOARD_MCS is not set
+# CONFIG_KEYBOARD_MPR121 is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_SAMSUNG is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_OMAP4 is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_CAP11XX is not set
+# CONFIG_KEYBOARD_BCM is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_BYD=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_CYPRESS=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_SENTELIC is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+CONFIG_MOUSE_PS2_FOCALTECH=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_CYAPA is not set
+# CONFIG_MOUSE_ELAN_I2C is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+# CONFIG_MOUSE_SYNAPTICS_I2C is not set
+# CONFIG_MOUSE_SYNAPTICS_USB is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_AD714X is not set
+# CONFIG_INPUT_ATMEL_CAPTOUCH is not set
+# CONFIG_INPUT_BMA150 is not set
+# CONFIG_INPUT_E3X0_BUTTON is not set
+# CONFIG_INPUT_MMA8450 is not set
+# CONFIG_INPUT_MPU3050 is not set
+# CONFIG_INPUT_GP2A is not set
+# CONFIG_INPUT_GPIO_BEEPER is not set
+# CONFIG_INPUT_GPIO_TILT_POLLED is not set
+# CONFIG_INPUT_GPIO_DECODER is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_KXTJ9 is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
+CONFIG_INPUT_UINPUT=y
+# CONFIG_INPUT_PCF8574 is not set
+# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
+# CONFIG_INPUT_ADXL34X is not set
+# CONFIG_INPUT_CMA3000 is not set
+# CONFIG_INPUT_DRV260X_HAPTICS is not set
+# CONFIG_INPUT_DRV2665_HAPTICS is not set
+# CONFIG_INPUT_DRV2667_HAPTICS is not set
+# CONFIG_RMI4_CORE is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_AMBAKMI is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_ALTERA_PS2 is not set
+# CONFIG_SERIO_PS2MULT is not set
+# CONFIG_SERIO_ARC_PS2 is not set
+# CONFIG_SERIO_APBPS2 is not set
+# CONFIG_USERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_TTY=y
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_VT_CONSOLE_SLEEP=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVMEM=y
+# CONFIG_DEVKMEM is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_EARLYCON=y
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_AMBA_PL010 is not set
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set
+# CONFIG_SERIAL_MAX3100 is not set
+# CONFIG_SERIAL_MAX310X is not set
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_SCCNXP is not set
+# CONFIG_SERIAL_SC16IS7XX is not set
+# CONFIG_SERIAL_BCM63XX is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_IFX6X60 is not set
+# CONFIG_SERIAL_XILINX_PS_UART is not set
+# CONFIG_SERIAL_ARC is not set
+# CONFIG_SERIAL_FSL_LPUART is not set
+# CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set
+# CONFIG_SERIAL_ST_ASC is not set
+# CONFIG_SERIAL_STM32 is not set
+# CONFIG_HVC_DCC is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_XILLYBUS is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MUX=y
+
+#
+# Multiplexer I2C Chip support
+#
+# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set
+# CONFIG_I2C_MUX_GPIO is not set
+# CONFIG_I2C_MUX_PCA9541 is not set
+# CONFIG_I2C_MUX_PCA954x is not set
+# CONFIG_I2C_MUX_PINCTRL is not set
+# CONFIG_I2C_MUX_REG is not set
+# CONFIG_I2C_DEMUX_PINCTRL is not set
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_CBUS_GPIO is not set
+# CONFIG_I2C_DESIGNWARE_PLATFORM is not set
+# CONFIG_I2C_EMEV2 is not set
+# CONFIG_I2C_GPIO is not set
+CONFIG_I2C_GOKE=y
+# CONFIG_I2C_NOMADIK is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_PXA_PCI is not set
+# CONFIG_I2C_RK3X is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_DIOLAN_U2C is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_ROBOTFUZZ_OSIF is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+CONFIG_DMA_MSG_MIN_LEN=5
+CONFIG_DMA_MSG_MAX_LEN=4090
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_SLAVE is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_ALTERA is not set
+# CONFIG_SPI_AXI_SPI_ENGINE is not set
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_CADENCE is not set
+# CONFIG_SPI_DESIGNWARE is not set
+# CONFIG_SPI_GPIO is not set
+# CONFIG_SPI_FSL_SPI is not set
+# CONFIG_SPI_OC_TINY is not set
+CONFIG_SPI_PL022=y
+# CONFIG_SPI_PXA2XX_PCI is not set
+# CONFIG_SPI_ROCKCHIP is not set
+# CONFIG_SPI_SC18IS602 is not set
+# CONFIG_SPI_XCOMM is not set
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_ZYNQMP_GQSPI is not set
+
+#
+# SPI Protocol Masters
+#
+CONFIG_SPI_SPIDEV=y
+# CONFIG_SPI_LOOPBACK_TEST is not set
+# CONFIG_SPI_TLE62X0 is not set
+# CONFIG_SPMI is not set
+# CONFIG_HSI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+# CONFIG_PTP_1588_CLOCK is not set
+
+#
+# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
+#
+CONFIG_PINCTRL=y
+
+#
+# Pin controllers
+#
+CONFIG_PINMUX=y
+CONFIG_PINCONF=y
+CONFIG_GENERIC_PINCONF=y
+# CONFIG_DEBUG_PINCTRL is not set
+# CONFIG_PINCTRL_AMD is not set
+CONFIG_PINCTRL_SINGLE=y
+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
+CONFIG_GPIOLIB=y
+CONFIG_OF_GPIO=y
+CONFIG_GPIOLIB_IRQCHIP=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO drivers
+#
+# CONFIG_GPIO_74XX_MMIO is not set
+# CONFIG_GPIO_ALTERA is not set
+# CONFIG_GPIO_DWAPB is not set
+# CONFIG_GPIO_EM is not set
+# CONFIG_GPIO_GENERIC_PLATFORM is not set
+# CONFIG_GPIO_GRGPIO is not set
+# CONFIG_GPIO_MOCKUP is not set
+# CONFIG_GPIO_MPC8XXX is not set
+CONFIG_GPIO_PL061=y
+# CONFIG_GPIO_SYSCON is not set
+# CONFIG_GPIO_XILINX is not set
+# CONFIG_GPIO_ZEVIO is not set
+# CONFIG_GPIO_ZX is not set
+
+#
+# I2C GPIO expanders
+#
+# CONFIG_GPIO_ADP5588 is not set
+# CONFIG_GPIO_ADNP is not set
+# CONFIG_GPIO_MAX7300 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_SX150X is not set
+# CONFIG_GPIO_TPIC2810 is not set
+# CONFIG_GPIO_TS4900 is not set
+
+#
+# MFD GPIO expanders
+#
+# CONFIG_HTC_EGPIO is not set
+
+#
+# SPI GPIO expanders
+#
+# CONFIG_GPIO_74X164 is not set
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MC33880 is not set
+# CONFIG_GPIO_PISOSR is not set
+
+#
+# SPI or I2C GPIO expanders
+#
+# CONFIG_GPIO_MCP23S08 is not set
+
+#
+# USB GPIO expanders
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_AVS is not set
+CONFIG_POWER_RESET=y
+# CONFIG_POWER_RESET_BRCMKONA is not set
+# CONFIG_POWER_RESET_BRCMSTB is not set
+CONFIG_POWER_RESET_GOKE=y
+# CONFIG_POWER_RESET_GPIO is not set
+# CONFIG_POWER_RESET_GPIO_RESTART is not set
+# CONFIG_POWER_RESET_LTC2952 is not set
+# CONFIG_POWER_RESET_RESTART is not set
+# CONFIG_POWER_RESET_VERSATILE is not set
+# CONFIG_POWER_RESET_SYSCON is not set
+# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set
+# CONFIG_SYSCON_REBOOT_MODE is not set
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_TEST_POWER is not set
+# CONFIG_BATTERY_DS2780 is not set
+# CONFIG_BATTERY_DS2781 is not set
+# CONFIG_BATTERY_DS2782 is not set
+# CONFIG_BATTERY_SBS is not set
+# CONFIG_BATTERY_BQ27XXX is not set
+# CONFIG_BATTERY_MAX17040 is not set
+# CONFIG_BATTERY_MAX17042 is not set
+# CONFIG_CHARGER_MAX8903 is not set
+# CONFIG_CHARGER_LP8727 is not set
+# CONFIG_CHARGER_GPIO is not set
+# CONFIG_CHARGER_BQ2415X is not set
+# CONFIG_CHARGER_BQ24190 is not set
+# CONFIG_CHARGER_BQ24257 is not set
+# CONFIG_CHARGER_BQ24735 is not set
+# CONFIG_CHARGER_BQ25890 is not set
+# CONFIG_CHARGER_SMB347 is not set
+# CONFIG_BATTERY_GAUGE_LTC2941 is not set
+# CONFIG_CHARGER_RT9455 is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+CONFIG_MFD_CORE=y
+# CONFIG_MFD_ACT8945A is not set
+# CONFIG_MFD_AS3711 is not set
+# CONFIG_MFD_AS3722 is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_AAT2870_CORE is not set
+# CONFIG_MFD_ATMEL_FLEXCOM is not set
+# CONFIG_MFD_ATMEL_HLCDC is not set
+# CONFIG_MFD_BCM590XX is not set
+# CONFIG_MFD_AXP20X_I2C is not set
+# CONFIG_MFD_CROS_EC is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_DA9052_SPI is not set
+# CONFIG_MFD_DA9052_I2C is not set
+# CONFIG_MFD_DA9055 is not set
+# CONFIG_MFD_DA9062 is not set
+# CONFIG_MFD_DA9063 is not set
+# CONFIG_MFD_DA9150 is not set
+# CONFIG_MFD_DLN2 is not set
+# CONFIG_MFD_EXYNOS_LPASS is not set
+# CONFIG_MFD_MC13XXX_SPI is not set
+# CONFIG_MFD_MC13XXX_I2C is not set
+# CONFIG_MFD_HI6421_PMIC is not set
+CONFIG_MFD_GOKE_FMC=y
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_HTC_I2CPLD is not set
+# CONFIG_INTEL_SOC_PMIC is not set
+# CONFIG_MFD_KEMPLD is not set
+# CONFIG_MFD_88PM800 is not set
+# CONFIG_MFD_88PM805 is not set
+# CONFIG_MFD_88PM860X is not set
+# CONFIG_MFD_MAX14577 is not set
+# CONFIG_MFD_MAX77620 is not set
+# CONFIG_MFD_MAX77686 is not set
+# CONFIG_MFD_MAX77693 is not set
+# CONFIG_MFD_MAX77843 is not set
+# CONFIG_MFD_MAX8907 is not set
+# CONFIG_MFD_MAX8925 is not set
+# CONFIG_MFD_MAX8997 is not set
+# CONFIG_MFD_MAX8998 is not set
+# CONFIG_MFD_MT6397 is not set
+# CONFIG_MFD_MENF21BMC is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_MFD_VIPERBOARD is not set
+# CONFIG_MFD_RETU is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_PM8921_CORE is not set
+# CONFIG_MFD_RT5033 is not set
+# CONFIG_MFD_RTSX_USB is not set
+# CONFIG_MFD_RC5T583 is not set
+# CONFIG_MFD_RK808 is not set
+# CONFIG_MFD_RN5T618 is not set
+# CONFIG_MFD_SEC_CORE is not set
+# CONFIG_MFD_SI476X_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_SKY81452 is not set
+# CONFIG_MFD_SMSC is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_MFD_STMPE is not set
+CONFIG_MFD_SYSCON=y
+# CONFIG_MFD_TI_AM335X_TSCADC is not set
+# CONFIG_MFD_LP3943 is not set
+# CONFIG_MFD_LP8788 is not set
+# CONFIG_MFD_PALMAS is not set
+# CONFIG_TPS6105X is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TPS6507X is not set
+# CONFIG_MFD_TPS65086 is not set
+# CONFIG_MFD_TPS65090 is not set
+# CONFIG_MFD_TPS65217 is not set
+# CONFIG_MFD_TI_LP873X is not set
+# CONFIG_MFD_TPS65218 is not set
+# CONFIG_MFD_TPS6586X is not set
+# CONFIG_MFD_TPS65910 is not set
+# CONFIG_MFD_TPS65912_I2C is not set
+# CONFIG_MFD_TPS65912_SPI is not set
+# CONFIG_MFD_TPS80031 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_TWL6040_CORE is not set
+# CONFIG_MFD_WL1273_CORE is not set
+# CONFIG_MFD_LM3533 is not set
+# CONFIG_MFD_TC3589X is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_MFD_ARIZONA_I2C is not set
+# CONFIG_MFD_ARIZONA_SPI is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X_I2C is not set
+# CONFIG_MFD_WM831X_SPI is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8994 is not set
+# CONFIG_REGULATOR is not set
+CONFIG_MEDIA_SUPPORT=y
+
+#
+# Multimedia core support
+#
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set
+# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set
+# CONFIG_MEDIA_RADIO_SUPPORT is not set
+# CONFIG_MEDIA_SDR_SUPPORT is not set
+# CONFIG_MEDIA_RC_SUPPORT is not set
+# CONFIG_MEDIA_CONTROLLER is not set
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L2=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEOBUF2_CORE=y
+CONFIG_VIDEOBUF2_MEMOPS=y
+CONFIG_VIDEOBUF2_VMALLOC=y
+# CONFIG_TTPCI_EEPROM is not set
+
+#
+# Media drivers
+#
+CONFIG_MEDIA_USB_SUPPORT=y
+
+#
+# Webcam devices
+#
+CONFIG_USB_VIDEO_CLASS=y
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+CONFIG_USB_GSPCA=m
+# CONFIG_USB_M5602 is not set
+# CONFIG_USB_STV06XX is not set
+# CONFIG_USB_GL860 is not set
+# CONFIG_USB_GSPCA_BENQ is not set
+# CONFIG_USB_GSPCA_CONEX is not set
+# CONFIG_USB_GSPCA_CPIA1 is not set
+# CONFIG_USB_GSPCA_DTCS033 is not set
+# CONFIG_USB_GSPCA_ETOMS is not set
+# CONFIG_USB_GSPCA_FINEPIX is not set
+# CONFIG_USB_GSPCA_JEILINJ is not set
+# CONFIG_USB_GSPCA_JL2005BCD is not set
+# CONFIG_USB_GSPCA_KINECT is not set
+# CONFIG_USB_GSPCA_KONICA is not set
+# CONFIG_USB_GSPCA_MARS is not set
+# CONFIG_USB_GSPCA_MR97310A is not set
+# CONFIG_USB_GSPCA_NW80X is not set
+# CONFIG_USB_GSPCA_OV519 is not set
+# CONFIG_USB_GSPCA_OV534 is not set
+# CONFIG_USB_GSPCA_OV534_9 is not set
+# CONFIG_USB_GSPCA_PAC207 is not set
+# CONFIG_USB_GSPCA_PAC7302 is not set
+# CONFIG_USB_GSPCA_PAC7311 is not set
+# CONFIG_USB_GSPCA_SE401 is not set
+# CONFIG_USB_GSPCA_SN9C2028 is not set
+# CONFIG_USB_GSPCA_SN9C20X is not set
+# CONFIG_USB_GSPCA_SONIXB is not set
+# CONFIG_USB_GSPCA_SONIXJ is not set
+# CONFIG_USB_GSPCA_SPCA500 is not set
+# CONFIG_USB_GSPCA_SPCA501 is not set
+# CONFIG_USB_GSPCA_SPCA505 is not set
+# CONFIG_USB_GSPCA_SPCA506 is not set
+# CONFIG_USB_GSPCA_SPCA508 is not set
+# CONFIG_USB_GSPCA_SPCA561 is not set
+# CONFIG_USB_GSPCA_SPCA1528 is not set
+# CONFIG_USB_GSPCA_SQ905 is not set
+# CONFIG_USB_GSPCA_SQ905C is not set
+# CONFIG_USB_GSPCA_SQ930X is not set
+# CONFIG_USB_GSPCA_STK014 is not set
+# CONFIG_USB_GSPCA_STK1135 is not set
+# CONFIG_USB_GSPCA_STV0680 is not set
+# CONFIG_USB_GSPCA_SUNPLUS is not set
+# CONFIG_USB_GSPCA_T613 is not set
+# CONFIG_USB_GSPCA_TOPRO is not set
+# CONFIG_USB_GSPCA_TOUPTEK is not set
+# CONFIG_USB_GSPCA_TV8532 is not set
+# CONFIG_USB_GSPCA_VC032X is not set
+# CONFIG_USB_GSPCA_VICAM is not set
+# CONFIG_USB_GSPCA_XIRLINK_CIT is not set
+# CONFIG_USB_GSPCA_ZC3XX is not set
+# CONFIG_USB_PWC is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_USB_ZR364XX is not set
+# CONFIG_USB_STKWEBCAM is not set
+# CONFIG_USB_S2255 is not set
+
+#
+# Webcam, TV (analog/digital) USB devices
+#
+# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_V4L_PLATFORM_DRIVERS is not set
+# CONFIG_V4L_MEM2MEM_DRIVERS is not set
+# CONFIG_V4L_TEST_DRIVERS is not set
+
+#
+# Supported MMC/SDIO adapters
+#
+# CONFIG_CYPRESS_FIRMWARE is not set
+
+#
+# Media ancillary drivers (tuners, sensors, i2c, spi, frontends)
+#
+CONFIG_MEDIA_SUBDRV_AUTOSELECT=y
+
+#
+# Audio decoders, processors and mixers
+#
+
+#
+# RDS decoders
+#
+
+#
+# Video decoders
+#
+
+#
+# Video and audio decoders
+#
+
+#
+# Video encoders
+#
+
+#
+# Camera sensor devices
+#
+
+#
+# Flash devices
+#
+
+#
+# Video improvement chips
+#
+
+#
+# Audio/Video compression chips
+#
+
+#
+# Miscellaneous helper chips
+#
+
+#
+# Sensors used on soc_camera driver
+#
+
+#
+# Tools to develop new frontends
+#
+# CONFIG_DVB_DUMMY_FE is not set
+
+#
+# Graphics support
+#
+# CONFIG_IMX_IPUV3_CORE is not set
+# CONFIG_DRM is not set
+
+#
+# ACP (Audio CoProcessor) Configuration
+#
+
+#
+# Frame buffer Devices
+#
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB_CMDLINE=y
+CONFIG_FB_NOTIFY=y
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_ARMCLCD is not set
+# CONFIG_FB_OPENCORES is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_SMSCUFX is not set
+# CONFIG_FB_UDL is not set
+# CONFIG_FB_IBM_GXT4500 is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_FB_AUO_K190X is not set
+# CONFIG_FB_SIMPLE is not set
+# CONFIG_FB_SSD1307 is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+# CONFIG_LOGO is not set
+# CONFIG_SOUND is not set
+
+#
+# HID support
+#
+CONFIG_HID=y
+# CONFIG_HID_BATTERY_STRENGTH is not set
+# CONFIG_HIDRAW is not set
+# CONFIG_UHID is not set
+CONFIG_HID_GENERIC=y
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_ACRUX is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_APPLEIR is not set
+# CONFIG_HID_AUREAL is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_BETOP_FF is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_CMEDIA is not set
+# CONFIG_HID_CP2112 is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EMS_FF is not set
+# CONFIG_HID_ELECOM is not set
+# CONFIG_HID_ELO is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_GEMBIRD is not set
+# CONFIG_HID_GFRM is not set
+# CONFIG_HID_HOLTEK is not set
+# CONFIG_HID_KEYTOUCH is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_UCLOGIC is not set
+# CONFIG_HID_WALTOP is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_ICADE is not set
+# CONFIG_HID_TWINHAN is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LCPOWER is not set
+# CONFIG_HID_LENOVO is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MAGICMOUSE is not set
+CONFIG_HID_MICROSOFT=y
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_MULTITOUCH is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_ORTEK is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PENMOUNT is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_PICOLCD is not set
+# CONFIG_HID_PLANTRONICS is not set
+# CONFIG_HID_PRIMAX is not set
+# CONFIG_HID_ROCCAT is not set
+# CONFIG_HID_SAITEK is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SPEEDLINK is not set
+# CONFIG_HID_STEELSERIES is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_RMI is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TIVO is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_WACOM is not set
+# CONFIG_HID_XINMO is not set
+# CONFIG_HID_ZEROPLUS is not set
+# CONFIG_HID_ZYDACRON is not set
+# CONFIG_HID_SENSOR_HUB is not set
+# CONFIG_HID_ALPS is not set
+
+#
+# USB HID support
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# I2C HID support
+#
+# CONFIG_I2C_HID is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_COMMON=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB=y
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEFAULT_PERSIST=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_PLATFORM=y
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+# CONFIG_USB_FOTG210_HCD is not set
+# CONFIG_USB_MAX3421_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HCD_TEST_MODE is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_REALTEK is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_STORAGE_ENE_UB6250 is not set
+# CONFIG_USB_UAS is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USBIP_CORE is not set
+# CONFIG_USB_MUSB_HDRC is not set
+CONFIG_USB_DWC3=y
+# CONFIG_USB_DWC3_HOST is not set
+# CONFIG_USB_DWC3_GADGET is not set
+CONFIG_USB_DWC3_DUAL_ROLE=y
+
+#
+# Platform Glue Driver Support
+#
+CONFIG_USB_DWC3_OF_SIMPLE=y
+# CONFIG_USB_DWC2 is not set
+# CONFIG_USB_CHIPIDEA is not set
+# CONFIG_USB_ISP1760 is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_EHSET_TEST_FIXTURE is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_YUREX is not set
+# CONFIG_USB_EZUSB_FX2 is not set
+# CONFIG_USB_HSIC_USB3503 is not set
+# CONFIG_USB_HSIC_USB4604 is not set
+# CONFIG_USB_LINK_LAYER_TEST is not set
+
+#
+# USB Physical Layer drivers
+#
+# CONFIG_USB_PHY is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_USB_ISP1301 is not set
+# CONFIG_USB_ULPI is not set
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2
+
+#
+# USB Peripheral Controller
+#
+# CONFIG_USB_FUSB300 is not set
+# CONFIG_USB_FOTG210_UDC is not set
+# CONFIG_USB_GR_UDC is not set
+# CONFIG_USB_R8A66597 is not set
+# CONFIG_USB_PXA27X is not set
+# CONFIG_USB_MV_UDC is not set
+# CONFIG_USB_MV_U3D is not set
+# CONFIG_USB_M66592 is not set
+# CONFIG_USB_BDC_UDC is not set
+# CONFIG_USB_NET2272 is not set
+# CONFIG_USB_GADGET_XILINX is not set
+# CONFIG_USB_DUMMY_HCD is not set
+CONFIG_USB_LIBCOMPOSITE=y
+CONFIG_USB_U_ETHER=y
+CONFIG_USB_F_ECM=y
+CONFIG_USB_F_RNDIS=y
+CONFIG_USB_CONFIGFS=y
+# CONFIG_USB_CONFIGFS_SERIAL is not set
+# CONFIG_USB_CONFIGFS_ACM is not set
+# CONFIG_USB_CONFIGFS_OBEX is not set
+# CONFIG_USB_CONFIGFS_NCM is not set
+CONFIG_USB_CONFIGFS_ECM=y
+# CONFIG_USB_CONFIGFS_ECM_SUBSET is not set
+CONFIG_USB_CONFIGFS_RNDIS=y
+# CONFIG_USB_CONFIGFS_EEM is not set
+# CONFIG_USB_CONFIGFS_MASS_STORAGE is not set
+# CONFIG_USB_CONFIGFS_F_LB_SS is not set
+# CONFIG_USB_CONFIGFS_F_FS is not set
+# CONFIG_USB_CONFIGFS_F_HID is not set
+# CONFIG_USB_CONFIGFS_F_UVC is not set
+# CONFIG_USB_CONFIGFS_F_PRINTER is not set
+# CONFIG_USB_ULPI_BUS is not set
+# CONFIG_UWB is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_PWRSEQ_EMMC=y
+CONFIG_PWRSEQ_SIMPLE=y
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_MINORS=8
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_ARMMMCI is not set
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+# CONFIG_MMC_SDHCI_OF_ARASAN is not set
+# CONFIG_MMC_SDHCI_OF_AT91 is not set
+CONFIG_MMC_SDHCI_GOKE=y
+# CONFIG_MMC_SDHCI_F_SDH30 is not set
+# CONFIG_MMC_SPI is not set
+# CONFIG_MMC_DW is not set
+# CONFIG_MMC_VUB300 is not set
+# CONFIG_MMC_USHC is not set
+# CONFIG_MMC_USDHI6ROL0 is not set
+# CONFIG_MMC_MTK is not set
+# CONFIG_MMC_CQ_HCI is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_EDAC_ATOMIC_SCRUB=y
+CONFIG_EDAC_SUPPORT=y
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+CONFIG_RTC_SYSTOHC=y
+CONFIG_RTC_SYSTOHC_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_ABB5ZES3 is not set
+# CONFIG_RTC_DRV_ABX80X is not set
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_HYM8563 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_ISL12022 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8523 is not set
+# CONFIG_RTC_DRV_PCF85063 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_BQ32K is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8010 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+# CONFIG_RTC_DRV_EM3027 is not set
+# CONFIG_RTC_DRV_RV8803 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T93 is not set
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1302 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1343 is not set
+# CONFIG_RTC_DRV_DS1347 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6916 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RX4581 is not set
+# CONFIG_RTC_DRV_RX6110 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
+# CONFIG_RTC_DRV_MCP795 is not set
+CONFIG_RTC_I2C_AND_SPI=y
+
+#
+# SPI and I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS3232 is not set
+# CONFIG_RTC_DRV_PCF2127 is not set
+# CONFIG_RTC_DRV_RV3029C2 is not set
+
+#
+# Platform RTC drivers
+#
+CONFIG_RTC_DRV_GOKE=y
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1685_FAMILY is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_DS2404 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+# CONFIG_RTC_DRV_ZYNQMP is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_PL030 is not set
+# CONFIG_RTC_DRV_PL031 is not set
+# CONFIG_RTC_DRV_SNVS is not set
+
+#
+# HID Sensor RTC drivers
+#
+# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set
+# CONFIG_DMADEVICES is not set
+
+#
+# DMABUF options
+#
+# CONFIG_SYNC_FILE is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+# CONFIG_VIRT_DRIVERS is not set
+
+#
+# Virtio drivers
+#
+# CONFIG_VIRTIO_MMIO is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_STAGING is not set
+# CONFIG_GOLDFISH is not set
+# CONFIG_CHROME_PLATFORMS is not set
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_COMMON_CLK=y
+
+#
+# Common Clock Framework
+#
+# CONFIG_COMMON_CLK_SI5351 is not set
+# CONFIG_COMMON_CLK_SI514 is not set
+# CONFIG_COMMON_CLK_SI570 is not set
+# CONFIG_COMMON_CLK_CDCE706 is not set
+# CONFIG_COMMON_CLK_CDCE925 is not set
+# CONFIG_COMMON_CLK_CS2000_CP is not set
+# CONFIG_CLK_QORIQ is not set
+# CONFIG_COMMON_CLK_NXP is not set
+# CONFIG_COMMON_CLK_PXA is not set
+# CONFIG_COMMON_CLK_PIC32 is not set
+CONFIG_COMMON_CLK_GK7202V300=y
+CONFIG_RESET_GOKE=y
+
+#
+# Hardware Spinlock drivers
+#
+
+#
+# Clock Source drivers
+#
+CONFIG_CLKSRC_OF=y
+CONFIG_CLKSRC_PROBE=y
+CONFIG_CLKSRC_MMIO=y
+CONFIG_ARM_ARCH_TIMER=y
+CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y
+# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS is not set
+CONFIG_ARM_TIMER_SP804=y
+# CONFIG_ATMEL_PIT is not set
+# CONFIG_SH_TIMER_CMT is not set
+# CONFIG_SH_TIMER_MTU2 is not set
+# CONFIG_SH_TIMER_TMU is not set
+# CONFIG_EM_TIMER_STI is not set
+# CONFIG_MAILBOX is not set
+# CONFIG_IOMMU_SUPPORT is not set
+
+#
+# Remoteproc drivers
+#
+# CONFIG_STE_MODEM_RPROC is not set
+
+#
+# Rpmsg drivers
+#
+
+#
+# SOC (System On Chip) specific Drivers
+#
+
+#
+# Broadcom SoC drivers
+#
+# CONFIG_SOC_BRCMSTB is not set
+# CONFIG_SUNXI_SRAM is not set
+# CONFIG_SOC_TI is not set
+# CONFIG_PM_DEVFREQ is not set
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
+# CONFIG_IIO is not set
+# CONFIG_PWM is not set
+CONFIG_IRQCHIP=y
+CONFIG_ARM_GIC=y
+CONFIG_ARM_GIC_MAX_NR=1
+# CONFIG_IPACK_BUS is not set
+CONFIG_RESET_CONTROLLER=y
+# CONFIG_RESET_ATH79 is not set
+# CONFIG_RESET_BERLIN is not set
+# CONFIG_RESET_LPC18XX is not set
+# CONFIG_RESET_MESON is not set
+# CONFIG_RESET_PISTACHIO is not set
+# CONFIG_RESET_SOCFPGA is not set
+# CONFIG_RESET_STM32 is not set
+# CONFIG_RESET_SUNXI is not set
+# CONFIG_TI_SYSCON_RESET is not set
+# CONFIG_RESET_ZYNQ is not set
+# CONFIG_FMC is not set
+
+#
+# PHY Subsystem
+#
+CONFIG_GENERIC_PHY=y
+# CONFIG_PHY_PXA_28NM_HSIC is not set
+# CONFIG_PHY_PXA_28NM_USB2 is not set
+# CONFIG_BCM_KONA_USB2_PHY is not set
+CONFIG_PHY_GOKE_USBP2=y
+# CONFIG_USB_MODE_OPTION is not set
+# CONFIG_POWERCAP is not set
+# CONFIG_MCB is not set
+
+#
+# Performance monitor support
+#
+# CONFIG_RAS is not set
+
+#
+# Android
+#
+# CONFIG_ANDROID is not set
+# CONFIG_NVMEM is not set
+# CONFIG_STM is not set
+# CONFIG_INTEL_TH is not set
+
+#
+# FPGA Configuration Support
+#
+# CONFIG_FPGA is not set
+
+#
+# goke driver support
+#
+
+#
+# Firmware Drivers
+#
+# CONFIG_FIRMWARE_MEMMAP is not set
+# CONFIG_FW_CFG_SYSFS is not set
+CONFIG_HAVE_ARM_SMCCC=y
+
+#
+# File systems
+#
+CONFIG_DCACHE_WORD_ACCESS=y
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_USE_FOR_EXT2=y
+# CONFIG_EXT4_FS_POSIX_ACL is not set
+# CONFIG_EXT4_FS_SECURITY is not set
+# CONFIG_EXT4_ENCRYPTION is not set
+# CONFIG_EXT4_DEBUG is not set
+CONFIG_JBD2=y
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+# CONFIG_F2FS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_EXPORTFS=y
+# CONFIG_EXPORTFS_BLOCK_OPS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_MANDATORY_FILE_LOCKING=y
+# CONFIG_FS_ENCRYPTION is not set
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_QUOTACTL is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+# CONFIG_OVERLAY_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_FAT_DEFAULT_UTF8 is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_PROC_CHILDREN is not set
+CONFIG_KERNFS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_TMPFS_XATTR=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=y
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ORANGEFS_FS is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_YAFFS_FS=y
+CONFIG_YAFFS_YAFFS1=y
+# CONFIG_YAFFS_9BYTE_TAGS is not set
+# CONFIG_YAFFS_DOES_ECC is not set
+CONFIG_YAFFS_YAFFS2=y
+CONFIG_YAFFS_AUTO_YAFFS2=y
+# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set
+# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
+# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set
+# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set
+# CONFIG_YAFFS_DISABLE_BACKGROUND is not set
+# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set
+CONFIG_YAFFS_XATTR=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+# CONFIG_JFFS2_LZMA is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_UBIFS_FS=y
+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_ATIME_SUPPORT is not set
+# CONFIG_LOGFS is not set
+CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX6FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_PSTORE is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V2=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+# CONFIG_NFS_SWAP is not set
+# CONFIG_NFS_V4_1 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFS_USE_LEGACY_DNS is not set
+CONFIG_NFS_USE_KERNEL_DNS=y
+# CONFIG_NFSD is not set
+CONFIG_GRACE_PERIOD=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_ACL_SUPPORT=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_DEBUG is not set
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=y
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+# CONFIG_NLS_MAC_ROMAN is not set
+# CONFIG_NLS_MAC_CELTIC is not set
+# CONFIG_NLS_MAC_CENTEURO is not set
+# CONFIG_NLS_MAC_CROATIAN is not set
+# CONFIG_NLS_MAC_CYRILLIC is not set
+# CONFIG_NLS_MAC_GAELIC is not set
+# CONFIG_NLS_MAC_GREEK is not set
+# CONFIG_NLS_MAC_ICELAND is not set
+# CONFIG_NLS_MAC_INUIT is not set
+# CONFIG_NLS_MAC_ROMANIAN is not set
+# CONFIG_NLS_MAC_TURKISH is not set
+CONFIG_NLS_UTF8=y
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+
+#
+# printk and dmesg options
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
+# CONFIG_BOOT_PRINTK_DELAY is not set
+
+#
+# Compile-time checks and compiler options
+#
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_READABLE_ASM is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_PAGE_OWNER is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_SECTION_MISMATCH_WARN_ONLY=y
+CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_DEBUG_KERNEL=y
+
+#
+# Memory Debugging
+#
+# CONFIG_PAGE_EXTENSION is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_PAGE_POISONING is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_SHIRQ is not set
+
+#
+# Debug Lockups and Hangs
+#
+# CONFIG_LOCKUP_DETECTOR is not set
+# CONFIG_DETECT_HUNG_TASK is not set
+# CONFIG_WQ_WATCHDOG is not set
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+CONFIG_PANIC_TIMEOUT=0
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHED_INFO is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_SCHED_STACK_END_CHECK is not set
+# CONFIG_DEBUG_TIMEKEEPING is not set
+# CONFIG_TIMER_STATS is not set
+
+#
+# Lock Debugging (spinlocks, mutexes, etc...)
+#
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_ATOMIC_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_LOCK_TORTURE_TEST is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_PI_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+
+#
+# RCU Debugging
+#
+# CONFIG_PROVE_RCU is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_TORTURE_TEST is not set
+# CONFIG_RCU_PERF_TEST is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_TRACE is not set
+# CONFIG_RCU_EQS_DEBUG is not set
+# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_NOTIFIER_ERROR_INJECTION is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+
+#
+# Runtime Testing
+#
+# CONFIG_TEST_LIST_SORT is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_RBTREE_TEST is not set
+# CONFIG_INTERVAL_TREE_TEST is not set
+# CONFIG_PERCPU_TEST is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_TEST_HEXDUMP is not set
+# CONFIG_TEST_STRING_HELPERS is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_TEST_PRINTF is not set
+# CONFIG_TEST_BITMAP is not set
+# CONFIG_TEST_UUID is not set
+# CONFIG_TEST_RHASHTABLE is not set
+# CONFIG_TEST_HASH is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_TEST_LKM is not set
+# CONFIG_TEST_USER_COPY is not set
+# CONFIG_TEST_BPF is not set
+# CONFIG_TEST_FIRMWARE is not set
+# CONFIG_TEST_UDELAY is not set
+# CONFIG_MEMTEST is not set
+# CONFIG_TEST_STATIC_KEYS is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set
+# CONFIG_UBSAN is not set
+CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
+CONFIG_STRICT_DEVMEM=y
+# CONFIG_IO_STRICT_DEVMEM is not set
+# CONFIG_ARM_PTDUMP is not set
+# CONFIG_ARM_UNWIND is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_LL is not set
+CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
+# CONFIG_DEBUG_UART_8250 is not set
+CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
+# CONFIG_PID_IN_CONTEXTIDR is not set
+# CONFIG_DEBUG_SET_MODULE_RONX is not set
+# CONFIG_CORESIGHT is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_PERSISTENT_KEYRINGS is not set
+# CONFIG_ENCRYPTED_KEYS is not set
+# CONFIG_KEY_DH_OPERATIONS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y
+CONFIG_HAVE_ARCH_HARDENED_USERCOPY=y
+# CONFIG_HARDENED_USERCOPY is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_RNG_DEFAULT=m
+CONFIG_CRYPTO_AKCIPHER2=y
+CONFIG_CRYPTO_KPP2=y
+# CONFIG_CRYPTO_RSA is not set
+# CONFIG_CRYPTO_DH is not set
+# CONFIG_CRYPTO_ECDH is not set
+CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_USER is not set
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_NULL2=y
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_MCRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+# CONFIG_CRYPTO_CHACHA20POLY1305 is not set
+CONFIG_CRYPTO_SEQIV=m
+CONFIG_CRYPTO_ECHAINIV=m
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+CONFIG_CRYPTO_CTR=m
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+# CONFIG_CRYPTO_KEYWRAP is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_CMAC is not set
+CONFIG_CRYPTO_HMAC=m
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_CRC32 is not set
+CONFIG_CRYPTO_CRCT10DIF=y
+CONFIG_CRYPTO_GHASH=m
+# CONFIG_CRYPTO_POLY1305 is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=y
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_SHA3 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_CHACHA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_LZO=y
+# CONFIG_CRYPTO_842 is not set
+# CONFIG_CRYPTO_LZ4 is not set
+# CONFIG_CRYPTO_LZ4HC is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_DRBG_MENU=m
+CONFIG_CRYPTO_DRBG_HMAC=y
+# CONFIG_CRYPTO_DRBG_HASH is not set
+# CONFIG_CRYPTO_DRBG_CTR is not set
+CONFIG_CRYPTO_DRBG=m
+CONFIG_CRYPTO_JITTERENTROPY=m
+# CONFIG_CRYPTO_USER_API_HASH is not set
+# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
+# CONFIG_CRYPTO_USER_API_RNG is not set
+# CONFIG_CRYPTO_USER_API_AEAD is not set
+# CONFIG_CRYPTO_HW is not set
+# CONFIG_ASYMMETRIC_KEY_TYPE is not set
+
+#
+# Certificates for signature checking
+#
+# CONFIG_ARM_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_HAVE_ARCH_BITREVERSE=y
+CONFIG_RATIONAL=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_NET_UTILS=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IO=y
+CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=y
+# CONFIG_CRC8 is not set
+# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set
+# CONFIG_RANDOM32_SELFTEST is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_LZ4_DECOMPRESS=y
+CONFIG_XZ_DEC=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_BCJ=y
+# CONFIG_XZ_DEC_TEST is not set
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_LZ4=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_ASSOCIATIVE_ARRAY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_HAS_DMA=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
+# CONFIG_IRQ_POLL is not set
+CONFIG_LIBFDT=y
+CONFIG_OID_REGISTRY=y
+# CONFIG_SG_SPLIT is not set
+CONFIG_SG_POOL=y
+CONFIG_ARCH_HAS_SG_CHAIN=y
+CONFIG_SBITMAP=y
+# CONFIG_VIRTUALIZATION is not set
diff -urN linux-4.9.37/arch/arm/configs/gk7202v300_mini_defconfig linux-4.9.y/arch/arm/configs/gk7202v300_mini_defconfig
--- linux-4.9.37/arch/arm/configs/gk7202v300_mini_defconfig 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/arch/arm/configs/gk7202v300_mini_defconfig 2021-06-07 13:01:32.000000000 +0300
@@ -0,0 +1,1791 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/arm 4.9.37 Kernel Configuration
+#
+CONFIG_ARM=y
+CONFIG_ARM_HAS_SG_CHAIN=y
+CONFIG_MIGHT_HAVE_PCI=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_ARM_PATCH_PHYS_VIRT=y
+CONFIG_GENERIC_BUG=y
+CONFIG_PGTABLE_LEVELS=2
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_IRQ_WORK=y
+CONFIG_BUILDTIME_EXTABLE_SORT=y
+
+#
+# General setup
+#
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+# CONFIG_COMPILE_TEST is not set
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_HAVE_KERNEL_LZ4=y
+# CONFIG_KERNEL_GZIP is not set
+# CONFIG_KERNEL_LZMA is not set
+CONFIG_KERNEL_XZ=y
+# CONFIG_KERNEL_LZO is not set
+# CONFIG_KERNEL_LZ4 is not set
+CONFIG_DEFAULT_HOSTNAME="(none)"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_CROSS_MEMORY_ATTACH=y
+CONFIG_FHANDLE=y
+CONFIG_USELIB=y
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_ARCH_AUDITSYSCALL=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_IRQ_DOMAIN_HIERARCHY=y
+CONFIG_HANDLE_DOMAIN_IRQ=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_ARCH_CLOCKSOURCE_DATA=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+
+#
+# Timers subsystem
+#
+CONFIG_HZ_PERIODIC=y
+# CONFIG_NO_HZ_IDLE is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set
+# CONFIG_IRQ_TIME_ACCOUNTING is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TINY_RCU=y
+# CONFIG_RCU_EXPERT is not set
+CONFIG_SRCU=y
+# CONFIG_TASKS_RCU is not set
+# CONFIG_RCU_STALL_COMMON is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_RCU_EXPEDITE_BOOT is not set
+# CONFIG_BUILD_BIN2C is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_NMI_LOG_BUF_SHIFT=13
+CONFIG_GENERIC_SCHED_CLOCK=y
+CONFIG_CGROUPS=y
+# CONFIG_MEMCG is not set
+# CONFIG_BLK_CGROUP is not set
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUP_PIDS is not set
+# CONFIG_CGROUP_FREEZER is not set
+# CONFIG_CPUSETS is not set
+# CONFIG_CGROUP_DEVICE is not set
+# CONFIG_CGROUP_CPUACCT is not set
+# CONFIG_CGROUP_DEBUG is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+CONFIG_NAMESPACES=y
+CONFIG_UTS_NS=y
+CONFIG_IPC_NS=y
+# CONFIG_USER_NS is not set
+CONFIG_PID_NS=y
+CONFIG_NET_NS=y
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_HAVE_UID16=y
+CONFIG_BPF=y
+# CONFIG_EXPERT is not set
+CONFIG_UID16=y
+CONFIG_MULTIUSER=y
+# CONFIG_SGETMASK_SYSCALL is not set
+CONFIG_SYSFS_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set
+CONFIG_KALLSYMS_BASE_RELATIVE=y
+CONFIG_PRINTK=y
+CONFIG_PRINTK_NMI=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+# CONFIG_BPF_SYSCALL is not set
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_ADVISE_SYSCALLS=y
+# CONFIG_USERFAULTFD is not set
+CONFIG_MEMBARRIER=y
+# CONFIG_EMBEDDED is not set
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLAB_FREELIST_RANDOM is not set
+# CONFIG_SYSTEM_DATA_VERIFICATION is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+# CONFIG_JUMP_LABEL is not set
+# CONFIG_UPROBES is not set
+# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_ARCH_USE_BUILTIN_BSWAP=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_NMI=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_IDLE_POLL_SETUP=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_HAVE_GCC_PLUGINS=y
+# CONFIG_GCC_PLUGINS is not set
+CONFIG_HAVE_CC_STACKPROTECTOR=y
+CONFIG_CC_STACKPROTECTOR=y
+# CONFIG_CC_STACKPROTECTOR_NONE is not set
+# CONFIG_CC_STACKPROTECTOR_REGULAR is not set
+CONFIG_CC_STACKPROTECTOR_STRONG=y
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_MODULES_USE_ELF_REL=y
+CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_HAVE_ARCH_MMAP_RND_BITS=y
+CONFIG_HAVE_EXIT_THREAD=y
+CONFIG_ARCH_MMAP_RND_BITS_MIN=8
+CONFIG_ARCH_MMAP_RND_BITS_MAX=16
+CONFIG_ARCH_MMAP_RND_BITS=8
+# CONFIG_HAVE_ARCH_HASH is not set
+# CONFIG_ISA_BUS_API is not set
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_OLD_SIGACTION=y
+# CONFIG_CPU_NO_EFFICIENT_FFS is not set
+# CONFIG_HAVE_ARCH_VMAP_STACK is not set
+
+#
+# GCOV-based kernel profiling
+#
+CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_MODULE_SIG is not set
+# CONFIG_MODULE_COMPRESS is not set
+# CONFIG_TRIM_UNUSED_KSYMS is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+CONFIG_BLK_DEV_BSG=y
+# CONFIG_BLK_DEV_BSGLIB is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+CONFIG_BLK_CMDLINE_PARSER=y
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_AIX_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_CMDLINE_PARTITION=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+CONFIG_INLINE_READ_UNLOCK=y
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+CONFIG_INLINE_WRITE_UNLOCK=y
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+CONFIG_MMU=y
+CONFIG_ARCH_MULTIPLATFORM=y
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_LPC32XX is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C24XX is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP1 is not set
+
+#
+# Multiple platform selection
+#
+
+#
+# CPU Core family selection
+#
+# CONFIG_ARCH_MULTI_V6 is not set
+CONFIG_ARCH_MULTI_V7=y
+CONFIG_ARCH_MULTI_V6_V7=y
+# CONFIG_ARCH_MULTI_CPU_AUTO is not set
+# CONFIG_ARCH_VIRT is not set
+# CONFIG_ARCH_MVEBU is not set
+# CONFIG_ARCH_ALPINE is not set
+# CONFIG_ARCH_ARTPEC is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_BCM is not set
+# CONFIG_ARCH_BERLIN is not set
+# CONFIG_ARCH_DIGICOLOR is not set
+# CONFIG_ARCH_HIGHBANK is not set
+# CONFIG_ARCH_HISI is not set
+CONFIG_ARCH_GOKE=y
+
+#
+# Goke platform type
+#
+# CONFIG_ARCH_GK7205V200 is not set
+# CONFIG_ARCH_GK7205V300 is not set
+CONFIG_ARCH_GK7202V300=y
+# CONFIG_ARCH_GK7605V100 is not set
+# CONFIG_GOKE_MC is not set
+CONFIG_BSP_ZRELADDR=0x40008000
+CONFIG_BSP_PARAMS_PHYS=0x00000100
+CONFIG_BSP_INITRD_PHYS=0x00800000
+# CONFIG_ARCH_KEYSTONE is not set
+# CONFIG_ARCH_MESON is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_MEDIATEK is not set
+
+#
+# TI OMAP/AM/DM/DRA Family
+#
+# CONFIG_ARCH_OMAP3 is not set
+# CONFIG_ARCH_OMAP4 is not set
+# CONFIG_SOC_OMAP5 is not set
+# CONFIG_SOC_AM33XX is not set
+# CONFIG_SOC_AM43XX is not set
+# CONFIG_SOC_DRA7XX is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_QCOM is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_ROCKCHIP is not set
+# CONFIG_ARCH_SOCFPGA is not set
+# CONFIG_PLAT_SPEAR is not set
+# CONFIG_ARCH_STI is not set
+# CONFIG_ARCH_S5PV210 is not set
+# CONFIG_ARCH_EXYNOS is not set
+# CONFIG_ARCH_RENESAS is not set
+# CONFIG_ARCH_SUNXI is not set
+# CONFIG_ARCH_SIRF is not set
+# CONFIG_ARCH_TANGO is not set
+# CONFIG_ARCH_TEGRA is not set
+# CONFIG_ARCH_UNIPHIER is not set
+# CONFIG_ARCH_U8500 is not set
+# CONFIG_ARCH_VEXPRESS is not set
+# CONFIG_ARCH_WM8850 is not set
+# CONFIG_ARCH_ZX is not set
+# CONFIG_ARCH_ZYNQ is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_V7=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_LPAE is not set
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+# CONFIG_ARM_THUMB is not set
+# CONFIG_ARM_THUMBEE is not set
+CONFIG_ARM_VIRT_EXT=y
+# CONFIG_SWP_EMULATE is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_KUSER_HELPERS=y
+# CONFIG_VDSO is not set
+CONFIG_MIGHT_HAVE_CACHE_L2X0=y
+# CONFIG_CACHE_L2X0 is not set
+CONFIG_ARM_L1_CACHE_SHIFT_6=y
+CONFIG_ARM_L1_CACHE_SHIFT=6
+CONFIG_ARM_DMA_MEM_BUFFERABLE=y
+# CONFIG_DEBUG_RODATA is not set
+CONFIG_MULTI_IRQ_HANDLER=y
+# CONFIG_ARM_ERRATA_430973 is not set
+# CONFIG_ARM_ERRATA_720789 is not set
+# CONFIG_ARM_ERRATA_754322 is not set
+# CONFIG_ARM_ERRATA_775420 is not set
+# CONFIG_ARM_ERRATA_773022 is not set
+# CONFIG_ARM_ERRATA_818325_852422 is not set
+# CONFIG_ARM_ERRATA_821420 is not set
+# CONFIG_ARM_ERRATA_825619 is not set
+# CONFIG_ARM_ERRATA_852421 is not set
+# CONFIG_ARM_ERRATA_852423 is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS_GENERIC is not set
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_HAVE_SMP=y
+# CONFIG_SMP is not set
+CONFIG_HAVE_ARM_ARCH_TIMER=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_3G_OPT is not set
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_ARM_PSCI is not set
+CONFIG_ARCH_NR_GPIO=0
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ_FIXED=0
+CONFIG_HZ_100=y
+# CONFIG_HZ_200 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_500 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
+# CONFIG_SCHED_HRTICK is not set
+# CONFIG_THUMB2_KERNEL is not set
+# CONFIG_ARM_PATCH_IDIV is not set
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_HAVE_ARCH_PFN_VALID=y
+# CONFIG_HIGHMEM is not set
+# CONFIG_CPU_SW_DOMAIN_PAN is not set
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+# CONFIG_ARM_MODULE_PLTS is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_NO_BOOTMEM=y
+# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_COMPACTION=y
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NEED_PER_CPU_KM=y
+# CONFIG_CLEANCACHE is not set
+# CONFIG_CMA is not set
+# CONFIG_ZPOOL is not set
+# CONFIG_ZBUD is not set
+# CONFIG_ZSMALLOC is not set
+CONFIG_GENERIC_EARLY_IOREMAP=y
+# CONFIG_IDLE_PAGE_TRACKING is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+# CONFIG_SECCOMP is not set
+CONFIG_SWIOTLB=y
+CONFIG_IOMMU_HELPER=y
+# CONFIG_PARAVIRT is not set
+# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set
+# CONFIG_XEN is not set
+
+#
+# Boot options
+#
+CONFIG_USE_OF=y
+CONFIG_ATAGS=y
+# CONFIG_DEPRECATED_PARAM_STRUCT is not set
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER=y
+# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set
+CONFIG_CMDLINE=""
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_AUTO_ZRELADDR=y
+# CONFIG_EFI is not set
+
+#
+# CPU Power Management
+#
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# CPU Idle
+#
+# CONFIG_CPU_IDLE is not set
+# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+# CONFIG_KERNEL_MODE_NEON is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_ELFCORE=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
+CONFIG_BINFMT_SCRIPT=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_COREDUMP=y
+
+#
+# Power management options
+#
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_PM_SLEEP=y
+# CONFIG_PM_AUTOSLEEP is not set
+# CONFIG_PM_WAKELOCKS is not set
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_APM_EMULATION is not set
+CONFIG_PM_CLK=y
+# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_CPU_PM=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARM_CPU_SUSPEND=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+CONFIG_UNIX=y
+# CONFIG_UNIX_DIAG is not set
+# CONFIG_NET_KEY is not set
+# CONFIG_INET is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NET_PTP_CLASSIFY is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_VSOCKETS is not set
+# CONFIG_NETLINK_DIAG is not set
+# CONFIG_MPLS is not set
+# CONFIG_HSR is not set
+# CONFIG_SOCK_CGROUP_DATA is not set
+# CONFIG_CGROUP_NET_PRIO is not set
+# CONFIG_CGROUP_NET_CLASSID is not set
+CONFIG_NET_RX_BUSY_POLL=y
+CONFIG_BQL=y
+# CONFIG_BPF_JIT is not set
+
+#
+# Network testing
+#
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_STREAM_PARSER is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_NFC is not set
+# CONFIG_LWTUNNEL is not set
+# CONFIG_DST_CACHE is not set
+# CONFIG_NET_DEVLINK is not set
+CONFIG_MAY_USE_DEVLINK=y
+CONFIG_HAVE_CBPF_JIT=y
+
+#
+# Device Drivers
+#
+CONFIG_ARM_AMBA=y
+
+#
+# Generic Driver Options
+#
+# CONFIG_UEVENT_HELPER is not set
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_FW_LOADER=y
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set
+CONFIG_ALLOW_DEV_COREDUMP=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+CONFIG_REGMAP=y
+CONFIG_REGMAP_MMIO=y
+# CONFIG_DMA_SHARED_BUFFER is not set
+
+#
+# Bus devices
+#
+# CONFIG_BRCMSTB_GISB_ARB is not set
+# CONFIG_VEXPRESS_CONFIG is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+CONFIG_MTD_OF_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
+# CONFIG_MTD_OOPS is not set
+# CONFIG_MTD_PARTITIONED_MASTER is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SST25L is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOCG3 is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR & LPDDR2 PCM memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_LPDDR2_NVM is not set
+CONFIG_MTD_SPI_NOR=y
+# CONFIG_MTD_MT81xx_NOR is not set
+# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
+# CONFIG_SPI_CADENCE_QUADSPI is not set
+CONFIG_SPI_GOKE_SFC=y
+CONFIG_CLOSE_SPI_8PIN_4IO=y
+CONFIG_GOKE_SPI_BLOCK_PROTECT=y
+# CONFIG_MTD_UBI is not set
+CONFIG_DTC=y
+CONFIG_OF=y
+# CONFIG_OF_UNITTEST is not set
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_RESERVED_MEM=y
+# CONFIG_OF_OVERLAY is not set
+CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_NULL_BLK is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+
+#
+# DRBD disabled because PROC_FS or INET not selected
+#
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=65536
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_NVME_TARGET is not set
+
+#
+# Misc devices
+#
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_DUMMY_IRQ is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_APDS9802ALS is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_ISL29020 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_BH1770 is not set
+# CONFIG_SENSORS_APDS990X is not set
+# CONFIG_HMC6352 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_TI_DAC7512 is not set
+# CONFIG_USB_SWITCH_FSA9480 is not set
+# CONFIG_LATTICE_ECP3_CONFIG is not set
+# CONFIG_SRAM is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_EEPROM_93XX46 is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_SENSORS_LIS3_SPI is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
+
+#
+# Altera FPGA firmware download module
+#
+# CONFIG_ALTERA_STAPL is not set
+
+#
+# Intel MIC Bus Driver
+#
+
+#
+# SCIF Bus Driver
+#
+
+#
+# VOP Bus Driver
+#
+
+#
+# Intel MIC Host Driver
+#
+
+#
+# Intel MIC Card Driver
+#
+
+#
+# SCIF Driver
+#
+
+#
+# Intel MIC Coprocessor State Management (COSM) Drivers
+#
+
+#
+# VOP Driver
+#
+# CONFIG_ECHO is not set
+# CONFIG_CXL_BASE is not set
+# CONFIG_CXL_AFU_DRIVER_OPS is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_NETDEVICES is not set
+# CONFIG_NVM is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+# CONFIG_INPUT_MATRIXKMAP is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+# CONFIG_RMI4_CORE is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_TTY=y
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_VT_CONSOLE_SLEEP=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVMEM=y
+# CONFIG_DEVKMEM is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_EARLYCON=y
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_AMBA_PL010 is not set
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set
+# CONFIG_SERIAL_MAX3100 is not set
+# CONFIG_SERIAL_MAX310X is not set
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_SCCNXP is not set
+# CONFIG_SERIAL_SC16IS7XX is not set
+# CONFIG_SERIAL_BCM63XX is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_XILINX_PS_UART is not set
+# CONFIG_SERIAL_ARC is not set
+# CONFIG_SERIAL_FSL_LPUART is not set
+# CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set
+# CONFIG_SERIAL_ST_ASC is not set
+# CONFIG_SERIAL_STM32 is not set
+# CONFIG_HVC_DCC is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_XILLYBUS is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MUX=y
+
+#
+# Multiplexer I2C Chip support
+#
+# CONFIG_I2C_MUX_PCA9541 is not set
+# CONFIG_I2C_MUX_PINCTRL is not set
+# CONFIG_I2C_MUX_REG is not set
+# CONFIG_I2C_DEMUX_PINCTRL is not set
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_DESIGNWARE_PLATFORM is not set
+# CONFIG_I2C_EMEV2 is not set
+CONFIG_I2C_GOKE=y
+# CONFIG_I2C_NOMADIK is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_PXA_PCI is not set
+# CONFIG_I2C_RK3X is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+CONFIG_DMA_MSG_MIN_LEN=5
+CONFIG_DMA_MSG_MAX_LEN=4090
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_SLAVE is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_ALTERA is not set
+# CONFIG_SPI_AXI_SPI_ENGINE is not set
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_CADENCE is not set
+# CONFIG_SPI_DESIGNWARE is not set
+# CONFIG_SPI_FSL_SPI is not set
+CONFIG_SPI_PL022=y
+# CONFIG_SPI_PXA2XX_PCI is not set
+# CONFIG_SPI_ROCKCHIP is not set
+# CONFIG_SPI_SC18IS602 is not set
+# CONFIG_SPI_XCOMM is not set
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_ZYNQMP_GQSPI is not set
+
+#
+# SPI Protocol Masters
+#
+CONFIG_SPI_SPIDEV=y
+# CONFIG_SPI_LOOPBACK_TEST is not set
+# CONFIG_SPI_TLE62X0 is not set
+# CONFIG_SPMI is not set
+# CONFIG_HSI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+# CONFIG_PTP_1588_CLOCK is not set
+
+#
+# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
+#
+CONFIG_PINCTRL=y
+
+#
+# Pin controllers
+#
+# CONFIG_DEBUG_PINCTRL is not set
+# CONFIG_PINCTRL_SINGLE is not set
+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
+# CONFIG_GPIOLIB is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_AVS is not set
+CONFIG_POWER_RESET=y
+# CONFIG_POWER_RESET_BRCMKONA is not set
+# CONFIG_POWER_RESET_BRCMSTB is not set
+CONFIG_POWER_RESET_GOKE=y
+# CONFIG_POWER_RESET_RESTART is not set
+# CONFIG_POWER_RESET_VERSATILE is not set
+# CONFIG_POWER_RESET_SYSCON is not set
+# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set
+# CONFIG_SYSCON_REBOOT_MODE is not set
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_TEST_POWER is not set
+# CONFIG_BATTERY_DS2780 is not set
+# CONFIG_BATTERY_DS2781 is not set
+# CONFIG_BATTERY_DS2782 is not set
+# CONFIG_BATTERY_SBS is not set
+# CONFIG_BATTERY_BQ27XXX is not set
+# CONFIG_BATTERY_MAX17040 is not set
+# CONFIG_BATTERY_MAX17042 is not set
+# CONFIG_CHARGER_MAX8903 is not set
+# CONFIG_CHARGER_LP8727 is not set
+# CONFIG_CHARGER_BQ2415X is not set
+# CONFIG_CHARGER_SMB347 is not set
+# CONFIG_BATTERY_GAUGE_LTC2941 is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+CONFIG_MFD_CORE=y
+# CONFIG_MFD_ACT8945A is not set
+# CONFIG_MFD_AS3711 is not set
+# CONFIG_MFD_AS3722 is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_ATMEL_FLEXCOM is not set
+# CONFIG_MFD_ATMEL_HLCDC is not set
+# CONFIG_MFD_BCM590XX is not set
+# CONFIG_MFD_AXP20X_I2C is not set
+# CONFIG_MFD_CROS_EC is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_DA9052_SPI is not set
+# CONFIG_MFD_DA9052_I2C is not set
+# CONFIG_MFD_DA9055 is not set
+# CONFIG_MFD_DA9062 is not set
+# CONFIG_MFD_DA9063 is not set
+# CONFIG_MFD_DA9150 is not set
+# CONFIG_MFD_EXYNOS_LPASS is not set
+# CONFIG_MFD_MC13XXX_SPI is not set
+# CONFIG_MFD_MC13XXX_I2C is not set
+# CONFIG_MFD_HI6421_PMIC is not set
+CONFIG_MFD_GOKE_FMC=y
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_KEMPLD is not set
+# CONFIG_MFD_88PM800 is not set
+# CONFIG_MFD_88PM805 is not set
+# CONFIG_MFD_88PM860X is not set
+# CONFIG_MFD_MAX14577 is not set
+# CONFIG_MFD_MAX77620 is not set
+# CONFIG_MFD_MAX77686 is not set
+# CONFIG_MFD_MAX77693 is not set
+# CONFIG_MFD_MAX77843 is not set
+# CONFIG_MFD_MAX8907 is not set
+# CONFIG_MFD_MAX8925 is not set
+# CONFIG_MFD_MAX8997 is not set
+# CONFIG_MFD_MAX8998 is not set
+# CONFIG_MFD_MT6397 is not set
+# CONFIG_MFD_MENF21BMC is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_MFD_RETU is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_PM8921_CORE is not set
+# CONFIG_MFD_RT5033 is not set
+# CONFIG_MFD_RC5T583 is not set
+# CONFIG_MFD_RK808 is not set
+# CONFIG_MFD_RN5T618 is not set
+# CONFIG_MFD_SEC_CORE is not set
+# CONFIG_MFD_SI476X_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_SKY81452 is not set
+# CONFIG_MFD_SMSC is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_MFD_STMPE is not set
+CONFIG_MFD_SYSCON=y
+# CONFIG_MFD_TI_AM335X_TSCADC is not set
+# CONFIG_MFD_LP3943 is not set
+# CONFIG_MFD_LP8788 is not set
+# CONFIG_MFD_PALMAS is not set
+# CONFIG_TPS6105X is not set
+# CONFIG_TPS6507X is not set
+# CONFIG_MFD_TPS65086 is not set
+# CONFIG_MFD_TPS65090 is not set
+# CONFIG_MFD_TPS65217 is not set
+# CONFIG_MFD_TI_LP873X is not set
+# CONFIG_MFD_TPS65218 is not set
+# CONFIG_MFD_TPS6586X is not set
+# CONFIG_MFD_TPS65912_I2C is not set
+# CONFIG_MFD_TPS65912_SPI is not set
+# CONFIG_MFD_TPS80031 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_TWL6040_CORE is not set
+# CONFIG_MFD_WL1273_CORE is not set
+# CONFIG_MFD_LM3533 is not set
+# CONFIG_MFD_TC3589X is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_MFD_ARIZONA_I2C is not set
+# CONFIG_MFD_ARIZONA_SPI is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X_I2C is not set
+# CONFIG_MFD_WM831X_SPI is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8994 is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_IMX_IPUV3_CORE is not set
+# CONFIG_DRM is not set
+
+#
+# ACP (Audio CoProcessor) Configuration
+#
+
+#
+# Frame buffer Devices
+#
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB_CMDLINE=y
+CONFIG_FB_NOTIFY=y
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_ARMCLCD is not set
+# CONFIG_FB_OPENCORES is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_IBM_GXT4500 is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_FB_AUO_K190X is not set
+# CONFIG_FB_SIMPLE is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+# CONFIG_LOGO is not set
+# CONFIG_SOUND is not set
+
+#
+# HID support
+#
+# CONFIG_HID is not set
+
+#
+# I2C HID support
+#
+# CONFIG_I2C_HID is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_UWB is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_EDAC_ATOMIC_SCRUB=y
+CONFIG_EDAC_SUPPORT=y
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+
+#
+# DMABUF options
+#
+# CONFIG_SYNC_FILE is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+# CONFIG_VIRT_DRIVERS is not set
+
+#
+# Virtio drivers
+#
+# CONFIG_VIRTIO_MMIO is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_STAGING is not set
+# CONFIG_GOLDFISH is not set
+# CONFIG_CHROME_PLATFORMS is not set
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_COMMON_CLK=y
+
+#
+# Common Clock Framework
+#
+# CONFIG_COMMON_CLK_SI5351 is not set
+# CONFIG_COMMON_CLK_SI514 is not set
+# CONFIG_COMMON_CLK_SI570 is not set
+# CONFIG_COMMON_CLK_CDCE706 is not set
+# CONFIG_COMMON_CLK_CDCE925 is not set
+# CONFIG_COMMON_CLK_CS2000_CP is not set
+# CONFIG_CLK_QORIQ is not set
+# CONFIG_COMMON_CLK_NXP is not set
+# CONFIG_COMMON_CLK_PXA is not set
+# CONFIG_COMMON_CLK_PIC32 is not set
+CONFIG_COMMON_CLK_GK7202V300=y
+CONFIG_RESET_GOKE=y
+
+#
+# Hardware Spinlock drivers
+#
+
+#
+# Clock Source drivers
+#
+CONFIG_CLKSRC_OF=y
+CONFIG_CLKSRC_PROBE=y
+CONFIG_CLKSRC_MMIO=y
+CONFIG_ARM_ARCH_TIMER=y
+# CONFIG_ARM_ARCH_TIMER_EVTSTREAM is not set
+# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS is not set
+CONFIG_ARM_TIMER_SP804=y
+# CONFIG_ATMEL_PIT is not set
+# CONFIG_SH_TIMER_CMT is not set
+# CONFIG_SH_TIMER_MTU2 is not set
+# CONFIG_SH_TIMER_TMU is not set
+# CONFIG_EM_TIMER_STI is not set
+# CONFIG_MAILBOX is not set
+# CONFIG_IOMMU_SUPPORT is not set
+
+#
+# Remoteproc drivers
+#
+# CONFIG_STE_MODEM_RPROC is not set
+
+#
+# Rpmsg drivers
+#
+
+#
+# SOC (System On Chip) specific Drivers
+#
+
+#
+# Broadcom SoC drivers
+#
+# CONFIG_SOC_BRCMSTB is not set
+# CONFIG_SUNXI_SRAM is not set
+# CONFIG_SOC_TI is not set
+# CONFIG_PM_DEVFREQ is not set
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
+# CONFIG_IIO is not set
+# CONFIG_PWM is not set
+CONFIG_IRQCHIP=y
+CONFIG_ARM_GIC=y
+CONFIG_ARM_GIC_MAX_NR=1
+# CONFIG_IPACK_BUS is not set
+CONFIG_RESET_CONTROLLER=y
+# CONFIG_RESET_ATH79 is not set
+# CONFIG_RESET_BERLIN is not set
+# CONFIG_RESET_LPC18XX is not set
+# CONFIG_RESET_MESON is not set
+# CONFIG_RESET_PISTACHIO is not set
+# CONFIG_RESET_SOCFPGA is not set
+# CONFIG_RESET_STM32 is not set
+# CONFIG_RESET_SUNXI is not set
+# CONFIG_TI_SYSCON_RESET is not set
+# CONFIG_RESET_ZYNQ is not set
+# CONFIG_FMC is not set
+
+#
+# PHY Subsystem
+#
+# CONFIG_GENERIC_PHY is not set
+# CONFIG_PHY_PXA_28NM_HSIC is not set
+# CONFIG_PHY_PXA_28NM_USB2 is not set
+# CONFIG_BCM_KONA_USB2_PHY is not set
+# CONFIG_PHY_GOKE_USBP2 is not set
+# CONFIG_USB_MODE_OPTION is not set
+# CONFIG_POWERCAP is not set
+# CONFIG_MCB is not set
+
+#
+# Performance monitor support
+#
+# CONFIG_RAS is not set
+
+#
+# Android
+#
+# CONFIG_ANDROID is not set
+# CONFIG_NVMEM is not set
+# CONFIG_STM is not set
+# CONFIG_INTEL_TH is not set
+
+#
+# FPGA Configuration Support
+#
+# CONFIG_FPGA is not set
+
+#
+# goke driver support
+#
+
+#
+# Firmware Drivers
+#
+# CONFIG_FIRMWARE_MEMMAP is not set
+# CONFIG_FW_CFG_SYSFS is not set
+CONFIG_HAVE_ARM_SMCCC=y
+
+#
+# File systems
+#
+CONFIG_DCACHE_WORD_ACCESS=y
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+# CONFIG_F2FS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_EXPORTFS=y
+# CONFIG_EXPORTFS_BLOCK_OPS is not set
+CONFIG_FILE_LOCKING=y
+# CONFIG_MANDATORY_FILE_LOCKING is not set
+# CONFIG_FS_ENCRYPTION is not set
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_QUOTACTL is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+# CONFIG_OVERLAY_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_PROC_CHILDREN is not set
+CONFIG_KERNFS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=y
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ORANGEFS_FS is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_YAFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+# CONFIG_JFFS2_LZMA is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_LOGFS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX6FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_PSTORE is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_MAC_ROMAN is not set
+# CONFIG_NLS_MAC_CELTIC is not set
+# CONFIG_NLS_MAC_CENTEURO is not set
+# CONFIG_NLS_MAC_CROATIAN is not set
+# CONFIG_NLS_MAC_CYRILLIC is not set
+# CONFIG_NLS_MAC_GAELIC is not set
+# CONFIG_NLS_MAC_GREEK is not set
+# CONFIG_NLS_MAC_ICELAND is not set
+# CONFIG_NLS_MAC_INUIT is not set
+# CONFIG_NLS_MAC_ROMANIAN is not set
+# CONFIG_NLS_MAC_TURKISH is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Kernel hacking
+#
+
+#
+# printk and dmesg options
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
+# CONFIG_BOOT_PRINTK_DELAY is not set
+
+#
+# Compile-time checks and compiler options
+#
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_READABLE_ASM is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_PAGE_OWNER is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_SECTION_MISMATCH_WARN_ONLY=y
+CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_DEBUG_KERNEL=y
+
+#
+# Memory Debugging
+#
+# CONFIG_PAGE_EXTENSION is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_PAGE_POISONING is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_SHIRQ is not set
+
+#
+# Debug Lockups and Hangs
+#
+# CONFIG_LOCKUP_DETECTOR is not set
+# CONFIG_DETECT_HUNG_TASK is not set
+# CONFIG_WQ_WATCHDOG is not set
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+CONFIG_PANIC_TIMEOUT=0
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHED_INFO is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_SCHED_STACK_END_CHECK is not set
+# CONFIG_DEBUG_TIMEKEEPING is not set
+# CONFIG_TIMER_STATS is not set
+
+#
+# Lock Debugging (spinlocks, mutexes, etc...)
+#
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_ATOMIC_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_LOCK_TORTURE_TEST is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_PI_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+
+#
+# RCU Debugging
+#
+# CONFIG_PROVE_RCU is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_TORTURE_TEST is not set
+# CONFIG_RCU_PERF_TEST is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_TRACE is not set
+# CONFIG_RCU_EQS_DEBUG is not set
+# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_NOTIFIER_ERROR_INJECTION is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+
+#
+# Runtime Testing
+#
+# CONFIG_TEST_LIST_SORT is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_RBTREE_TEST is not set
+# CONFIG_INTERVAL_TREE_TEST is not set
+# CONFIG_PERCPU_TEST is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_TEST_HEXDUMP is not set
+# CONFIG_TEST_STRING_HELPERS is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_TEST_PRINTF is not set
+# CONFIG_TEST_BITMAP is not set
+# CONFIG_TEST_UUID is not set
+# CONFIG_TEST_RHASHTABLE is not set
+# CONFIG_TEST_HASH is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_TEST_LKM is not set
+# CONFIG_TEST_USER_COPY is not set
+# CONFIG_TEST_BPF is not set
+# CONFIG_TEST_FIRMWARE is not set
+# CONFIG_TEST_UDELAY is not set
+# CONFIG_MEMTEST is not set
+# CONFIG_TEST_STATIC_KEYS is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set
+# CONFIG_UBSAN is not set
+CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
+CONFIG_STRICT_DEVMEM=y
+# CONFIG_IO_STRICT_DEVMEM is not set
+# CONFIG_ARM_PTDUMP is not set
+# CONFIG_ARM_UNWIND is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_LL is not set
+CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
+# CONFIG_DEBUG_UART_8250 is not set
+CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
+# CONFIG_PID_IN_CONTEXTIDR is not set
+# CONFIG_DEBUG_SET_MODULE_RONX is not set
+# CONFIG_CORESIGHT is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y
+CONFIG_HAVE_ARCH_HARDENED_USERCOPY=y
+# CONFIG_HARDENED_USERCOPY is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+# CONFIG_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_HAVE_ARCH_BITREVERSE=y
+CONFIG_RATIONAL=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_NET_UTILS=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IO=y
+CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+# CONFIG_CRC8 is not set
+# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set
+# CONFIG_RANDOM32_SELFTEST is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_XZ_DEC=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_BCJ=y
+# CONFIG_XZ_DEC_TEST is not set
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_HAS_DMA=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
+# CONFIG_IRQ_POLL is not set
+CONFIG_LIBFDT=y
+# CONFIG_SG_SPLIT is not set
+# CONFIG_SG_POOL is not set
+CONFIG_ARCH_HAS_SG_CHAIN=y
+CONFIG_SBITMAP=y
+# CONFIG_VIRTUALIZATION is not set
diff -urN linux-4.9.37/arch/arm/configs/gk7205v200_emmc_defconfig linux-4.9.y/arch/arm/configs/gk7205v200_emmc_defconfig
--- linux-4.9.37/arch/arm/configs/gk7205v200_emmc_defconfig 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/arch/arm/configs/gk7205v200_emmc_defconfig 2021-06-07 13:01:32.000000000 +0300
@@ -0,0 +1,2975 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/arm 4.9.37 Kernel Configuration
+#
+CONFIG_ARM=y
+CONFIG_ARM_HAS_SG_CHAIN=y
+CONFIG_MIGHT_HAVE_PCI=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_ARM_PATCH_PHYS_VIRT=y
+CONFIG_GENERIC_BUG=y
+CONFIG_PGTABLE_LEVELS=2
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_IRQ_WORK=y
+CONFIG_BUILDTIME_EXTABLE_SORT=y
+
+#
+# General setup
+#
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+# CONFIG_COMPILE_TEST is not set
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_HAVE_KERNEL_LZ4=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_XZ is not set
+# CONFIG_KERNEL_LZO is not set
+# CONFIG_KERNEL_LZ4 is not set
+CONFIG_DEFAULT_HOSTNAME="(none)"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_CROSS_MEMORY_ATTACH=y
+CONFIG_FHANDLE=y
+CONFIG_USELIB=y
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_ARCH_AUDITSYSCALL=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_IRQ_DOMAIN_HIERARCHY=y
+CONFIG_HANDLE_DOMAIN_IRQ=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_ARCH_CLOCKSOURCE_DATA=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+
+#
+# Timers subsystem
+#
+CONFIG_HZ_PERIODIC=y
+# CONFIG_NO_HZ_IDLE is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set
+# CONFIG_IRQ_TIME_ACCOUNTING is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TINY_RCU=y
+# CONFIG_RCU_EXPERT is not set
+CONFIG_SRCU=y
+# CONFIG_TASKS_RCU is not set
+# CONFIG_RCU_STALL_COMMON is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_RCU_EXPEDITE_BOOT is not set
+# CONFIG_BUILD_BIN2C is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_NMI_LOG_BUF_SHIFT=13
+CONFIG_GENERIC_SCHED_CLOCK=y
+CONFIG_CGROUPS=y
+# CONFIG_MEMCG is not set
+# CONFIG_BLK_CGROUP is not set
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUP_PIDS is not set
+CONFIG_CGROUP_FREEZER=y
+# CONFIG_CPUSETS is not set
+# CONFIG_CGROUP_DEVICE is not set
+# CONFIG_CGROUP_CPUACCT is not set
+# CONFIG_CGROUP_DEBUG is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+CONFIG_NAMESPACES=y
+CONFIG_UTS_NS=y
+CONFIG_IPC_NS=y
+# CONFIG_USER_NS is not set
+CONFIG_PID_NS=y
+CONFIG_NET_NS=y
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_RD_XZ is not set
+# CONFIG_RD_LZO is not set
+CONFIG_RD_LZ4=y
+CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_HAVE_UID16=y
+CONFIG_BPF=y
+# CONFIG_EXPERT is not set
+CONFIG_UID16=y
+CONFIG_MULTIUSER=y
+# CONFIG_SGETMASK_SYSCALL is not set
+CONFIG_SYSFS_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set
+CONFIG_KALLSYMS_BASE_RELATIVE=y
+CONFIG_PRINTK=y
+CONFIG_PRINTK_NMI=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+# CONFIG_BPF_SYSCALL is not set
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_ADVISE_SYSCALLS=y
+# CONFIG_USERFAULTFD is not set
+CONFIG_MEMBARRIER=y
+# CONFIG_EMBEDDED is not set
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLAB_FREELIST_RANDOM is not set
+# CONFIG_SYSTEM_DATA_VERIFICATION is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+# CONFIG_JUMP_LABEL is not set
+# CONFIG_UPROBES is not set
+# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_ARCH_USE_BUILTIN_BSWAP=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_NMI=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_IDLE_POLL_SETUP=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_HAVE_GCC_PLUGINS=y
+# CONFIG_GCC_PLUGINS is not set
+CONFIG_HAVE_CC_STACKPROTECTOR=y
+CONFIG_CC_STACKPROTECTOR=y
+# CONFIG_CC_STACKPROTECTOR_NONE is not set
+# CONFIG_CC_STACKPROTECTOR_REGULAR is not set
+CONFIG_CC_STACKPROTECTOR_STRONG=y
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_MODULES_USE_ELF_REL=y
+CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_HAVE_ARCH_MMAP_RND_BITS=y
+CONFIG_HAVE_EXIT_THREAD=y
+CONFIG_ARCH_MMAP_RND_BITS_MIN=8
+CONFIG_ARCH_MMAP_RND_BITS_MAX=16
+CONFIG_ARCH_MMAP_RND_BITS=8
+# CONFIG_HAVE_ARCH_HASH is not set
+# CONFIG_ISA_BUS_API is not set
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_OLD_SIGACTION=y
+# CONFIG_CPU_NO_EFFICIENT_FFS is not set
+# CONFIG_HAVE_ARCH_VMAP_STACK is not set
+
+#
+# GCOV-based kernel profiling
+#
+CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_MODULE_SIG is not set
+# CONFIG_MODULE_COMPRESS is not set
+# CONFIG_TRIM_UNUSED_KSYMS is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+CONFIG_BLK_DEV_BSG=y
+# CONFIG_BLK_DEV_BSGLIB is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+CONFIG_BLK_CMDLINE_PARSER=y
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_AIX_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_CMDLINE_PARTITION=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+CONFIG_INLINE_READ_UNLOCK=y
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+CONFIG_INLINE_WRITE_UNLOCK=y
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+CONFIG_MMU=y
+CONFIG_ARCH_MULTIPLATFORM=y
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_LPC32XX is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C24XX is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP1 is not set
+
+#
+# Multiple platform selection
+#
+
+#
+# CPU Core family selection
+#
+# CONFIG_ARCH_MULTI_V6 is not set
+CONFIG_ARCH_MULTI_V7=y
+CONFIG_ARCH_MULTI_V6_V7=y
+# CONFIG_ARCH_MULTI_CPU_AUTO is not set
+# CONFIG_ARCH_VIRT is not set
+# CONFIG_ARCH_MVEBU is not set
+# CONFIG_ARCH_ALPINE is not set
+# CONFIG_ARCH_ARTPEC is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_BCM is not set
+# CONFIG_ARCH_BERLIN is not set
+# CONFIG_ARCH_DIGICOLOR is not set
+# CONFIG_ARCH_HIGHBANK is not set
+# CONFIG_ARCH_HISI is not set
+CONFIG_ARCH_GOKE=y
+
+#
+# Goke platform type
+#
+CONFIG_ARCH_GK7205V200=y
+# CONFIG_ARCH_GK7205V300 is not set
+# CONFIG_ARCH_GK7202V300 is not set
+# CONFIG_ARCH_GK7605V100 is not set
+# CONFIG_GOKE_MC is not set
+CONFIG_BSP_ZRELADDR=0x40008000
+CONFIG_BSP_PARAMS_PHYS=0x00000100
+CONFIG_BSP_INITRD_PHYS=0x00800000
+# CONFIG_ARCH_KEYSTONE is not set
+# CONFIG_ARCH_MESON is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_MEDIATEK is not set
+
+#
+# TI OMAP/AM/DM/DRA Family
+#
+# CONFIG_ARCH_OMAP3 is not set
+# CONFIG_ARCH_OMAP4 is not set
+# CONFIG_SOC_OMAP5 is not set
+# CONFIG_SOC_AM33XX is not set
+# CONFIG_SOC_AM43XX is not set
+# CONFIG_SOC_DRA7XX is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_QCOM is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_ROCKCHIP is not set
+# CONFIG_ARCH_SOCFPGA is not set
+# CONFIG_PLAT_SPEAR is not set
+# CONFIG_ARCH_STI is not set
+# CONFIG_ARCH_S5PV210 is not set
+# CONFIG_ARCH_EXYNOS is not set
+# CONFIG_ARCH_RENESAS is not set
+# CONFIG_ARCH_SUNXI is not set
+# CONFIG_ARCH_SIRF is not set
+# CONFIG_ARCH_TANGO is not set
+# CONFIG_ARCH_TEGRA is not set
+# CONFIG_ARCH_UNIPHIER is not set
+# CONFIG_ARCH_U8500 is not set
+# CONFIG_ARCH_VEXPRESS is not set
+# CONFIG_ARCH_WM8850 is not set
+# CONFIG_ARCH_ZX is not set
+# CONFIG_ARCH_ZYNQ is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_V7=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_LPAE is not set
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+CONFIG_ARM_THUMB=y
+# CONFIG_ARM_THUMBEE is not set
+CONFIG_ARM_VIRT_EXT=y
+# CONFIG_SWP_EMULATE is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_KUSER_HELPERS=y
+CONFIG_VDSO=y
+CONFIG_MIGHT_HAVE_CACHE_L2X0=y
+# CONFIG_CACHE_L2X0 is not set
+CONFIG_ARM_L1_CACHE_SHIFT_6=y
+CONFIG_ARM_L1_CACHE_SHIFT=6
+CONFIG_ARM_DMA_MEM_BUFFERABLE=y
+# CONFIG_DEBUG_RODATA is not set
+CONFIG_MULTI_IRQ_HANDLER=y
+# CONFIG_ARM_ERRATA_430973 is not set
+# CONFIG_ARM_ERRATA_720789 is not set
+# CONFIG_ARM_ERRATA_754322 is not set
+# CONFIG_ARM_ERRATA_775420 is not set
+# CONFIG_ARM_ERRATA_773022 is not set
+# CONFIG_ARM_ERRATA_818325_852422 is not set
+# CONFIG_ARM_ERRATA_821420 is not set
+# CONFIG_ARM_ERRATA_825619 is not set
+# CONFIG_ARM_ERRATA_852421 is not set
+# CONFIG_ARM_ERRATA_852423 is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS_GENERIC is not set
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_HAVE_SMP=y
+# CONFIG_SMP is not set
+CONFIG_HAVE_ARM_ARCH_TIMER=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_3G_OPT is not set
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_ARM_PSCI is not set
+CONFIG_ARCH_NR_GPIO=0
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ_FIXED=0
+CONFIG_HZ_100=y
+# CONFIG_HZ_200 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_500 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
+# CONFIG_SCHED_HRTICK is not set
+# CONFIG_THUMB2_KERNEL is not set
+CONFIG_ARM_PATCH_IDIV=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_HAVE_ARCH_PFN_VALID=y
+# CONFIG_HIGHMEM is not set
+# CONFIG_CPU_SW_DOMAIN_PAN is not set
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+# CONFIG_ARM_MODULE_PLTS is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_NO_BOOTMEM=y
+# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_COMPACTION=y
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NEED_PER_CPU_KM=y
+# CONFIG_CLEANCACHE is not set
+# CONFIG_CMA is not set
+# CONFIG_ZPOOL is not set
+# CONFIG_ZBUD is not set
+# CONFIG_ZSMALLOC is not set
+CONFIG_GENERIC_EARLY_IOREMAP=y
+# CONFIG_IDLE_PAGE_TRACKING is not set
+CONFIG_FRAME_VECTOR=y
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+# CONFIG_SECCOMP is not set
+CONFIG_SWIOTLB=y
+CONFIG_IOMMU_HELPER=y
+# CONFIG_PARAVIRT is not set
+# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set
+# CONFIG_XEN is not set
+
+#
+# Boot options
+#
+CONFIG_USE_OF=y
+CONFIG_ATAGS=y
+# CONFIG_DEPRECATED_PARAM_STRUCT is not set
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER=y
+# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set
+CONFIG_CMDLINE=""
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_AUTO_ZRELADDR=y
+# CONFIG_EFI is not set
+
+#
+# CPU Power Management
+#
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# CPU Idle
+#
+# CONFIG_CPU_IDLE is not set
+# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+# CONFIG_KERNEL_MODE_NEON is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_ELFCORE=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
+CONFIG_BINFMT_SCRIPT=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_COREDUMP=y
+
+#
+# Power management options
+#
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_PM_SLEEP=y
+# CONFIG_PM_AUTOSLEEP is not set
+# CONFIG_PM_WAKELOCKS is not set
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_APM_EMULATION is not set
+CONFIG_PM_CLK=y
+# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_CPU_PM=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARM_CPU_SUSPEND=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_DIAG is not set
+CONFIG_UNIX=y
+# CONFIG_UNIX_DIAG is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_ALGO=y
+CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+# CONFIG_IP_FIB_TRIE_STATS is not set
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
+# CONFIG_NET_IP_TUNNEL is not set
+CONFIG_IP_MROUTE=y
+# CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_NET_UDP_TUNNEL is not set
+# CONFIG_NET_FOU is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_INET_UDP_DIAG is not set
+# CONFIG_INET_DIAG_DESTROY is not set
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BIC=m
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+# CONFIG_TCP_CONG_HSTCP is not set
+# CONFIG_TCP_CONG_HYBLA is not set
+# CONFIG_TCP_CONG_VEGAS is not set
+# CONFIG_TCP_CONG_NV is not set
+# CONFIG_TCP_CONG_SCALABLE is not set
+# CONFIG_TCP_CONG_LP is not set
+# CONFIG_TCP_CONG_VENO is not set
+# CONFIG_TCP_CONG_YEAH is not set
+# CONFIG_TCP_CONG_ILLINOIS is not set
+# CONFIG_TCP_CONG_DCTCP is not set
+# CONFIG_TCP_CONG_CDG is not set
+# CONFIG_TCP_CONG_BBR is not set
+CONFIG_DEFAULT_CUBIC=y
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NET_PTP_CLASSIFY is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP is not set
+# CONFIG_BRIDGE is not set
+CONFIG_HAVE_NET_DSA=y
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+CONFIG_DNS_RESOLVER=y
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+# CONFIG_VSOCKETS is not set
+# CONFIG_NETLINK_DIAG is not set
+# CONFIG_MPLS is not set
+# CONFIG_HSR is not set
+# CONFIG_NET_SWITCHDEV is not set
+# CONFIG_NET_L3_MASTER_DEV is not set
+# CONFIG_NET_NCSI is not set
+# CONFIG_SOCK_CGROUP_DATA is not set
+# CONFIG_CGROUP_NET_PRIO is not set
+# CONFIG_CGROUP_NET_CLASSID is not set
+CONFIG_NET_RX_BUSY_POLL=y
+CONFIG_BQL=y
+# CONFIG_BPF_JIT is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_AF_KCM is not set
+# CONFIG_STREAM_PARSER is not set
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_CFG80211=m
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+CONFIG_CFG80211_DEFAULT_PS=y
+# CONFIG_CFG80211_INTERNAL_REGDB is not set
+CONFIG_CFG80211_CRDA_SUPPORT=y
+CONFIG_CFG80211_WEXT=y
+# CONFIG_LIB80211 is not set
+CONFIG_MAC80211=m
+CONFIG_MAC80211_HAS_RC=y
+CONFIG_MAC80211_RC_MINSTREL=y
+CONFIG_MAC80211_RC_MINSTREL_HT=y
+# CONFIG_MAC80211_RC_MINSTREL_VHT is not set
+CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y
+CONFIG_MAC80211_RC_DEFAULT="minstrel_ht"
+CONFIG_MAC80211_MESH=y
+# CONFIG_MAC80211_MESSAGE_TRACING is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+CONFIG_MAC80211_STA_HASH_MAX_SIZE=0
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+# CONFIG_LWTUNNEL is not set
+# CONFIG_DST_CACHE is not set
+# CONFIG_NET_DEVLINK is not set
+CONFIG_MAY_USE_DEVLINK=y
+CONFIG_HAVE_CBPF_JIT=y
+
+#
+# Device Drivers
+#
+CONFIG_ARM_AMBA=y
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set
+CONFIG_ALLOW_DEV_COREDUMP=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+CONFIG_REGMAP=y
+CONFIG_REGMAP_I2C=y
+CONFIG_REGMAP_SPI=y
+CONFIG_REGMAP_MMIO=y
+CONFIG_DMA_SHARED_BUFFER=y
+# CONFIG_FENCE_TRACE is not set
+
+#
+# Bus devices
+#
+# CONFIG_BRCMSTB_GISB_ARB is not set
+# CONFIG_VEXPRESS_CONFIG is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+CONFIG_MTD_OF_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
+# CONFIG_MTD_OOPS is not set
+# CONFIG_MTD_PARTITIONED_MASTER is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SST25L is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOCG3 is not set
+CONFIG_MTD_NAND_ECC=y
+# CONFIG_MTD_NAND_ECC_SMC is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_ECC_BCH is not set
+# CONFIG_MTD_SM_COMMON is not set
+# CONFIG_MTD_NAND_DENALI_DT is not set
+# CONFIG_MTD_NAND_GPIO is not set
+# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_DOCG4 is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_BRCMNAND is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_NAND_HISI504 is not set
+# CONFIG_MTD_NAND_MTK is not set
+CONFIG_MTD_SPI_NAND_GOKE=y
+# CONFIG_GOKE_NAND_ECC_STATUS_REPORT is not set
+# CONFIG_GOKE_NAND_FS_MAY_NO_YAFFS2 is not set
+CONFIG_MTD_SPI_NAND_FMC100=y
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR & LPDDR2 PCM memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_LPDDR2_NVM is not set
+CONFIG_MTD_SPI_NOR=y
+# CONFIG_MTD_MT81xx_NOR is not set
+# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
+# CONFIG_SPI_CADENCE_QUADSPI is not set
+CONFIG_SPI_GOKE_SFC=y
+# CONFIG_CLOSE_SPI_8PIN_4IO is not set
+CONFIG_GOKE_SPI_BLOCK_PROTECT=y
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_LIMIT=20
+# CONFIG_MTD_UBI_FASTMAP is not set
+# CONFIG_MTD_UBI_GLUEBI is not set
+# CONFIG_MTD_UBI_BLOCK is not set
+CONFIG_DTC=y
+CONFIG_OF=y
+# CONFIG_OF_UNITTEST is not set
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_NET=y
+CONFIG_OF_MDIO=y
+CONFIG_OF_RESERVED_MEM=y
+# CONFIG_OF_OVERLAY is not set
+CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_NULL_BLK is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_DRBD is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=65536
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MG_DISK is not set
+# CONFIG_BLK_DEV_RBD is not set
+# CONFIG_NVME_TARGET is not set
+
+#
+# Misc devices
+#
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_DUMMY_IRQ is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_APDS9802ALS is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_ISL29020 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_BH1770 is not set
+# CONFIG_SENSORS_APDS990X is not set
+# CONFIG_HMC6352 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_TI_DAC7512 is not set
+# CONFIG_USB_SWITCH_FSA9480 is not set
+# CONFIG_LATTICE_ECP3_CONFIG is not set
+# CONFIG_SRAM is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_EEPROM_93XX46 is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+# CONFIG_SENSORS_LIS3_SPI is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
+
+#
+# Altera FPGA firmware download module
+#
+# CONFIG_ALTERA_STAPL is not set
+
+#
+# Intel MIC Bus Driver
+#
+
+#
+# SCIF Bus Driver
+#
+
+#
+# VOP Bus Driver
+#
+
+#
+# Intel MIC Host Driver
+#
+
+#
+# Intel MIC Card Driver
+#
+
+#
+# SCIF Driver
+#
+
+#
+# Intel MIC Coprocessor State Management (COSM) Drivers
+#
+
+#
+# VOP Driver
+#
+# CONFIG_ECHO is not set
+# CONFIG_CXL_BASE is not set
+# CONFIG_CXL_AFU_DRIVER_OPS is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+CONFIG_SCSI_NETLINK=y
+# CONFIG_SCSI_MQ_DEFAULT is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+CONFIG_SCSI_FC_ATTRS=y
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_ISCSI_BOOT_SYSFS is not set
+# CONFIG_SCSI_UFSHCD is not set
+# CONFIG_LIBFC is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_TARGET_CORE is not set
+CONFIG_NETDEVICES=y
+CONFIG_NET_CORE=y
+# CONFIG_BONDING is not set
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_NET_TEAM is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_VXLAN is not set
+# CONFIG_MACSEC is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_TUN is not set
+# CONFIG_TUN_VNET_CROSS_LE is not set
+# CONFIG_VETH is not set
+# CONFIG_NLMON is not set
+
+#
+# CAIF transport drivers
+#
+
+#
+# Distributed Switch Architecture drivers
+#
+CONFIG_ETHERNET=y
+# CONFIG_ALTERA_TSE is not set
+# CONFIG_NET_VENDOR_AMAZON is not set
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_AURORA is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_DM9000 is not set
+# CONFIG_DNET is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_HISILICON is not set
+CONFIG_NET_VENDOR_GOKE=y
+CONFIG_GOKE_FEMAC=y
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+CONFIG_NET_VENDOR_MICROCHIP=y
+# CONFIG_ENC28J60 is not set
+# CONFIG_ENCX24J600 is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
+# CONFIG_ETHOC is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_PHYLIB=y
+CONFIG_SWPHY=y
+
+#
+# MDIO bus device drivers
+#
+# CONFIG_MDIO_BCM_UNIMAC is not set
+# CONFIG_MDIO_BITBANG is not set
+# CONFIG_MDIO_BUS_MUX_GPIO is not set
+# CONFIG_MDIO_BUS_MUX_MMIOREG is not set
+CONFIG_MDIO_GOKE_FEMAC=y
+# CONFIG_MDIO_HISI_FEMAC is not set
+
+#
+# MII PHY device drivers
+#
+# CONFIG_AMD_PHY is not set
+# CONFIG_AQUANTIA_PHY is not set
+# CONFIG_AT803X_PHY is not set
+# CONFIG_BCM7XXX_PHY is not set
+# CONFIG_BCM87XX_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_DP83848_PHY is not set
+# CONFIG_DP83867_PHY is not set
+CONFIG_FIXED_PHY=y
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_INTEL_XWAY_PHY is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_MICREL_PHY is not set
+# CONFIG_MICROCHIP_PHY is not set
+# CONFIG_MICROSEMI_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_TERANETICS_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_XILINX_GMII2RGMII is not set
+# CONFIG_MICREL_KS8995MA is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_USB_NET_DRIVERS is not set
+# CONFIG_WLAN is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_ISDN is not set
+# CONFIG_NVM is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+# CONFIG_INPUT_MATRIXKMAP is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ADP5588 is not set
+# CONFIG_KEYBOARD_ADP5589 is not set
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_QT1070 is not set
+# CONFIG_KEYBOARD_QT2160 is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_KEYBOARD_GPIO_POLLED is not set
+# CONFIG_KEYBOARD_TCA6416 is not set
+# CONFIG_KEYBOARD_TCA8418 is not set
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_LM8333 is not set
+# CONFIG_KEYBOARD_MAX7359 is not set
+# CONFIG_KEYBOARD_MCS is not set
+# CONFIG_KEYBOARD_MPR121 is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_SAMSUNG is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_OMAP4 is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_CAP11XX is not set
+# CONFIG_KEYBOARD_BCM is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_BYD=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_CYPRESS=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_SENTELIC is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+CONFIG_MOUSE_PS2_FOCALTECH=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_CYAPA is not set
+# CONFIG_MOUSE_ELAN_I2C is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+# CONFIG_MOUSE_SYNAPTICS_I2C is not set
+# CONFIG_MOUSE_SYNAPTICS_USB is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_AD714X is not set
+# CONFIG_INPUT_ATMEL_CAPTOUCH is not set
+# CONFIG_INPUT_BMA150 is not set
+# CONFIG_INPUT_E3X0_BUTTON is not set
+# CONFIG_INPUT_MMA8450 is not set
+# CONFIG_INPUT_MPU3050 is not set
+# CONFIG_INPUT_GP2A is not set
+# CONFIG_INPUT_GPIO_BEEPER is not set
+# CONFIG_INPUT_GPIO_TILT_POLLED is not set
+# CONFIG_INPUT_GPIO_DECODER is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_KXTJ9 is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
+CONFIG_INPUT_UINPUT=y
+# CONFIG_INPUT_PCF8574 is not set
+# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
+# CONFIG_INPUT_ADXL34X is not set
+# CONFIG_INPUT_CMA3000 is not set
+# CONFIG_INPUT_DRV260X_HAPTICS is not set
+# CONFIG_INPUT_DRV2665_HAPTICS is not set
+# CONFIG_INPUT_DRV2667_HAPTICS is not set
+# CONFIG_RMI4_CORE is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_AMBAKMI is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_ALTERA_PS2 is not set
+# CONFIG_SERIO_PS2MULT is not set
+# CONFIG_SERIO_ARC_PS2 is not set
+# CONFIG_SERIO_APBPS2 is not set
+# CONFIG_USERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_TTY=y
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_VT_CONSOLE_SLEEP=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVMEM=y
+# CONFIG_DEVKMEM is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_EARLYCON=y
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_AMBA_PL010 is not set
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set
+# CONFIG_SERIAL_MAX3100 is not set
+# CONFIG_SERIAL_MAX310X is not set
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_SCCNXP is not set
+# CONFIG_SERIAL_SC16IS7XX is not set
+# CONFIG_SERIAL_BCM63XX is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_IFX6X60 is not set
+# CONFIG_SERIAL_XILINX_PS_UART is not set
+# CONFIG_SERIAL_ARC is not set
+# CONFIG_SERIAL_FSL_LPUART is not set
+# CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set
+# CONFIG_SERIAL_ST_ASC is not set
+# CONFIG_SERIAL_STM32 is not set
+# CONFIG_HVC_DCC is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_XILLYBUS is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MUX=y
+
+#
+# Multiplexer I2C Chip support
+#
+# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set
+# CONFIG_I2C_MUX_GPIO is not set
+# CONFIG_I2C_MUX_PCA9541 is not set
+# CONFIG_I2C_MUX_PCA954x is not set
+# CONFIG_I2C_MUX_PINCTRL is not set
+# CONFIG_I2C_MUX_REG is not set
+# CONFIG_I2C_DEMUX_PINCTRL is not set
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_CBUS_GPIO is not set
+# CONFIG_I2C_DESIGNWARE_PLATFORM is not set
+# CONFIG_I2C_EMEV2 is not set
+# CONFIG_I2C_GPIO is not set
+CONFIG_I2C_GOKE=y
+# CONFIG_I2C_NOMADIK is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_PXA_PCI is not set
+# CONFIG_I2C_RK3X is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_DIOLAN_U2C is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_ROBOTFUZZ_OSIF is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+CONFIG_DMA_MSG_MIN_LEN=5
+CONFIG_DMA_MSG_MAX_LEN=4090
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_SLAVE is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_ALTERA is not set
+# CONFIG_SPI_AXI_SPI_ENGINE is not set
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_CADENCE is not set
+# CONFIG_SPI_DESIGNWARE is not set
+# CONFIG_SPI_GPIO is not set
+# CONFIG_SPI_FSL_SPI is not set
+# CONFIG_SPI_OC_TINY is not set
+CONFIG_SPI_PL022=y
+# CONFIG_SPI_PXA2XX_PCI is not set
+# CONFIG_SPI_ROCKCHIP is not set
+# CONFIG_SPI_SC18IS602 is not set
+# CONFIG_SPI_XCOMM is not set
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_ZYNQMP_GQSPI is not set
+
+#
+# SPI Protocol Masters
+#
+CONFIG_SPI_SPIDEV=y
+# CONFIG_SPI_LOOPBACK_TEST is not set
+# CONFIG_SPI_TLE62X0 is not set
+# CONFIG_SPMI is not set
+# CONFIG_HSI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+# CONFIG_PTP_1588_CLOCK is not set
+
+#
+# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
+#
+CONFIG_PINCTRL=y
+
+#
+# Pin controllers
+#
+CONFIG_PINMUX=y
+CONFIG_PINCONF=y
+CONFIG_GENERIC_PINCONF=y
+# CONFIG_DEBUG_PINCTRL is not set
+# CONFIG_PINCTRL_AMD is not set
+CONFIG_PINCTRL_SINGLE=y
+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
+CONFIG_GPIOLIB=y
+CONFIG_OF_GPIO=y
+CONFIG_GPIOLIB_IRQCHIP=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO drivers
+#
+# CONFIG_GPIO_74XX_MMIO is not set
+# CONFIG_GPIO_ALTERA is not set
+# CONFIG_GPIO_DWAPB is not set
+# CONFIG_GPIO_EM is not set
+# CONFIG_GPIO_GENERIC_PLATFORM is not set
+# CONFIG_GPIO_GRGPIO is not set
+# CONFIG_GPIO_MOCKUP is not set
+# CONFIG_GPIO_MPC8XXX is not set
+CONFIG_GPIO_PL061=y
+# CONFIG_GPIO_SYSCON is not set
+# CONFIG_GPIO_XILINX is not set
+# CONFIG_GPIO_ZEVIO is not set
+# CONFIG_GPIO_ZX is not set
+
+#
+# I2C GPIO expanders
+#
+# CONFIG_GPIO_ADP5588 is not set
+# CONFIG_GPIO_ADNP is not set
+# CONFIG_GPIO_MAX7300 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_SX150X is not set
+# CONFIG_GPIO_TPIC2810 is not set
+# CONFIG_GPIO_TS4900 is not set
+
+#
+# MFD GPIO expanders
+#
+# CONFIG_HTC_EGPIO is not set
+
+#
+# SPI GPIO expanders
+#
+# CONFIG_GPIO_74X164 is not set
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MC33880 is not set
+# CONFIG_GPIO_PISOSR is not set
+
+#
+# SPI or I2C GPIO expanders
+#
+# CONFIG_GPIO_MCP23S08 is not set
+
+#
+# USB GPIO expanders
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_AVS is not set
+CONFIG_POWER_RESET=y
+# CONFIG_POWER_RESET_BRCMKONA is not set
+# CONFIG_POWER_RESET_BRCMSTB is not set
+CONFIG_POWER_RESET_GOKE=y
+# CONFIG_POWER_RESET_GPIO is not set
+# CONFIG_POWER_RESET_GPIO_RESTART is not set
+# CONFIG_POWER_RESET_LTC2952 is not set
+# CONFIG_POWER_RESET_RESTART is not set
+# CONFIG_POWER_RESET_VERSATILE is not set
+# CONFIG_POWER_RESET_SYSCON is not set
+# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set
+# CONFIG_SYSCON_REBOOT_MODE is not set
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_TEST_POWER is not set
+# CONFIG_BATTERY_DS2780 is not set
+# CONFIG_BATTERY_DS2781 is not set
+# CONFIG_BATTERY_DS2782 is not set
+# CONFIG_BATTERY_SBS is not set
+# CONFIG_BATTERY_BQ27XXX is not set
+# CONFIG_BATTERY_MAX17040 is not set
+# CONFIG_BATTERY_MAX17042 is not set
+# CONFIG_CHARGER_MAX8903 is not set
+# CONFIG_CHARGER_LP8727 is not set
+# CONFIG_CHARGER_GPIO is not set
+# CONFIG_CHARGER_BQ2415X is not set
+# CONFIG_CHARGER_BQ24190 is not set
+# CONFIG_CHARGER_BQ24257 is not set
+# CONFIG_CHARGER_BQ24735 is not set
+# CONFIG_CHARGER_BQ25890 is not set
+# CONFIG_CHARGER_SMB347 is not set
+# CONFIG_BATTERY_GAUGE_LTC2941 is not set
+# CONFIG_CHARGER_RT9455 is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+CONFIG_MFD_CORE=y
+# CONFIG_MFD_ACT8945A is not set
+# CONFIG_MFD_AS3711 is not set
+# CONFIG_MFD_AS3722 is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_AAT2870_CORE is not set
+# CONFIG_MFD_ATMEL_FLEXCOM is not set
+# CONFIG_MFD_ATMEL_HLCDC is not set
+# CONFIG_MFD_BCM590XX is not set
+# CONFIG_MFD_AXP20X_I2C is not set
+# CONFIG_MFD_CROS_EC is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_DA9052_SPI is not set
+# CONFIG_MFD_DA9052_I2C is not set
+# CONFIG_MFD_DA9055 is not set
+# CONFIG_MFD_DA9062 is not set
+# CONFIG_MFD_DA9063 is not set
+# CONFIG_MFD_DA9150 is not set
+# CONFIG_MFD_DLN2 is not set
+# CONFIG_MFD_EXYNOS_LPASS is not set
+# CONFIG_MFD_MC13XXX_SPI is not set
+# CONFIG_MFD_MC13XXX_I2C is not set
+# CONFIG_MFD_HI6421_PMIC is not set
+CONFIG_MFD_GOKE_FMC=y
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_HTC_I2CPLD is not set
+# CONFIG_INTEL_SOC_PMIC is not set
+# CONFIG_MFD_KEMPLD is not set
+# CONFIG_MFD_88PM800 is not set
+# CONFIG_MFD_88PM805 is not set
+# CONFIG_MFD_88PM860X is not set
+# CONFIG_MFD_MAX14577 is not set
+# CONFIG_MFD_MAX77620 is not set
+# CONFIG_MFD_MAX77686 is not set
+# CONFIG_MFD_MAX77693 is not set
+# CONFIG_MFD_MAX77843 is not set
+# CONFIG_MFD_MAX8907 is not set
+# CONFIG_MFD_MAX8925 is not set
+# CONFIG_MFD_MAX8997 is not set
+# CONFIG_MFD_MAX8998 is not set
+# CONFIG_MFD_MT6397 is not set
+# CONFIG_MFD_MENF21BMC is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_MFD_VIPERBOARD is not set
+# CONFIG_MFD_RETU is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_PM8921_CORE is not set
+# CONFIG_MFD_RT5033 is not set
+# CONFIG_MFD_RTSX_USB is not set
+# CONFIG_MFD_RC5T583 is not set
+# CONFIG_MFD_RK808 is not set
+# CONFIG_MFD_RN5T618 is not set
+# CONFIG_MFD_SEC_CORE is not set
+# CONFIG_MFD_SI476X_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_SKY81452 is not set
+# CONFIG_MFD_SMSC is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_MFD_STMPE is not set
+CONFIG_MFD_SYSCON=y
+# CONFIG_MFD_TI_AM335X_TSCADC is not set
+# CONFIG_MFD_LP3943 is not set
+# CONFIG_MFD_LP8788 is not set
+# CONFIG_MFD_PALMAS is not set
+# CONFIG_TPS6105X is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TPS6507X is not set
+# CONFIG_MFD_TPS65086 is not set
+# CONFIG_MFD_TPS65090 is not set
+# CONFIG_MFD_TPS65217 is not set
+# CONFIG_MFD_TI_LP873X is not set
+# CONFIG_MFD_TPS65218 is not set
+# CONFIG_MFD_TPS6586X is not set
+# CONFIG_MFD_TPS65910 is not set
+# CONFIG_MFD_TPS65912_I2C is not set
+# CONFIG_MFD_TPS65912_SPI is not set
+# CONFIG_MFD_TPS80031 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_TWL6040_CORE is not set
+# CONFIG_MFD_WL1273_CORE is not set
+# CONFIG_MFD_LM3533 is not set
+# CONFIG_MFD_TC3589X is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_MFD_ARIZONA_I2C is not set
+# CONFIG_MFD_ARIZONA_SPI is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X_I2C is not set
+# CONFIG_MFD_WM831X_SPI is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8994 is not set
+# CONFIG_REGULATOR is not set
+CONFIG_MEDIA_SUPPORT=y
+
+#
+# Multimedia core support
+#
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set
+# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set
+# CONFIG_MEDIA_RADIO_SUPPORT is not set
+# CONFIG_MEDIA_SDR_SUPPORT is not set
+# CONFIG_MEDIA_RC_SUPPORT is not set
+# CONFIG_MEDIA_CONTROLLER is not set
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L2=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEOBUF2_CORE=y
+CONFIG_VIDEOBUF2_MEMOPS=y
+CONFIG_VIDEOBUF2_VMALLOC=y
+# CONFIG_TTPCI_EEPROM is not set
+
+#
+# Media drivers
+#
+CONFIG_MEDIA_USB_SUPPORT=y
+
+#
+# Webcam devices
+#
+CONFIG_USB_VIDEO_CLASS=y
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+CONFIG_USB_GSPCA=m
+# CONFIG_USB_M5602 is not set
+# CONFIG_USB_STV06XX is not set
+# CONFIG_USB_GL860 is not set
+# CONFIG_USB_GSPCA_BENQ is not set
+# CONFIG_USB_GSPCA_CONEX is not set
+# CONFIG_USB_GSPCA_CPIA1 is not set
+# CONFIG_USB_GSPCA_DTCS033 is not set
+# CONFIG_USB_GSPCA_ETOMS is not set
+# CONFIG_USB_GSPCA_FINEPIX is not set
+# CONFIG_USB_GSPCA_JEILINJ is not set
+# CONFIG_USB_GSPCA_JL2005BCD is not set
+# CONFIG_USB_GSPCA_KINECT is not set
+# CONFIG_USB_GSPCA_KONICA is not set
+# CONFIG_USB_GSPCA_MARS is not set
+# CONFIG_USB_GSPCA_MR97310A is not set
+# CONFIG_USB_GSPCA_NW80X is not set
+# CONFIG_USB_GSPCA_OV519 is not set
+# CONFIG_USB_GSPCA_OV534 is not set
+# CONFIG_USB_GSPCA_OV534_9 is not set
+# CONFIG_USB_GSPCA_PAC207 is not set
+# CONFIG_USB_GSPCA_PAC7302 is not set
+# CONFIG_USB_GSPCA_PAC7311 is not set
+# CONFIG_USB_GSPCA_SE401 is not set
+# CONFIG_USB_GSPCA_SN9C2028 is not set
+# CONFIG_USB_GSPCA_SN9C20X is not set
+# CONFIG_USB_GSPCA_SONIXB is not set
+# CONFIG_USB_GSPCA_SONIXJ is not set
+# CONFIG_USB_GSPCA_SPCA500 is not set
+# CONFIG_USB_GSPCA_SPCA501 is not set
+# CONFIG_USB_GSPCA_SPCA505 is not set
+# CONFIG_USB_GSPCA_SPCA506 is not set
+# CONFIG_USB_GSPCA_SPCA508 is not set
+# CONFIG_USB_GSPCA_SPCA561 is not set
+# CONFIG_USB_GSPCA_SPCA1528 is not set
+# CONFIG_USB_GSPCA_SQ905 is not set
+# CONFIG_USB_GSPCA_SQ905C is not set
+# CONFIG_USB_GSPCA_SQ930X is not set
+# CONFIG_USB_GSPCA_STK014 is not set
+# CONFIG_USB_GSPCA_STK1135 is not set
+# CONFIG_USB_GSPCA_STV0680 is not set
+# CONFIG_USB_GSPCA_SUNPLUS is not set
+# CONFIG_USB_GSPCA_T613 is not set
+# CONFIG_USB_GSPCA_TOPRO is not set
+# CONFIG_USB_GSPCA_TOUPTEK is not set
+# CONFIG_USB_GSPCA_TV8532 is not set
+# CONFIG_USB_GSPCA_VC032X is not set
+# CONFIG_USB_GSPCA_VICAM is not set
+# CONFIG_USB_GSPCA_XIRLINK_CIT is not set
+# CONFIG_USB_GSPCA_ZC3XX is not set
+# CONFIG_USB_PWC is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_USB_ZR364XX is not set
+# CONFIG_USB_STKWEBCAM is not set
+# CONFIG_USB_S2255 is not set
+
+#
+# Webcam, TV (analog/digital) USB devices
+#
+# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_V4L_PLATFORM_DRIVERS is not set
+# CONFIG_V4L_MEM2MEM_DRIVERS is not set
+# CONFIG_V4L_TEST_DRIVERS is not set
+
+#
+# Supported MMC/SDIO adapters
+#
+# CONFIG_CYPRESS_FIRMWARE is not set
+
+#
+# Media ancillary drivers (tuners, sensors, i2c, spi, frontends)
+#
+CONFIG_MEDIA_SUBDRV_AUTOSELECT=y
+
+#
+# Audio decoders, processors and mixers
+#
+
+#
+# RDS decoders
+#
+
+#
+# Video decoders
+#
+
+#
+# Video and audio decoders
+#
+
+#
+# Video encoders
+#
+
+#
+# Camera sensor devices
+#
+
+#
+# Flash devices
+#
+
+#
+# Video improvement chips
+#
+
+#
+# Audio/Video compression chips
+#
+
+#
+# Miscellaneous helper chips
+#
+
+#
+# Sensors used on soc_camera driver
+#
+
+#
+# Tools to develop new frontends
+#
+# CONFIG_DVB_DUMMY_FE is not set
+
+#
+# Graphics support
+#
+# CONFIG_IMX_IPUV3_CORE is not set
+# CONFIG_DRM is not set
+
+#
+# ACP (Audio CoProcessor) Configuration
+#
+
+#
+# Frame buffer Devices
+#
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB_CMDLINE=y
+CONFIG_FB_NOTIFY=y
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_ARMCLCD is not set
+# CONFIG_FB_OPENCORES is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_SMSCUFX is not set
+# CONFIG_FB_UDL is not set
+# CONFIG_FB_IBM_GXT4500 is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_FB_AUO_K190X is not set
+# CONFIG_FB_SIMPLE is not set
+# CONFIG_FB_SSD1307 is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+# CONFIG_LOGO is not set
+# CONFIG_SOUND is not set
+
+#
+# HID support
+#
+CONFIG_HID=y
+# CONFIG_HID_BATTERY_STRENGTH is not set
+# CONFIG_HIDRAW is not set
+# CONFIG_UHID is not set
+CONFIG_HID_GENERIC=y
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_ACRUX is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_APPLEIR is not set
+# CONFIG_HID_AUREAL is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_BETOP_FF is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_CMEDIA is not set
+# CONFIG_HID_CP2112 is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EMS_FF is not set
+# CONFIG_HID_ELECOM is not set
+# CONFIG_HID_ELO is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_GEMBIRD is not set
+# CONFIG_HID_GFRM is not set
+# CONFIG_HID_HOLTEK is not set
+# CONFIG_HID_KEYTOUCH is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_UCLOGIC is not set
+# CONFIG_HID_WALTOP is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_ICADE is not set
+# CONFIG_HID_TWINHAN is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LCPOWER is not set
+# CONFIG_HID_LENOVO is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MAGICMOUSE is not set
+CONFIG_HID_MICROSOFT=y
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_MULTITOUCH is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_ORTEK is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PENMOUNT is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_PICOLCD is not set
+# CONFIG_HID_PLANTRONICS is not set
+# CONFIG_HID_PRIMAX is not set
+# CONFIG_HID_ROCCAT is not set
+# CONFIG_HID_SAITEK is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SPEEDLINK is not set
+# CONFIG_HID_STEELSERIES is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_RMI is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TIVO is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_WACOM is not set
+# CONFIG_HID_XINMO is not set
+# CONFIG_HID_ZEROPLUS is not set
+# CONFIG_HID_ZYDACRON is not set
+# CONFIG_HID_SENSOR_HUB is not set
+# CONFIG_HID_ALPS is not set
+
+#
+# USB HID support
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# I2C HID support
+#
+# CONFIG_I2C_HID is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_COMMON=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB=y
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEFAULT_PERSIST=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_PLATFORM=y
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+# CONFIG_USB_FOTG210_HCD is not set
+# CONFIG_USB_MAX3421_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HCD_TEST_MODE is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_REALTEK is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_STORAGE_ENE_UB6250 is not set
+# CONFIG_USB_UAS is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USBIP_CORE is not set
+# CONFIG_USB_MUSB_HDRC is not set
+CONFIG_USB_DWC3=y
+# CONFIG_USB_DWC3_HOST is not set
+# CONFIG_USB_DWC3_GADGET is not set
+CONFIG_USB_DWC3_DUAL_ROLE=y
+
+#
+# Platform Glue Driver Support
+#
+CONFIG_USB_DWC3_OF_SIMPLE=y
+# CONFIG_USB_DWC2 is not set
+# CONFIG_USB_CHIPIDEA is not set
+# CONFIG_USB_ISP1760 is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_EHSET_TEST_FIXTURE is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_YUREX is not set
+# CONFIG_USB_EZUSB_FX2 is not set
+# CONFIG_USB_HSIC_USB3503 is not set
+# CONFIG_USB_HSIC_USB4604 is not set
+# CONFIG_USB_LINK_LAYER_TEST is not set
+
+#
+# USB Physical Layer drivers
+#
+# CONFIG_USB_PHY is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_USB_ISP1301 is not set
+# CONFIG_USB_ULPI is not set
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2
+
+#
+# USB Peripheral Controller
+#
+# CONFIG_USB_FUSB300 is not set
+# CONFIG_USB_FOTG210_UDC is not set
+# CONFIG_USB_GR_UDC is not set
+# CONFIG_USB_R8A66597 is not set
+# CONFIG_USB_PXA27X is not set
+# CONFIG_USB_MV_UDC is not set
+# CONFIG_USB_MV_U3D is not set
+# CONFIG_USB_M66592 is not set
+# CONFIG_USB_BDC_UDC is not set
+# CONFIG_USB_NET2272 is not set
+# CONFIG_USB_GADGET_XILINX is not set
+# CONFIG_USB_DUMMY_HCD is not set
+CONFIG_USB_LIBCOMPOSITE=m
+CONFIG_USB_F_ACM=m
+CONFIG_USB_U_SERIAL=m
+CONFIG_USB_U_ETHER=m
+CONFIG_USB_F_ECM=m
+CONFIG_USB_F_RNDIS=m
+CONFIG_USB_F_MASS_STORAGE=m
+CONFIG_USB_CONFIGFS=m
+# CONFIG_USB_CONFIGFS_SERIAL is not set
+CONFIG_USB_CONFIGFS_ACM=y
+# CONFIG_USB_CONFIGFS_OBEX is not set
+# CONFIG_USB_CONFIGFS_NCM is not set
+CONFIG_USB_CONFIGFS_ECM=y
+# CONFIG_USB_CONFIGFS_ECM_SUBSET is not set
+CONFIG_USB_CONFIGFS_RNDIS=y
+# CONFIG_USB_CONFIGFS_EEM is not set
+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
+# CONFIG_USB_CONFIGFS_F_LB_SS is not set
+# CONFIG_USB_CONFIGFS_F_FS is not set
+# CONFIG_USB_CONFIGFS_F_HID is not set
+# CONFIG_USB_CONFIGFS_F_UVC is not set
+# CONFIG_USB_CONFIGFS_F_PRINTER is not set
+# CONFIG_USB_ULPI_BUS is not set
+# CONFIG_UWB is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_PWRSEQ_EMMC=y
+CONFIG_PWRSEQ_SIMPLE=y
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_MINORS=8
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_ARMMMCI is not set
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+# CONFIG_MMC_SDHCI_OF_ARASAN is not set
+# CONFIG_MMC_SDHCI_OF_AT91 is not set
+CONFIG_MMC_SDHCI_GOKE=y
+# CONFIG_MMC_SDHCI_F_SDH30 is not set
+# CONFIG_MMC_SPI is not set
+# CONFIG_MMC_DW is not set
+# CONFIG_MMC_VUB300 is not set
+# CONFIG_MMC_USHC is not set
+# CONFIG_MMC_USDHI6ROL0 is not set
+# CONFIG_MMC_MTK is not set
+# CONFIG_MMC_CQ_HCI is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_EDAC_ATOMIC_SCRUB=y
+CONFIG_EDAC_SUPPORT=y
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+CONFIG_RTC_SYSTOHC=y
+CONFIG_RTC_SYSTOHC_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_ABB5ZES3 is not set
+# CONFIG_RTC_DRV_ABX80X is not set
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_HYM8563 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_ISL12022 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8523 is not set
+# CONFIG_RTC_DRV_PCF85063 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_BQ32K is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8010 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+# CONFIG_RTC_DRV_EM3027 is not set
+# CONFIG_RTC_DRV_RV8803 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T93 is not set
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1302 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1343 is not set
+# CONFIG_RTC_DRV_DS1347 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6916 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RX4581 is not set
+# CONFIG_RTC_DRV_RX6110 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
+# CONFIG_RTC_DRV_MCP795 is not set
+CONFIG_RTC_I2C_AND_SPI=y
+
+#
+# SPI and I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS3232 is not set
+# CONFIG_RTC_DRV_PCF2127 is not set
+# CONFIG_RTC_DRV_RV3029C2 is not set
+
+#
+# Platform RTC drivers
+#
+CONFIG_RTC_DRV_GOKE=y
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1685_FAMILY is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_DS2404 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+# CONFIG_RTC_DRV_ZYNQMP is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_PL030 is not set
+# CONFIG_RTC_DRV_PL031 is not set
+# CONFIG_RTC_DRV_SNVS is not set
+
+#
+# HID Sensor RTC drivers
+#
+# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set
+# CONFIG_DMADEVICES is not set
+
+#
+# DMABUF options
+#
+# CONFIG_SYNC_FILE is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+# CONFIG_VIRT_DRIVERS is not set
+
+#
+# Virtio drivers
+#
+# CONFIG_VIRTIO_MMIO is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_STAGING is not set
+# CONFIG_GOLDFISH is not set
+# CONFIG_CHROME_PLATFORMS is not set
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_COMMON_CLK=y
+
+#
+# Common Clock Framework
+#
+# CONFIG_COMMON_CLK_SI5351 is not set
+# CONFIG_COMMON_CLK_SI514 is not set
+# CONFIG_COMMON_CLK_SI570 is not set
+# CONFIG_COMMON_CLK_CDCE706 is not set
+# CONFIG_COMMON_CLK_CDCE925 is not set
+# CONFIG_COMMON_CLK_CS2000_CP is not set
+# CONFIG_CLK_QORIQ is not set
+# CONFIG_COMMON_CLK_NXP is not set
+# CONFIG_COMMON_CLK_PXA is not set
+# CONFIG_COMMON_CLK_PIC32 is not set
+CONFIG_COMMON_CLK_GK7205V200=y
+CONFIG_RESET_GOKE=y
+
+#
+# Hardware Spinlock drivers
+#
+
+#
+# Clock Source drivers
+#
+CONFIG_CLKSRC_OF=y
+CONFIG_CLKSRC_PROBE=y
+CONFIG_CLKSRC_MMIO=y
+CONFIG_ARM_ARCH_TIMER=y
+CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y
+# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS is not set
+CONFIG_ARM_TIMER_SP804=y
+# CONFIG_ATMEL_PIT is not set
+# CONFIG_SH_TIMER_CMT is not set
+# CONFIG_SH_TIMER_MTU2 is not set
+# CONFIG_SH_TIMER_TMU is not set
+# CONFIG_EM_TIMER_STI is not set
+# CONFIG_MAILBOX is not set
+# CONFIG_IOMMU_SUPPORT is not set
+
+#
+# Remoteproc drivers
+#
+# CONFIG_STE_MODEM_RPROC is not set
+
+#
+# Rpmsg drivers
+#
+
+#
+# SOC (System On Chip) specific Drivers
+#
+
+#
+# Broadcom SoC drivers
+#
+# CONFIG_SOC_BRCMSTB is not set
+# CONFIG_SUNXI_SRAM is not set
+# CONFIG_SOC_TI is not set
+# CONFIG_PM_DEVFREQ is not set
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
+# CONFIG_IIO is not set
+# CONFIG_PWM is not set
+CONFIG_IRQCHIP=y
+CONFIG_ARM_GIC=y
+CONFIG_ARM_GIC_MAX_NR=1
+# CONFIG_IPACK_BUS is not set
+CONFIG_RESET_CONTROLLER=y
+# CONFIG_RESET_ATH79 is not set
+# CONFIG_RESET_BERLIN is not set
+# CONFIG_RESET_LPC18XX is not set
+# CONFIG_RESET_MESON is not set
+# CONFIG_RESET_PISTACHIO is not set
+# CONFIG_RESET_SOCFPGA is not set
+# CONFIG_RESET_STM32 is not set
+# CONFIG_RESET_SUNXI is not set
+# CONFIG_TI_SYSCON_RESET is not set
+# CONFIG_RESET_ZYNQ is not set
+# CONFIG_FMC is not set
+
+#
+# PHY Subsystem
+#
+CONFIG_GENERIC_PHY=y
+# CONFIG_PHY_PXA_28NM_HSIC is not set
+# CONFIG_PHY_PXA_28NM_USB2 is not set
+# CONFIG_BCM_KONA_USB2_PHY is not set
+CONFIG_PHY_GOKE_USBP2=y
+# CONFIG_USB_MODE_OPTION is not set
+# CONFIG_POWERCAP is not set
+# CONFIG_MCB is not set
+
+#
+# Performance monitor support
+#
+# CONFIG_RAS is not set
+
+#
+# Android
+#
+# CONFIG_ANDROID is not set
+# CONFIG_NVMEM is not set
+# CONFIG_STM is not set
+# CONFIG_INTEL_TH is not set
+
+#
+# FPGA Configuration Support
+#
+# CONFIG_FPGA is not set
+
+#
+# goke driver support
+#
+
+#
+# Firmware Drivers
+#
+# CONFIG_FIRMWARE_MEMMAP is not set
+# CONFIG_FW_CFG_SYSFS is not set
+CONFIG_HAVE_ARM_SMCCC=y
+
+#
+# File systems
+#
+CONFIG_DCACHE_WORD_ACCESS=y
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_USE_FOR_EXT2=y
+# CONFIG_EXT4_FS_POSIX_ACL is not set
+# CONFIG_EXT4_FS_SECURITY is not set
+# CONFIG_EXT4_ENCRYPTION is not set
+# CONFIG_EXT4_DEBUG is not set
+CONFIG_JBD2=y
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+# CONFIG_F2FS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_EXPORTFS=y
+# CONFIG_EXPORTFS_BLOCK_OPS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_MANDATORY_FILE_LOCKING=y
+# CONFIG_FS_ENCRYPTION is not set
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_QUOTACTL is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+# CONFIG_OVERLAY_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_FAT_DEFAULT_UTF8 is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_PROC_CHILDREN is not set
+CONFIG_KERNFS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_TMPFS_XATTR=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=y
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ORANGEFS_FS is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_YAFFS_FS=y
+CONFIG_YAFFS_YAFFS1=y
+# CONFIG_YAFFS_9BYTE_TAGS is not set
+# CONFIG_YAFFS_DOES_ECC is not set
+CONFIG_YAFFS_YAFFS2=y
+CONFIG_YAFFS_AUTO_YAFFS2=y
+# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set
+# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
+# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set
+# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set
+# CONFIG_YAFFS_DISABLE_BACKGROUND is not set
+# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set
+CONFIG_YAFFS_XATTR=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+# CONFIG_JFFS2_LZMA is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_UBIFS_FS=y
+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_ATIME_SUPPORT is not set
+# CONFIG_LOGFS is not set
+CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX6FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_PSTORE is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V2=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+# CONFIG_NFS_SWAP is not set
+# CONFIG_NFS_V4_1 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFS_USE_LEGACY_DNS is not set
+CONFIG_NFS_USE_KERNEL_DNS=y
+# CONFIG_NFSD is not set
+CONFIG_GRACE_PERIOD=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_ACL_SUPPORT=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_DEBUG is not set
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=y
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+# CONFIG_NLS_MAC_ROMAN is not set
+# CONFIG_NLS_MAC_CELTIC is not set
+# CONFIG_NLS_MAC_CENTEURO is not set
+# CONFIG_NLS_MAC_CROATIAN is not set
+# CONFIG_NLS_MAC_CYRILLIC is not set
+# CONFIG_NLS_MAC_GAELIC is not set
+# CONFIG_NLS_MAC_GREEK is not set
+# CONFIG_NLS_MAC_ICELAND is not set
+# CONFIG_NLS_MAC_INUIT is not set
+# CONFIG_NLS_MAC_ROMANIAN is not set
+# CONFIG_NLS_MAC_TURKISH is not set
+CONFIG_NLS_UTF8=y
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+
+#
+# printk and dmesg options
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
+# CONFIG_BOOT_PRINTK_DELAY is not set
+
+#
+# Compile-time checks and compiler options
+#
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_READABLE_ASM is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_PAGE_OWNER is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_SECTION_MISMATCH_WARN_ONLY=y
+CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_DEBUG_KERNEL=y
+
+#
+# Memory Debugging
+#
+# CONFIG_PAGE_EXTENSION is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_PAGE_POISONING is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_SHIRQ is not set
+
+#
+# Debug Lockups and Hangs
+#
+# CONFIG_LOCKUP_DETECTOR is not set
+# CONFIG_DETECT_HUNG_TASK is not set
+# CONFIG_WQ_WATCHDOG is not set
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+CONFIG_PANIC_TIMEOUT=0
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHED_INFO is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_SCHED_STACK_END_CHECK is not set
+# CONFIG_DEBUG_TIMEKEEPING is not set
+# CONFIG_TIMER_STATS is not set
+
+#
+# Lock Debugging (spinlocks, mutexes, etc...)
+#
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_ATOMIC_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_LOCK_TORTURE_TEST is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_PI_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+
+#
+# RCU Debugging
+#
+# CONFIG_PROVE_RCU is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_TORTURE_TEST is not set
+# CONFIG_RCU_PERF_TEST is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_TRACE is not set
+# CONFIG_RCU_EQS_DEBUG is not set
+# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_NOTIFIER_ERROR_INJECTION is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+
+#
+# Runtime Testing
+#
+# CONFIG_TEST_LIST_SORT is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_RBTREE_TEST is not set
+# CONFIG_INTERVAL_TREE_TEST is not set
+# CONFIG_PERCPU_TEST is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_TEST_HEXDUMP is not set
+# CONFIG_TEST_STRING_HELPERS is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_TEST_PRINTF is not set
+# CONFIG_TEST_BITMAP is not set
+# CONFIG_TEST_UUID is not set
+# CONFIG_TEST_RHASHTABLE is not set
+# CONFIG_TEST_HASH is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_TEST_LKM is not set
+# CONFIG_TEST_USER_COPY is not set
+# CONFIG_TEST_BPF is not set
+# CONFIG_TEST_FIRMWARE is not set
+# CONFIG_TEST_UDELAY is not set
+# CONFIG_MEMTEST is not set
+# CONFIG_TEST_STATIC_KEYS is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set
+# CONFIG_UBSAN is not set
+CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
+CONFIG_STRICT_DEVMEM=y
+# CONFIG_IO_STRICT_DEVMEM is not set
+# CONFIG_ARM_PTDUMP is not set
+# CONFIG_ARM_UNWIND is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_LL is not set
+CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
+# CONFIG_DEBUG_UART_8250 is not set
+CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
+# CONFIG_PID_IN_CONTEXTIDR is not set
+# CONFIG_DEBUG_SET_MODULE_RONX is not set
+# CONFIG_CORESIGHT is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_PERSISTENT_KEYRINGS is not set
+# CONFIG_ENCRYPTED_KEYS is not set
+# CONFIG_KEY_DH_OPERATIONS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y
+CONFIG_HAVE_ARCH_HARDENED_USERCOPY=y
+# CONFIG_HARDENED_USERCOPY is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_RNG_DEFAULT=m
+CONFIG_CRYPTO_AKCIPHER2=y
+CONFIG_CRYPTO_KPP2=y
+# CONFIG_CRYPTO_RSA is not set
+# CONFIG_CRYPTO_DH is not set
+# CONFIG_CRYPTO_ECDH is not set
+CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_USER is not set
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_NULL2=y
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_MCRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+# CONFIG_CRYPTO_CHACHA20POLY1305 is not set
+CONFIG_CRYPTO_SEQIV=m
+CONFIG_CRYPTO_ECHAINIV=m
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+CONFIG_CRYPTO_CTR=m
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+# CONFIG_CRYPTO_KEYWRAP is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_CMAC is not set
+CONFIG_CRYPTO_HMAC=m
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_CRC32 is not set
+CONFIG_CRYPTO_CRCT10DIF=y
+CONFIG_CRYPTO_GHASH=m
+# CONFIG_CRYPTO_POLY1305 is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=y
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_SHA3 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_CHACHA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_LZO=y
+# CONFIG_CRYPTO_842 is not set
+# CONFIG_CRYPTO_LZ4 is not set
+# CONFIG_CRYPTO_LZ4HC is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_DRBG_MENU=m
+CONFIG_CRYPTO_DRBG_HMAC=y
+# CONFIG_CRYPTO_DRBG_HASH is not set
+# CONFIG_CRYPTO_DRBG_CTR is not set
+CONFIG_CRYPTO_DRBG=m
+CONFIG_CRYPTO_JITTERENTROPY=m
+# CONFIG_CRYPTO_USER_API_HASH is not set
+# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
+# CONFIG_CRYPTO_USER_API_RNG is not set
+# CONFIG_CRYPTO_USER_API_AEAD is not set
+# CONFIG_CRYPTO_HW is not set
+# CONFIG_ASYMMETRIC_KEY_TYPE is not set
+
+#
+# Certificates for signature checking
+#
+# CONFIG_ARM_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_HAVE_ARCH_BITREVERSE=y
+CONFIG_RATIONAL=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_NET_UTILS=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IO=y
+CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=y
+# CONFIG_CRC8 is not set
+# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set
+# CONFIG_RANDOM32_SELFTEST is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_LZ4_DECOMPRESS=y
+CONFIG_XZ_DEC=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_BCJ=y
+# CONFIG_XZ_DEC_TEST is not set
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_LZ4=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_ASSOCIATIVE_ARRAY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_HAS_DMA=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
+# CONFIG_IRQ_POLL is not set
+CONFIG_LIBFDT=y
+CONFIG_OID_REGISTRY=y
+# CONFIG_SG_SPLIT is not set
+CONFIG_SG_POOL=y
+CONFIG_ARCH_HAS_SG_CHAIN=y
+CONFIG_SBITMAP=y
+# CONFIG_VIRTUALIZATION is not set
diff -urN linux-4.9.37/arch/arm/configs/gk7205v200_full_defconfig linux-4.9.y/arch/arm/configs/gk7205v200_full_defconfig
--- linux-4.9.37/arch/arm/configs/gk7205v200_full_defconfig 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/arch/arm/configs/gk7205v200_full_defconfig 2021-06-07 13:01:32.000000000 +0300
@@ -0,0 +1,2981 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/arm 4.9.37 Kernel Configuration
+#
+CONFIG_ARM=y
+CONFIG_ARM_HAS_SG_CHAIN=y
+CONFIG_MIGHT_HAVE_PCI=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_ARM_PATCH_PHYS_VIRT=y
+CONFIG_GENERIC_BUG=y
+CONFIG_PGTABLE_LEVELS=2
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_IRQ_WORK=y
+CONFIG_BUILDTIME_EXTABLE_SORT=y
+
+#
+# General setup
+#
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+# CONFIG_COMPILE_TEST is not set
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_HAVE_KERNEL_LZ4=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_XZ is not set
+# CONFIG_KERNEL_LZO is not set
+# CONFIG_KERNEL_LZ4 is not set
+CONFIG_DEFAULT_HOSTNAME="(none)"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_CROSS_MEMORY_ATTACH=y
+CONFIG_FHANDLE=y
+CONFIG_USELIB=y
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_ARCH_AUDITSYSCALL=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_IRQ_DOMAIN_HIERARCHY=y
+CONFIG_HANDLE_DOMAIN_IRQ=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_ARCH_CLOCKSOURCE_DATA=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+
+#
+# Timers subsystem
+#
+CONFIG_HZ_PERIODIC=y
+# CONFIG_NO_HZ_IDLE is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set
+# CONFIG_IRQ_TIME_ACCOUNTING is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TINY_RCU=y
+# CONFIG_RCU_EXPERT is not set
+CONFIG_SRCU=y
+# CONFIG_TASKS_RCU is not set
+# CONFIG_RCU_STALL_COMMON is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_RCU_EXPEDITE_BOOT is not set
+# CONFIG_BUILD_BIN2C is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_NMI_LOG_BUF_SHIFT=13
+CONFIG_GENERIC_SCHED_CLOCK=y
+CONFIG_CGROUPS=y
+# CONFIG_MEMCG is not set
+# CONFIG_BLK_CGROUP is not set
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUP_PIDS is not set
+CONFIG_CGROUP_FREEZER=y
+# CONFIG_CPUSETS is not set
+# CONFIG_CGROUP_DEVICE is not set
+# CONFIG_CGROUP_CPUACCT is not set
+# CONFIG_CGROUP_DEBUG is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+CONFIG_NAMESPACES=y
+CONFIG_UTS_NS=y
+CONFIG_IPC_NS=y
+# CONFIG_USER_NS is not set
+CONFIG_PID_NS=y
+CONFIG_NET_NS=y
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_RD_XZ is not set
+# CONFIG_RD_LZO is not set
+CONFIG_RD_LZ4=y
+CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_HAVE_UID16=y
+CONFIG_BPF=y
+# CONFIG_EXPERT is not set
+CONFIG_UID16=y
+CONFIG_MULTIUSER=y
+# CONFIG_SGETMASK_SYSCALL is not set
+CONFIG_SYSFS_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set
+CONFIG_KALLSYMS_BASE_RELATIVE=y
+CONFIG_PRINTK=y
+CONFIG_PRINTK_NMI=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+# CONFIG_BPF_SYSCALL is not set
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_ADVISE_SYSCALLS=y
+# CONFIG_USERFAULTFD is not set
+CONFIG_MEMBARRIER=y
+# CONFIG_EMBEDDED is not set
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLAB_FREELIST_RANDOM is not set
+# CONFIG_SYSTEM_DATA_VERIFICATION is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+# CONFIG_JUMP_LABEL is not set
+# CONFIG_UPROBES is not set
+# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_ARCH_USE_BUILTIN_BSWAP=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_NMI=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_IDLE_POLL_SETUP=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_HAVE_GCC_PLUGINS=y
+# CONFIG_GCC_PLUGINS is not set
+CONFIG_HAVE_CC_STACKPROTECTOR=y
+CONFIG_CC_STACKPROTECTOR=y
+# CONFIG_CC_STACKPROTECTOR_NONE is not set
+# CONFIG_CC_STACKPROTECTOR_REGULAR is not set
+CONFIG_CC_STACKPROTECTOR_STRONG=y
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_MODULES_USE_ELF_REL=y
+CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_HAVE_ARCH_MMAP_RND_BITS=y
+CONFIG_HAVE_EXIT_THREAD=y
+CONFIG_ARCH_MMAP_RND_BITS_MIN=8
+CONFIG_ARCH_MMAP_RND_BITS_MAX=16
+CONFIG_ARCH_MMAP_RND_BITS=8
+# CONFIG_HAVE_ARCH_HASH is not set
+# CONFIG_ISA_BUS_API is not set
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_OLD_SIGACTION=y
+# CONFIG_CPU_NO_EFFICIENT_FFS is not set
+# CONFIG_HAVE_ARCH_VMAP_STACK is not set
+
+#
+# GCOV-based kernel profiling
+#
+CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_MODULE_SIG is not set
+# CONFIG_MODULE_COMPRESS is not set
+# CONFIG_TRIM_UNUSED_KSYMS is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+CONFIG_BLK_DEV_BSG=y
+# CONFIG_BLK_DEV_BSGLIB is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+CONFIG_BLK_CMDLINE_PARSER=y
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_AIX_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_CMDLINE_PARTITION=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+CONFIG_INLINE_READ_UNLOCK=y
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+CONFIG_INLINE_WRITE_UNLOCK=y
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+CONFIG_MMU=y
+CONFIG_ARCH_MULTIPLATFORM=y
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_LPC32XX is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C24XX is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP1 is not set
+
+#
+# Multiple platform selection
+#
+
+#
+# CPU Core family selection
+#
+# CONFIG_ARCH_MULTI_V6 is not set
+CONFIG_ARCH_MULTI_V7=y
+CONFIG_ARCH_MULTI_V6_V7=y
+# CONFIG_ARCH_MULTI_CPU_AUTO is not set
+# CONFIG_ARCH_VIRT is not set
+# CONFIG_ARCH_MVEBU is not set
+# CONFIG_ARCH_ALPINE is not set
+# CONFIG_ARCH_ARTPEC is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_BCM is not set
+# CONFIG_ARCH_BERLIN is not set
+# CONFIG_ARCH_DIGICOLOR is not set
+# CONFIG_ARCH_HIGHBANK is not set
+# CONFIG_ARCH_HISI is not set
+CONFIG_ARCH_GOKE=y
+
+#
+# Goke platform type
+#
+CONFIG_ARCH_GK7205V200=y
+# CONFIG_ARCH_GK7205V300 is not set
+# CONFIG_ARCH_GK7202V300 is not set
+# CONFIG_ARCH_GK7605V100 is not set
+# CONFIG_GOKE_MC is not set
+CONFIG_BSP_ZRELADDR=0x40008000
+CONFIG_BSP_PARAMS_PHYS=0x00000100
+CONFIG_BSP_INITRD_PHYS=0x00800000
+# CONFIG_ARCH_KEYSTONE is not set
+# CONFIG_ARCH_MESON is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_MEDIATEK is not set
+
+#
+# TI OMAP/AM/DM/DRA Family
+#
+# CONFIG_ARCH_OMAP3 is not set
+# CONFIG_ARCH_OMAP4 is not set
+# CONFIG_SOC_OMAP5 is not set
+# CONFIG_SOC_AM33XX is not set
+# CONFIG_SOC_AM43XX is not set
+# CONFIG_SOC_DRA7XX is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_QCOM is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_ROCKCHIP is not set
+# CONFIG_ARCH_SOCFPGA is not set
+# CONFIG_PLAT_SPEAR is not set
+# CONFIG_ARCH_STI is not set
+# CONFIG_ARCH_S5PV210 is not set
+# CONFIG_ARCH_EXYNOS is not set
+# CONFIG_ARCH_RENESAS is not set
+# CONFIG_ARCH_SUNXI is not set
+# CONFIG_ARCH_SIRF is not set
+# CONFIG_ARCH_TANGO is not set
+# CONFIG_ARCH_TEGRA is not set
+# CONFIG_ARCH_UNIPHIER is not set
+# CONFIG_ARCH_U8500 is not set
+# CONFIG_ARCH_VEXPRESS is not set
+# CONFIG_ARCH_WM8850 is not set
+# CONFIG_ARCH_ZX is not set
+# CONFIG_ARCH_ZYNQ is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_V7=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_LPAE is not set
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+CONFIG_ARM_THUMB=y
+# CONFIG_ARM_THUMBEE is not set
+CONFIG_ARM_VIRT_EXT=y
+# CONFIG_SWP_EMULATE is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_KUSER_HELPERS=y
+CONFIG_VDSO=y
+CONFIG_MIGHT_HAVE_CACHE_L2X0=y
+# CONFIG_CACHE_L2X0 is not set
+CONFIG_ARM_L1_CACHE_SHIFT_6=y
+CONFIG_ARM_L1_CACHE_SHIFT=6
+CONFIG_ARM_DMA_MEM_BUFFERABLE=y
+# CONFIG_DEBUG_RODATA is not set
+CONFIG_MULTI_IRQ_HANDLER=y
+# CONFIG_ARM_ERRATA_430973 is not set
+# CONFIG_ARM_ERRATA_720789 is not set
+# CONFIG_ARM_ERRATA_754322 is not set
+# CONFIG_ARM_ERRATA_775420 is not set
+# CONFIG_ARM_ERRATA_773022 is not set
+# CONFIG_ARM_ERRATA_818325_852422 is not set
+# CONFIG_ARM_ERRATA_821420 is not set
+# CONFIG_ARM_ERRATA_825619 is not set
+# CONFIG_ARM_ERRATA_852421 is not set
+# CONFIG_ARM_ERRATA_852423 is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS_GENERIC is not set
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_HAVE_SMP=y
+# CONFIG_SMP is not set
+CONFIG_HAVE_ARM_ARCH_TIMER=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_3G_OPT is not set
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_ARM_PSCI is not set
+CONFIG_ARCH_NR_GPIO=0
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ_FIXED=0
+CONFIG_HZ_100=y
+# CONFIG_HZ_200 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_500 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
+# CONFIG_SCHED_HRTICK is not set
+# CONFIG_THUMB2_KERNEL is not set
+CONFIG_ARM_PATCH_IDIV=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_HAVE_ARCH_PFN_VALID=y
+# CONFIG_HIGHMEM is not set
+# CONFIG_CPU_SW_DOMAIN_PAN is not set
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+# CONFIG_ARM_MODULE_PLTS is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_NO_BOOTMEM=y
+# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_COMPACTION=y
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NEED_PER_CPU_KM=y
+# CONFIG_CLEANCACHE is not set
+# CONFIG_CMA is not set
+# CONFIG_ZPOOL is not set
+# CONFIG_ZBUD is not set
+# CONFIG_ZSMALLOC is not set
+CONFIG_GENERIC_EARLY_IOREMAP=y
+# CONFIG_IDLE_PAGE_TRACKING is not set
+CONFIG_FRAME_VECTOR=y
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+# CONFIG_SECCOMP is not set
+CONFIG_SWIOTLB=y
+CONFIG_IOMMU_HELPER=y
+# CONFIG_PARAVIRT is not set
+# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set
+# CONFIG_XEN is not set
+
+#
+# Boot options
+#
+CONFIG_USE_OF=y
+CONFIG_ATAGS=y
+# CONFIG_DEPRECATED_PARAM_STRUCT is not set
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER=y
+# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set
+CONFIG_CMDLINE=""
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_AUTO_ZRELADDR=y
+# CONFIG_EFI is not set
+
+#
+# CPU Power Management
+#
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# CPU Idle
+#
+# CONFIG_CPU_IDLE is not set
+# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+# CONFIG_KERNEL_MODE_NEON is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_ELFCORE=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
+CONFIG_BINFMT_SCRIPT=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_COREDUMP=y
+
+#
+# Power management options
+#
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_PM_SLEEP=y
+# CONFIG_PM_AUTOSLEEP is not set
+# CONFIG_PM_WAKELOCKS is not set
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_APM_EMULATION is not set
+CONFIG_PM_CLK=y
+# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_CPU_PM=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARM_CPU_SUSPEND=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_DIAG is not set
+CONFIG_UNIX=y
+# CONFIG_UNIX_DIAG is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_ALGO=y
+CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+# CONFIG_IP_FIB_TRIE_STATS is not set
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
+# CONFIG_NET_IP_TUNNEL is not set
+CONFIG_IP_MROUTE=y
+# CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_NET_UDP_TUNNEL is not set
+# CONFIG_NET_FOU is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_INET_UDP_DIAG is not set
+# CONFIG_INET_DIAG_DESTROY is not set
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BIC=m
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+# CONFIG_TCP_CONG_HSTCP is not set
+# CONFIG_TCP_CONG_HYBLA is not set
+# CONFIG_TCP_CONG_VEGAS is not set
+# CONFIG_TCP_CONG_NV is not set
+# CONFIG_TCP_CONG_SCALABLE is not set
+# CONFIG_TCP_CONG_LP is not set
+# CONFIG_TCP_CONG_VENO is not set
+# CONFIG_TCP_CONG_YEAH is not set
+# CONFIG_TCP_CONG_ILLINOIS is not set
+# CONFIG_TCP_CONG_DCTCP is not set
+# CONFIG_TCP_CONG_CDG is not set
+# CONFIG_TCP_CONG_BBR is not set
+CONFIG_DEFAULT_CUBIC=y
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NET_PTP_CLASSIFY is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP is not set
+# CONFIG_BRIDGE is not set
+CONFIG_HAVE_NET_DSA=y
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+CONFIG_DNS_RESOLVER=y
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+# CONFIG_VSOCKETS is not set
+# CONFIG_NETLINK_DIAG is not set
+# CONFIG_MPLS is not set
+# CONFIG_HSR is not set
+# CONFIG_NET_SWITCHDEV is not set
+# CONFIG_NET_L3_MASTER_DEV is not set
+# CONFIG_NET_NCSI is not set
+# CONFIG_SOCK_CGROUP_DATA is not set
+# CONFIG_CGROUP_NET_PRIO is not set
+# CONFIG_CGROUP_NET_CLASSID is not set
+CONFIG_NET_RX_BUSY_POLL=y
+CONFIG_BQL=y
+# CONFIG_BPF_JIT is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_AF_KCM is not set
+# CONFIG_STREAM_PARSER is not set
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_CFG80211=m
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+CONFIG_CFG80211_DEFAULT_PS=y
+# CONFIG_CFG80211_INTERNAL_REGDB is not set
+CONFIG_CFG80211_CRDA_SUPPORT=y
+CONFIG_CFG80211_WEXT=y
+# CONFIG_LIB80211 is not set
+CONFIG_MAC80211=m
+CONFIG_MAC80211_HAS_RC=y
+CONFIG_MAC80211_RC_MINSTREL=y
+CONFIG_MAC80211_RC_MINSTREL_HT=y
+# CONFIG_MAC80211_RC_MINSTREL_VHT is not set
+CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y
+CONFIG_MAC80211_RC_DEFAULT="minstrel_ht"
+CONFIG_MAC80211_MESH=y
+# CONFIG_MAC80211_MESSAGE_TRACING is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+CONFIG_MAC80211_STA_HASH_MAX_SIZE=0
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+# CONFIG_LWTUNNEL is not set
+# CONFIG_DST_CACHE is not set
+# CONFIG_NET_DEVLINK is not set
+CONFIG_MAY_USE_DEVLINK=y
+CONFIG_HAVE_CBPF_JIT=y
+
+#
+# Device Drivers
+#
+CONFIG_ARM_AMBA=y
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set
+CONFIG_ALLOW_DEV_COREDUMP=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+CONFIG_REGMAP=y
+CONFIG_REGMAP_I2C=y
+CONFIG_REGMAP_SPI=y
+CONFIG_REGMAP_MMIO=y
+CONFIG_DMA_SHARED_BUFFER=y
+# CONFIG_FENCE_TRACE is not set
+
+#
+# Bus devices
+#
+# CONFIG_BRCMSTB_GISB_ARB is not set
+# CONFIG_VEXPRESS_CONFIG is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+CONFIG_MTD_OF_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
+# CONFIG_MTD_OOPS is not set
+# CONFIG_MTD_PARTITIONED_MASTER is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SST25L is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOCG3 is not set
+CONFIG_MTD_NAND_ECC=y
+# CONFIG_MTD_NAND_ECC_SMC is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_ECC_BCH is not set
+# CONFIG_MTD_SM_COMMON is not set
+# CONFIG_MTD_NAND_DENALI_DT is not set
+# CONFIG_MTD_NAND_GPIO is not set
+# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_DOCG4 is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_BRCMNAND is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_NAND_HISI504 is not set
+# CONFIG_MTD_NAND_MTK is not set
+CONFIG_MTD_SPI_NAND_GOKE=y
+# CONFIG_GOKE_NAND_ECC_STATUS_REPORT is not set
+# CONFIG_GOKE_NAND_FS_MAY_NO_YAFFS2 is not set
+CONFIG_MTD_SPI_NAND_FMC100=y
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR & LPDDR2 PCM memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_LPDDR2_NVM is not set
+CONFIG_MTD_SPI_NOR=y
+# CONFIG_MTD_MT81xx_NOR is not set
+# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
+# CONFIG_SPI_CADENCE_QUADSPI is not set
+CONFIG_SPI_GOKE_SFC=y
+# CONFIG_CLOSE_SPI_8PIN_4IO is not set
+CONFIG_GOKE_SPI_BLOCK_PROTECT=y
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_LIMIT=20
+# CONFIG_MTD_UBI_FASTMAP is not set
+# CONFIG_MTD_UBI_GLUEBI is not set
+# CONFIG_MTD_UBI_BLOCK is not set
+CONFIG_DTC=y
+CONFIG_OF=y
+# CONFIG_OF_UNITTEST is not set
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_NET=y
+CONFIG_OF_MDIO=y
+CONFIG_OF_RESERVED_MEM=y
+# CONFIG_OF_OVERLAY is not set
+CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_NULL_BLK is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_DRBD is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=65536
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MG_DISK is not set
+# CONFIG_BLK_DEV_RBD is not set
+# CONFIG_NVME_TARGET is not set
+
+#
+# Misc devices
+#
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_DUMMY_IRQ is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_APDS9802ALS is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_ISL29020 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_BH1770 is not set
+# CONFIG_SENSORS_APDS990X is not set
+# CONFIG_HMC6352 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_TI_DAC7512 is not set
+# CONFIG_USB_SWITCH_FSA9480 is not set
+# CONFIG_LATTICE_ECP3_CONFIG is not set
+# CONFIG_SRAM is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_EEPROM_93XX46 is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+# CONFIG_SENSORS_LIS3_SPI is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
+
+#
+# Altera FPGA firmware download module
+#
+# CONFIG_ALTERA_STAPL is not set
+
+#
+# Intel MIC Bus Driver
+#
+
+#
+# SCIF Bus Driver
+#
+
+#
+# VOP Bus Driver
+#
+
+#
+# Intel MIC Host Driver
+#
+
+#
+# Intel MIC Card Driver
+#
+
+#
+# SCIF Driver
+#
+
+#
+# Intel MIC Coprocessor State Management (COSM) Drivers
+#
+
+#
+# VOP Driver
+#
+# CONFIG_ECHO is not set
+# CONFIG_CXL_BASE is not set
+# CONFIG_CXL_AFU_DRIVER_OPS is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+CONFIG_SCSI_NETLINK=y
+# CONFIG_SCSI_MQ_DEFAULT is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+CONFIG_SCSI_FC_ATTRS=y
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_ISCSI_BOOT_SYSFS is not set
+# CONFIG_SCSI_UFSHCD is not set
+# CONFIG_LIBFC is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_TARGET_CORE is not set
+CONFIG_NETDEVICES=y
+CONFIG_NET_CORE=y
+# CONFIG_BONDING is not set
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_NET_TEAM is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_VXLAN is not set
+# CONFIG_MACSEC is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_TUN is not set
+# CONFIG_TUN_VNET_CROSS_LE is not set
+# CONFIG_VETH is not set
+# CONFIG_NLMON is not set
+
+#
+# CAIF transport drivers
+#
+
+#
+# Distributed Switch Architecture drivers
+#
+CONFIG_ETHERNET=y
+# CONFIG_ALTERA_TSE is not set
+# CONFIG_NET_VENDOR_AMAZON is not set
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_AURORA is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_DM9000 is not set
+# CONFIG_DNET is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_HISILICON is not set
+CONFIG_NET_VENDOR_GOKE=y
+CONFIG_GOKE_FEMAC=y
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+CONFIG_NET_VENDOR_MICROCHIP=y
+# CONFIG_ENC28J60 is not set
+# CONFIG_ENCX24J600 is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
+# CONFIG_ETHOC is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_PHYLIB=y
+CONFIG_SWPHY=y
+
+#
+# MDIO bus device drivers
+#
+# CONFIG_MDIO_BCM_UNIMAC is not set
+# CONFIG_MDIO_BITBANG is not set
+# CONFIG_MDIO_BUS_MUX_GPIO is not set
+# CONFIG_MDIO_BUS_MUX_MMIOREG is not set
+CONFIG_MDIO_GOKE_FEMAC=y
+# CONFIG_MDIO_HISI_FEMAC is not set
+
+#
+# MII PHY device drivers
+#
+# CONFIG_AMD_PHY is not set
+# CONFIG_AQUANTIA_PHY is not set
+# CONFIG_AT803X_PHY is not set
+# CONFIG_BCM7XXX_PHY is not set
+# CONFIG_BCM87XX_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_DP83848_PHY is not set
+# CONFIG_DP83867_PHY is not set
+CONFIG_FIXED_PHY=y
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_INTEL_XWAY_PHY is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_MICREL_PHY is not set
+# CONFIG_MICROCHIP_PHY is not set
+# CONFIG_MICROSEMI_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_TERANETICS_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_XILINX_GMII2RGMII is not set
+# CONFIG_MICREL_KS8995MA is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_USB_NET_DRIVERS is not set
+# CONFIG_WLAN is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_ISDN is not set
+# CONFIG_NVM is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+# CONFIG_INPUT_MATRIXKMAP is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ADP5588 is not set
+# CONFIG_KEYBOARD_ADP5589 is not set
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_QT1070 is not set
+# CONFIG_KEYBOARD_QT2160 is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_KEYBOARD_GPIO_POLLED is not set
+# CONFIG_KEYBOARD_TCA6416 is not set
+# CONFIG_KEYBOARD_TCA8418 is not set
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_LM8333 is not set
+# CONFIG_KEYBOARD_MAX7359 is not set
+# CONFIG_KEYBOARD_MCS is not set
+# CONFIG_KEYBOARD_MPR121 is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_SAMSUNG is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_OMAP4 is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_CAP11XX is not set
+# CONFIG_KEYBOARD_BCM is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_BYD=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_CYPRESS=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_SENTELIC is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+CONFIG_MOUSE_PS2_FOCALTECH=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_CYAPA is not set
+# CONFIG_MOUSE_ELAN_I2C is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+# CONFIG_MOUSE_SYNAPTICS_I2C is not set
+# CONFIG_MOUSE_SYNAPTICS_USB is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_AD714X is not set
+# CONFIG_INPUT_ATMEL_CAPTOUCH is not set
+# CONFIG_INPUT_BMA150 is not set
+# CONFIG_INPUT_E3X0_BUTTON is not set
+# CONFIG_INPUT_MMA8450 is not set
+# CONFIG_INPUT_MPU3050 is not set
+# CONFIG_INPUT_GP2A is not set
+# CONFIG_INPUT_GPIO_BEEPER is not set
+# CONFIG_INPUT_GPIO_TILT_POLLED is not set
+# CONFIG_INPUT_GPIO_DECODER is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_KXTJ9 is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
+CONFIG_INPUT_UINPUT=y
+# CONFIG_INPUT_PCF8574 is not set
+# CONFIG_INPUT_PWM_BEEPER is not set
+# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
+# CONFIG_INPUT_ADXL34X is not set
+# CONFIG_INPUT_CMA3000 is not set
+# CONFIG_INPUT_DRV260X_HAPTICS is not set
+# CONFIG_INPUT_DRV2665_HAPTICS is not set
+# CONFIG_INPUT_DRV2667_HAPTICS is not set
+# CONFIG_RMI4_CORE is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_AMBAKMI is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_ALTERA_PS2 is not set
+# CONFIG_SERIO_PS2MULT is not set
+# CONFIG_SERIO_ARC_PS2 is not set
+# CONFIG_SERIO_APBPS2 is not set
+# CONFIG_USERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_TTY=y
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_VT_CONSOLE_SLEEP=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVMEM=y
+# CONFIG_DEVKMEM is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_EARLYCON=y
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_AMBA_PL010 is not set
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set
+# CONFIG_SERIAL_MAX3100 is not set
+# CONFIG_SERIAL_MAX310X is not set
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_SCCNXP is not set
+# CONFIG_SERIAL_SC16IS7XX is not set
+# CONFIG_SERIAL_BCM63XX is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_IFX6X60 is not set
+# CONFIG_SERIAL_XILINX_PS_UART is not set
+# CONFIG_SERIAL_ARC is not set
+# CONFIG_SERIAL_FSL_LPUART is not set
+# CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set
+# CONFIG_SERIAL_ST_ASC is not set
+# CONFIG_SERIAL_STM32 is not set
+# CONFIG_HVC_DCC is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_XILLYBUS is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MUX=y
+
+#
+# Multiplexer I2C Chip support
+#
+# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set
+# CONFIG_I2C_MUX_GPIO is not set
+# CONFIG_I2C_MUX_PCA9541 is not set
+# CONFIG_I2C_MUX_PCA954x is not set
+# CONFIG_I2C_MUX_PINCTRL is not set
+# CONFIG_I2C_MUX_REG is not set
+# CONFIG_I2C_DEMUX_PINCTRL is not set
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_CBUS_GPIO is not set
+# CONFIG_I2C_DESIGNWARE_PLATFORM is not set
+# CONFIG_I2C_EMEV2 is not set
+# CONFIG_I2C_GPIO is not set
+CONFIG_I2C_GOKE=y
+# CONFIG_I2C_NOMADIK is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_PXA_PCI is not set
+# CONFIG_I2C_RK3X is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_DIOLAN_U2C is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_ROBOTFUZZ_OSIF is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+CONFIG_DMA_MSG_MIN_LEN=5
+CONFIG_DMA_MSG_MAX_LEN=4090
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_SLAVE is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_ALTERA is not set
+# CONFIG_SPI_AXI_SPI_ENGINE is not set
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_CADENCE is not set
+# CONFIG_SPI_DESIGNWARE is not set
+# CONFIG_SPI_GPIO is not set
+# CONFIG_SPI_FSL_SPI is not set
+# CONFIG_SPI_OC_TINY is not set
+CONFIG_SPI_PL022=y
+# CONFIG_SPI_PXA2XX_PCI is not set
+# CONFIG_SPI_ROCKCHIP is not set
+# CONFIG_SPI_SC18IS602 is not set
+# CONFIG_SPI_XCOMM is not set
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_ZYNQMP_GQSPI is not set
+
+#
+# SPI Protocol Masters
+#
+CONFIG_SPI_SPIDEV=y
+# CONFIG_SPI_LOOPBACK_TEST is not set
+# CONFIG_SPI_TLE62X0 is not set
+# CONFIG_SPMI is not set
+# CONFIG_HSI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+# CONFIG_PTP_1588_CLOCK is not set
+
+#
+# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
+#
+CONFIG_PINCTRL=y
+
+#
+# Pin controllers
+#
+CONFIG_PINMUX=y
+CONFIG_PINCONF=y
+CONFIG_GENERIC_PINCONF=y
+# CONFIG_DEBUG_PINCTRL is not set
+# CONFIG_PINCTRL_AMD is not set
+CONFIG_PINCTRL_SINGLE=y
+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
+CONFIG_GPIOLIB=y
+CONFIG_OF_GPIO=y
+CONFIG_GPIOLIB_IRQCHIP=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO drivers
+#
+# CONFIG_GPIO_74XX_MMIO is not set
+# CONFIG_GPIO_ALTERA is not set
+# CONFIG_GPIO_DWAPB is not set
+# CONFIG_GPIO_EM is not set
+# CONFIG_GPIO_GENERIC_PLATFORM is not set
+# CONFIG_GPIO_GRGPIO is not set
+# CONFIG_GPIO_MOCKUP is not set
+# CONFIG_GPIO_MPC8XXX is not set
+CONFIG_GPIO_PL061=y
+# CONFIG_GPIO_SYSCON is not set
+# CONFIG_GPIO_XILINX is not set
+# CONFIG_GPIO_ZEVIO is not set
+# CONFIG_GPIO_ZX is not set
+
+#
+# I2C GPIO expanders
+#
+# CONFIG_GPIO_ADP5588 is not set
+# CONFIG_GPIO_ADNP is not set
+# CONFIG_GPIO_MAX7300 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_SX150X is not set
+# CONFIG_GPIO_TPIC2810 is not set
+# CONFIG_GPIO_TS4900 is not set
+
+#
+# MFD GPIO expanders
+#
+# CONFIG_HTC_EGPIO is not set
+
+#
+# SPI GPIO expanders
+#
+# CONFIG_GPIO_74X164 is not set
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MC33880 is not set
+# CONFIG_GPIO_PISOSR is not set
+
+#
+# SPI or I2C GPIO expanders
+#
+# CONFIG_GPIO_MCP23S08 is not set
+
+#
+# USB GPIO expanders
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_AVS is not set
+CONFIG_POWER_RESET=y
+# CONFIG_POWER_RESET_BRCMKONA is not set
+# CONFIG_POWER_RESET_BRCMSTB is not set
+CONFIG_POWER_RESET_GOKE=y
+# CONFIG_POWER_RESET_GPIO is not set
+# CONFIG_POWER_RESET_GPIO_RESTART is not set
+# CONFIG_POWER_RESET_LTC2952 is not set
+# CONFIG_POWER_RESET_RESTART is not set
+# CONFIG_POWER_RESET_VERSATILE is not set
+# CONFIG_POWER_RESET_SYSCON is not set
+# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set
+# CONFIG_SYSCON_REBOOT_MODE is not set
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_TEST_POWER is not set
+# CONFIG_BATTERY_DS2780 is not set
+# CONFIG_BATTERY_DS2781 is not set
+# CONFIG_BATTERY_DS2782 is not set
+# CONFIG_BATTERY_SBS is not set
+# CONFIG_BATTERY_BQ27XXX is not set
+# CONFIG_BATTERY_MAX17040 is not set
+# CONFIG_BATTERY_MAX17042 is not set
+# CONFIG_CHARGER_MAX8903 is not set
+# CONFIG_CHARGER_LP8727 is not set
+# CONFIG_CHARGER_GPIO is not set
+# CONFIG_CHARGER_BQ2415X is not set
+# CONFIG_CHARGER_BQ24190 is not set
+# CONFIG_CHARGER_BQ24257 is not set
+# CONFIG_CHARGER_BQ24735 is not set
+# CONFIG_CHARGER_BQ25890 is not set
+# CONFIG_CHARGER_SMB347 is not set
+# CONFIG_BATTERY_GAUGE_LTC2941 is not set
+# CONFIG_CHARGER_RT9455 is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+CONFIG_MFD_CORE=y
+# CONFIG_MFD_ACT8945A is not set
+# CONFIG_MFD_AS3711 is not set
+# CONFIG_MFD_AS3722 is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_AAT2870_CORE is not set
+# CONFIG_MFD_ATMEL_FLEXCOM is not set
+# CONFIG_MFD_ATMEL_HLCDC is not set
+# CONFIG_MFD_BCM590XX is not set
+# CONFIG_MFD_AXP20X_I2C is not set
+# CONFIG_MFD_CROS_EC is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_DA9052_SPI is not set
+# CONFIG_MFD_DA9052_I2C is not set
+# CONFIG_MFD_DA9055 is not set
+# CONFIG_MFD_DA9062 is not set
+# CONFIG_MFD_DA9063 is not set
+# CONFIG_MFD_DA9150 is not set
+# CONFIG_MFD_DLN2 is not set
+# CONFIG_MFD_EXYNOS_LPASS is not set
+# CONFIG_MFD_MC13XXX_SPI is not set
+# CONFIG_MFD_MC13XXX_I2C is not set
+# CONFIG_MFD_HI6421_PMIC is not set
+CONFIG_MFD_GOKE_FMC=y
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_HTC_I2CPLD is not set
+# CONFIG_INTEL_SOC_PMIC is not set
+# CONFIG_MFD_KEMPLD is not set
+# CONFIG_MFD_88PM800 is not set
+# CONFIG_MFD_88PM805 is not set
+# CONFIG_MFD_88PM860X is not set
+# CONFIG_MFD_MAX14577 is not set
+# CONFIG_MFD_MAX77620 is not set
+# CONFIG_MFD_MAX77686 is not set
+# CONFIG_MFD_MAX77693 is not set
+# CONFIG_MFD_MAX77843 is not set
+# CONFIG_MFD_MAX8907 is not set
+# CONFIG_MFD_MAX8925 is not set
+# CONFIG_MFD_MAX8997 is not set
+# CONFIG_MFD_MAX8998 is not set
+# CONFIG_MFD_MT6397 is not set
+# CONFIG_MFD_MENF21BMC is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_MFD_VIPERBOARD is not set
+# CONFIG_MFD_RETU is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_PM8921_CORE is not set
+# CONFIG_MFD_RT5033 is not set
+# CONFIG_MFD_RTSX_USB is not set
+# CONFIG_MFD_RC5T583 is not set
+# CONFIG_MFD_RK808 is not set
+# CONFIG_MFD_RN5T618 is not set
+# CONFIG_MFD_SEC_CORE is not set
+# CONFIG_MFD_SI476X_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_SKY81452 is not set
+# CONFIG_MFD_SMSC is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_MFD_STMPE is not set
+CONFIG_MFD_SYSCON=y
+# CONFIG_MFD_TI_AM335X_TSCADC is not set
+# CONFIG_MFD_LP3943 is not set
+# CONFIG_MFD_LP8788 is not set
+# CONFIG_MFD_PALMAS is not set
+# CONFIG_TPS6105X is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TPS6507X is not set
+# CONFIG_MFD_TPS65086 is not set
+# CONFIG_MFD_TPS65090 is not set
+# CONFIG_MFD_TPS65217 is not set
+# CONFIG_MFD_TI_LP873X is not set
+# CONFIG_MFD_TPS65218 is not set
+# CONFIG_MFD_TPS6586X is not set
+# CONFIG_MFD_TPS65910 is not set
+# CONFIG_MFD_TPS65912_I2C is not set
+# CONFIG_MFD_TPS65912_SPI is not set
+# CONFIG_MFD_TPS80031 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_TWL6040_CORE is not set
+# CONFIG_MFD_WL1273_CORE is not set
+# CONFIG_MFD_LM3533 is not set
+# CONFIG_MFD_TC3589X is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_MFD_ARIZONA_I2C is not set
+# CONFIG_MFD_ARIZONA_SPI is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X_I2C is not set
+# CONFIG_MFD_WM831X_SPI is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8994 is not set
+# CONFIG_REGULATOR is not set
+CONFIG_MEDIA_SUPPORT=y
+
+#
+# Multimedia core support
+#
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set
+# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set
+# CONFIG_MEDIA_RADIO_SUPPORT is not set
+# CONFIG_MEDIA_SDR_SUPPORT is not set
+# CONFIG_MEDIA_RC_SUPPORT is not set
+# CONFIG_MEDIA_CONTROLLER is not set
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L2=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEOBUF2_CORE=y
+CONFIG_VIDEOBUF2_MEMOPS=y
+CONFIG_VIDEOBUF2_VMALLOC=y
+# CONFIG_TTPCI_EEPROM is not set
+
+#
+# Media drivers
+#
+CONFIG_MEDIA_USB_SUPPORT=y
+
+#
+# Webcam devices
+#
+CONFIG_USB_VIDEO_CLASS=y
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+CONFIG_USB_GSPCA=m
+# CONFIG_USB_M5602 is not set
+# CONFIG_USB_STV06XX is not set
+# CONFIG_USB_GL860 is not set
+# CONFIG_USB_GSPCA_BENQ is not set
+# CONFIG_USB_GSPCA_CONEX is not set
+# CONFIG_USB_GSPCA_CPIA1 is not set
+# CONFIG_USB_GSPCA_DTCS033 is not set
+# CONFIG_USB_GSPCA_ETOMS is not set
+# CONFIG_USB_GSPCA_FINEPIX is not set
+# CONFIG_USB_GSPCA_JEILINJ is not set
+# CONFIG_USB_GSPCA_JL2005BCD is not set
+# CONFIG_USB_GSPCA_KINECT is not set
+# CONFIG_USB_GSPCA_KONICA is not set
+# CONFIG_USB_GSPCA_MARS is not set
+# CONFIG_USB_GSPCA_MR97310A is not set
+# CONFIG_USB_GSPCA_NW80X is not set
+# CONFIG_USB_GSPCA_OV519 is not set
+# CONFIG_USB_GSPCA_OV534 is not set
+# CONFIG_USB_GSPCA_OV534_9 is not set
+# CONFIG_USB_GSPCA_PAC207 is not set
+# CONFIG_USB_GSPCA_PAC7302 is not set
+# CONFIG_USB_GSPCA_PAC7311 is not set
+# CONFIG_USB_GSPCA_SE401 is not set
+# CONFIG_USB_GSPCA_SN9C2028 is not set
+# CONFIG_USB_GSPCA_SN9C20X is not set
+# CONFIG_USB_GSPCA_SONIXB is not set
+# CONFIG_USB_GSPCA_SONIXJ is not set
+# CONFIG_USB_GSPCA_SPCA500 is not set
+# CONFIG_USB_GSPCA_SPCA501 is not set
+# CONFIG_USB_GSPCA_SPCA505 is not set
+# CONFIG_USB_GSPCA_SPCA506 is not set
+# CONFIG_USB_GSPCA_SPCA508 is not set
+# CONFIG_USB_GSPCA_SPCA561 is not set
+# CONFIG_USB_GSPCA_SPCA1528 is not set
+# CONFIG_USB_GSPCA_SQ905 is not set
+# CONFIG_USB_GSPCA_SQ905C is not set
+# CONFIG_USB_GSPCA_SQ930X is not set
+# CONFIG_USB_GSPCA_STK014 is not set
+# CONFIG_USB_GSPCA_STK1135 is not set
+# CONFIG_USB_GSPCA_STV0680 is not set
+# CONFIG_USB_GSPCA_SUNPLUS is not set
+# CONFIG_USB_GSPCA_T613 is not set
+# CONFIG_USB_GSPCA_TOPRO is not set
+# CONFIG_USB_GSPCA_TOUPTEK is not set
+# CONFIG_USB_GSPCA_TV8532 is not set
+# CONFIG_USB_GSPCA_VC032X is not set
+# CONFIG_USB_GSPCA_VICAM is not set
+# CONFIG_USB_GSPCA_XIRLINK_CIT is not set
+# CONFIG_USB_GSPCA_ZC3XX is not set
+# CONFIG_USB_PWC is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_USB_ZR364XX is not set
+# CONFIG_USB_STKWEBCAM is not set
+# CONFIG_USB_S2255 is not set
+
+#
+# Webcam, TV (analog/digital) USB devices
+#
+# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_V4L_PLATFORM_DRIVERS is not set
+# CONFIG_V4L_MEM2MEM_DRIVERS is not set
+# CONFIG_V4L_TEST_DRIVERS is not set
+
+#
+# Supported MMC/SDIO adapters
+#
+# CONFIG_CYPRESS_FIRMWARE is not set
+
+#
+# Media ancillary drivers (tuners, sensors, i2c, spi, frontends)
+#
+CONFIG_MEDIA_SUBDRV_AUTOSELECT=y
+
+#
+# Audio decoders, processors and mixers
+#
+
+#
+# RDS decoders
+#
+
+#
+# Video decoders
+#
+
+#
+# Video and audio decoders
+#
+
+#
+# Video encoders
+#
+
+#
+# Camera sensor devices
+#
+
+#
+# Flash devices
+#
+
+#
+# Video improvement chips
+#
+
+#
+# Audio/Video compression chips
+#
+
+#
+# Miscellaneous helper chips
+#
+
+#
+# Sensors used on soc_camera driver
+#
+
+#
+# Tools to develop new frontends
+#
+# CONFIG_DVB_DUMMY_FE is not set
+
+#
+# Graphics support
+#
+# CONFIG_IMX_IPUV3_CORE is not set
+# CONFIG_DRM is not set
+
+#
+# ACP (Audio CoProcessor) Configuration
+#
+
+#
+# Frame buffer Devices
+#
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB_CMDLINE=y
+CONFIG_FB_NOTIFY=y
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_ARMCLCD is not set
+# CONFIG_FB_OPENCORES is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_SMSCUFX is not set
+# CONFIG_FB_UDL is not set
+# CONFIG_FB_IBM_GXT4500 is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_FB_AUO_K190X is not set
+# CONFIG_FB_SIMPLE is not set
+# CONFIG_FB_SSD1307 is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+# CONFIG_LOGO is not set
+# CONFIG_SOUND is not set
+
+#
+# HID support
+#
+CONFIG_HID=y
+# CONFIG_HID_BATTERY_STRENGTH is not set
+# CONFIG_HIDRAW is not set
+# CONFIG_UHID is not set
+CONFIG_HID_GENERIC=y
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_ACRUX is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_APPLEIR is not set
+# CONFIG_HID_AUREAL is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_BETOP_FF is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_CMEDIA is not set
+# CONFIG_HID_CP2112 is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EMS_FF is not set
+# CONFIG_HID_ELECOM is not set
+# CONFIG_HID_ELO is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_GEMBIRD is not set
+# CONFIG_HID_GFRM is not set
+# CONFIG_HID_HOLTEK is not set
+# CONFIG_HID_KEYTOUCH is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_UCLOGIC is not set
+# CONFIG_HID_WALTOP is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_ICADE is not set
+# CONFIG_HID_TWINHAN is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LCPOWER is not set
+# CONFIG_HID_LENOVO is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MAGICMOUSE is not set
+CONFIG_HID_MICROSOFT=y
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_MULTITOUCH is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_ORTEK is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PENMOUNT is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_PICOLCD is not set
+# CONFIG_HID_PLANTRONICS is not set
+# CONFIG_HID_PRIMAX is not set
+# CONFIG_HID_ROCCAT is not set
+# CONFIG_HID_SAITEK is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SPEEDLINK is not set
+# CONFIG_HID_STEELSERIES is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_RMI is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TIVO is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_WACOM is not set
+# CONFIG_HID_XINMO is not set
+# CONFIG_HID_ZEROPLUS is not set
+# CONFIG_HID_ZYDACRON is not set
+# CONFIG_HID_SENSOR_HUB is not set
+# CONFIG_HID_ALPS is not set
+
+#
+# USB HID support
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# I2C HID support
+#
+# CONFIG_I2C_HID is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_COMMON=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB=y
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEFAULT_PERSIST=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_PLATFORM=y
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+# CONFIG_USB_FOTG210_HCD is not set
+# CONFIG_USB_MAX3421_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HCD_TEST_MODE is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_REALTEK is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_STORAGE_ENE_UB6250 is not set
+# CONFIG_USB_UAS is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USBIP_CORE is not set
+# CONFIG_USB_MUSB_HDRC is not set
+CONFIG_USB_DWC3=y
+# CONFIG_USB_DWC3_HOST is not set
+# CONFIG_USB_DWC3_GADGET is not set
+CONFIG_USB_DWC3_DUAL_ROLE=y
+
+#
+# Platform Glue Driver Support
+#
+CONFIG_USB_DWC3_OF_SIMPLE=y
+# CONFIG_USB_DWC2 is not set
+# CONFIG_USB_CHIPIDEA is not set
+# CONFIG_USB_ISP1760 is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_EHSET_TEST_FIXTURE is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_YUREX is not set
+# CONFIG_USB_EZUSB_FX2 is not set
+# CONFIG_USB_HSIC_USB3503 is not set
+# CONFIG_USB_HSIC_USB4604 is not set
+# CONFIG_USB_LINK_LAYER_TEST is not set
+
+#
+# USB Physical Layer drivers
+#
+# CONFIG_USB_PHY is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_USB_ISP1301 is not set
+# CONFIG_USB_ULPI is not set
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2
+
+#
+# USB Peripheral Controller
+#
+# CONFIG_USB_FUSB300 is not set
+# CONFIG_USB_FOTG210_UDC is not set
+# CONFIG_USB_GR_UDC is not set
+# CONFIG_USB_R8A66597 is not set
+# CONFIG_USB_PXA27X is not set
+# CONFIG_USB_MV_UDC is not set
+# CONFIG_USB_MV_U3D is not set
+# CONFIG_USB_M66592 is not set
+# CONFIG_USB_BDC_UDC is not set
+# CONFIG_USB_NET2272 is not set
+# CONFIG_USB_GADGET_XILINX is not set
+# CONFIG_USB_DUMMY_HCD is not set
+CONFIG_USB_LIBCOMPOSITE=m
+CONFIG_USB_F_ACM=m
+CONFIG_USB_U_SERIAL=m
+CONFIG_USB_U_ETHER=m
+CONFIG_USB_F_ECM=m
+CONFIG_USB_F_RNDIS=m
+CONFIG_USB_F_MASS_STORAGE=m
+CONFIG_USB_CONFIGFS=m
+# CONFIG_USB_CONFIGFS_SERIAL is not set
+CONFIG_USB_CONFIGFS_ACM=y
+# CONFIG_USB_CONFIGFS_OBEX is not set
+# CONFIG_USB_CONFIGFS_NCM is not set
+CONFIG_USB_CONFIGFS_ECM=y
+# CONFIG_USB_CONFIGFS_ECM_SUBSET is not set
+CONFIG_USB_CONFIGFS_RNDIS=y
+# CONFIG_USB_CONFIGFS_EEM is not set
+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
+# CONFIG_USB_CONFIGFS_F_LB_SS is not set
+# CONFIG_USB_CONFIGFS_F_FS is not set
+# CONFIG_USB_CONFIGFS_F_HID is not set
+# CONFIG_USB_CONFIGFS_F_UVC is not set
+# CONFIG_USB_CONFIGFS_F_PRINTER is not set
+# CONFIG_USB_ULPI_BUS is not set
+# CONFIG_UWB is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_PWRSEQ_EMMC=y
+CONFIG_PWRSEQ_SIMPLE=y
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_MINORS=8
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_ARMMMCI is not set
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+# CONFIG_MMC_SDHCI_OF_ARASAN is not set
+# CONFIG_MMC_SDHCI_OF_AT91 is not set
+CONFIG_MMC_SDHCI_GOKE=y
+# CONFIG_MMC_SDHCI_F_SDH30 is not set
+# CONFIG_MMC_SPI is not set
+# CONFIG_MMC_DW is not set
+# CONFIG_MMC_VUB300 is not set
+# CONFIG_MMC_USHC is not set
+# CONFIG_MMC_USDHI6ROL0 is not set
+# CONFIG_MMC_MTK is not set
+# CONFIG_MMC_CQ_HCI is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_EDAC_ATOMIC_SCRUB=y
+CONFIG_EDAC_SUPPORT=y
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+CONFIG_RTC_SYSTOHC=y
+CONFIG_RTC_SYSTOHC_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_ABB5ZES3 is not set
+# CONFIG_RTC_DRV_ABX80X is not set
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_HYM8563 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_ISL12022 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8523 is not set
+# CONFIG_RTC_DRV_PCF85063 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_BQ32K is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8010 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+# CONFIG_RTC_DRV_EM3027 is not set
+# CONFIG_RTC_DRV_RV8803 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T93 is not set
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1302 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1343 is not set
+# CONFIG_RTC_DRV_DS1347 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6916 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RX4581 is not set
+# CONFIG_RTC_DRV_RX6110 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
+# CONFIG_RTC_DRV_MCP795 is not set
+CONFIG_RTC_I2C_AND_SPI=y
+
+#
+# SPI and I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS3232 is not set
+# CONFIG_RTC_DRV_PCF2127 is not set
+# CONFIG_RTC_DRV_RV3029C2 is not set
+
+#
+# Platform RTC drivers
+#
+CONFIG_RTC_DRV_GOKE=y
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1685_FAMILY is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_DS2404 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+# CONFIG_RTC_DRV_ZYNQMP is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_PL030 is not set
+# CONFIG_RTC_DRV_PL031 is not set
+# CONFIG_RTC_DRV_SNVS is not set
+
+#
+# HID Sensor RTC drivers
+#
+# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set
+# CONFIG_DMADEVICES is not set
+
+#
+# DMABUF options
+#
+# CONFIG_SYNC_FILE is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+# CONFIG_VIRT_DRIVERS is not set
+
+#
+# Virtio drivers
+#
+# CONFIG_VIRTIO_MMIO is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_STAGING is not set
+# CONFIG_GOLDFISH is not set
+# CONFIG_CHROME_PLATFORMS is not set
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_COMMON_CLK=y
+
+#
+# Common Clock Framework
+#
+# CONFIG_COMMON_CLK_SI5351 is not set
+# CONFIG_COMMON_CLK_SI514 is not set
+# CONFIG_COMMON_CLK_SI570 is not set
+# CONFIG_COMMON_CLK_CDCE706 is not set
+# CONFIG_COMMON_CLK_CDCE925 is not set
+# CONFIG_COMMON_CLK_CS2000_CP is not set
+# CONFIG_CLK_QORIQ is not set
+# CONFIG_COMMON_CLK_NXP is not set
+# CONFIG_COMMON_CLK_PWM is not set
+# CONFIG_COMMON_CLK_PXA is not set
+# CONFIG_COMMON_CLK_PIC32 is not set
+CONFIG_COMMON_CLK_GK7205V200=y
+CONFIG_RESET_GOKE=y
+
+#
+# Hardware Spinlock drivers
+#
+
+#
+# Clock Source drivers
+#
+CONFIG_CLKSRC_OF=y
+CONFIG_CLKSRC_PROBE=y
+CONFIG_CLKSRC_MMIO=y
+CONFIG_ARM_ARCH_TIMER=y
+CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y
+# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS is not set
+CONFIG_ARM_TIMER_SP804=y
+# CONFIG_ATMEL_PIT is not set
+# CONFIG_SH_TIMER_CMT is not set
+# CONFIG_SH_TIMER_MTU2 is not set
+# CONFIG_SH_TIMER_TMU is not set
+# CONFIG_EM_TIMER_STI is not set
+# CONFIG_MAILBOX is not set
+# CONFIG_IOMMU_SUPPORT is not set
+
+#
+# Remoteproc drivers
+#
+# CONFIG_STE_MODEM_RPROC is not set
+
+#
+# Rpmsg drivers
+#
+
+#
+# SOC (System On Chip) specific Drivers
+#
+
+#
+# Broadcom SoC drivers
+#
+# CONFIG_SOC_BRCMSTB is not set
+# CONFIG_SUNXI_SRAM is not set
+# CONFIG_SOC_TI is not set
+# CONFIG_PM_DEVFREQ is not set
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
+# CONFIG_IIO is not set
+CONFIG_PWM=y
+CONFIG_PWM_SYSFS=y
+# CONFIG_PWM_FSL_FTM is not set
+CONFIG_PWM_GOKE=y
+# CONFIG_PWM_PCA9685 is not set
+CONFIG_IRQCHIP=y
+CONFIG_ARM_GIC=y
+CONFIG_ARM_GIC_MAX_NR=1
+# CONFIG_IPACK_BUS is not set
+CONFIG_RESET_CONTROLLER=y
+# CONFIG_RESET_ATH79 is not set
+# CONFIG_RESET_BERLIN is not set
+# CONFIG_RESET_LPC18XX is not set
+# CONFIG_RESET_MESON is not set
+# CONFIG_RESET_PISTACHIO is not set
+# CONFIG_RESET_SOCFPGA is not set
+# CONFIG_RESET_STM32 is not set
+# CONFIG_RESET_SUNXI is not set
+# CONFIG_TI_SYSCON_RESET is not set
+# CONFIG_RESET_ZYNQ is not set
+# CONFIG_FMC is not set
+
+#
+# PHY Subsystem
+#
+CONFIG_GENERIC_PHY=y
+# CONFIG_PHY_PXA_28NM_HSIC is not set
+# CONFIG_PHY_PXA_28NM_USB2 is not set
+# CONFIG_BCM_KONA_USB2_PHY is not set
+CONFIG_PHY_GOKE_USBP2=y
+# CONFIG_USB_MODE_OPTION is not set
+# CONFIG_POWERCAP is not set
+# CONFIG_MCB is not set
+
+#
+# Performance monitor support
+#
+# CONFIG_RAS is not set
+
+#
+# Android
+#
+# CONFIG_ANDROID is not set
+# CONFIG_NVMEM is not set
+# CONFIG_STM is not set
+# CONFIG_INTEL_TH is not set
+
+#
+# FPGA Configuration Support
+#
+# CONFIG_FPGA is not set
+
+#
+# goke driver support
+#
+
+#
+# Firmware Drivers
+#
+# CONFIG_FIRMWARE_MEMMAP is not set
+# CONFIG_FW_CFG_SYSFS is not set
+CONFIG_HAVE_ARM_SMCCC=y
+
+#
+# File systems
+#
+CONFIG_DCACHE_WORD_ACCESS=y
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_USE_FOR_EXT2=y
+# CONFIG_EXT4_FS_POSIX_ACL is not set
+# CONFIG_EXT4_FS_SECURITY is not set
+# CONFIG_EXT4_ENCRYPTION is not set
+# CONFIG_EXT4_DEBUG is not set
+CONFIG_JBD2=y
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+# CONFIG_F2FS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_EXPORTFS=y
+# CONFIG_EXPORTFS_BLOCK_OPS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_MANDATORY_FILE_LOCKING=y
+# CONFIG_FS_ENCRYPTION is not set
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_QUOTACTL is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+# CONFIG_OVERLAY_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_FAT_DEFAULT_UTF8 is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_PROC_CHILDREN is not set
+CONFIG_KERNFS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_TMPFS_XATTR=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=y
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ORANGEFS_FS is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_YAFFS_FS=y
+CONFIG_YAFFS_YAFFS1=y
+# CONFIG_YAFFS_9BYTE_TAGS is not set
+# CONFIG_YAFFS_DOES_ECC is not set
+CONFIG_YAFFS_YAFFS2=y
+CONFIG_YAFFS_AUTO_YAFFS2=y
+# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set
+# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
+# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set
+# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set
+# CONFIG_YAFFS_DISABLE_BACKGROUND is not set
+# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set
+CONFIG_YAFFS_XATTR=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+# CONFIG_JFFS2_LZMA is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_UBIFS_FS=y
+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_ATIME_SUPPORT is not set
+# CONFIG_LOGFS is not set
+CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX6FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_PSTORE is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V2=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+# CONFIG_NFS_SWAP is not set
+# CONFIG_NFS_V4_1 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFS_USE_LEGACY_DNS is not set
+CONFIG_NFS_USE_KERNEL_DNS=y
+# CONFIG_NFSD is not set
+CONFIG_GRACE_PERIOD=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_ACL_SUPPORT=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_DEBUG is not set
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=y
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+# CONFIG_NLS_MAC_ROMAN is not set
+# CONFIG_NLS_MAC_CELTIC is not set
+# CONFIG_NLS_MAC_CENTEURO is not set
+# CONFIG_NLS_MAC_CROATIAN is not set
+# CONFIG_NLS_MAC_CYRILLIC is not set
+# CONFIG_NLS_MAC_GAELIC is not set
+# CONFIG_NLS_MAC_GREEK is not set
+# CONFIG_NLS_MAC_ICELAND is not set
+# CONFIG_NLS_MAC_INUIT is not set
+# CONFIG_NLS_MAC_ROMANIAN is not set
+# CONFIG_NLS_MAC_TURKISH is not set
+CONFIG_NLS_UTF8=y
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+
+#
+# printk and dmesg options
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
+# CONFIG_BOOT_PRINTK_DELAY is not set
+
+#
+# Compile-time checks and compiler options
+#
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_READABLE_ASM is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_PAGE_OWNER is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_SECTION_MISMATCH_WARN_ONLY=y
+CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_DEBUG_KERNEL=y
+
+#
+# Memory Debugging
+#
+# CONFIG_PAGE_EXTENSION is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_PAGE_POISONING is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_SHIRQ is not set
+
+#
+# Debug Lockups and Hangs
+#
+# CONFIG_LOCKUP_DETECTOR is not set
+# CONFIG_DETECT_HUNG_TASK is not set
+# CONFIG_WQ_WATCHDOG is not set
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+CONFIG_PANIC_TIMEOUT=0
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHED_INFO is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_SCHED_STACK_END_CHECK is not set
+# CONFIG_DEBUG_TIMEKEEPING is not set
+# CONFIG_TIMER_STATS is not set
+
+#
+# Lock Debugging (spinlocks, mutexes, etc...)
+#
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_ATOMIC_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_LOCK_TORTURE_TEST is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_PI_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+
+#
+# RCU Debugging
+#
+# CONFIG_PROVE_RCU is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_TORTURE_TEST is not set
+# CONFIG_RCU_PERF_TEST is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_TRACE is not set
+# CONFIG_RCU_EQS_DEBUG is not set
+# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_NOTIFIER_ERROR_INJECTION is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+
+#
+# Runtime Testing
+#
+# CONFIG_TEST_LIST_SORT is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_RBTREE_TEST is not set
+# CONFIG_INTERVAL_TREE_TEST is not set
+# CONFIG_PERCPU_TEST is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_TEST_HEXDUMP is not set
+# CONFIG_TEST_STRING_HELPERS is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_TEST_PRINTF is not set
+# CONFIG_TEST_BITMAP is not set
+# CONFIG_TEST_UUID is not set
+# CONFIG_TEST_RHASHTABLE is not set
+# CONFIG_TEST_HASH is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_TEST_LKM is not set
+# CONFIG_TEST_USER_COPY is not set
+# CONFIG_TEST_BPF is not set
+# CONFIG_TEST_FIRMWARE is not set
+# CONFIG_TEST_UDELAY is not set
+# CONFIG_MEMTEST is not set
+# CONFIG_TEST_STATIC_KEYS is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set
+# CONFIG_UBSAN is not set
+CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
+CONFIG_STRICT_DEVMEM=y
+# CONFIG_IO_STRICT_DEVMEM is not set
+# CONFIG_ARM_PTDUMP is not set
+# CONFIG_ARM_UNWIND is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_LL is not set
+CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
+# CONFIG_DEBUG_UART_8250 is not set
+CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
+# CONFIG_PID_IN_CONTEXTIDR is not set
+# CONFIG_DEBUG_SET_MODULE_RONX is not set
+# CONFIG_CORESIGHT is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_PERSISTENT_KEYRINGS is not set
+# CONFIG_ENCRYPTED_KEYS is not set
+# CONFIG_KEY_DH_OPERATIONS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y
+CONFIG_HAVE_ARCH_HARDENED_USERCOPY=y
+# CONFIG_HARDENED_USERCOPY is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_RNG_DEFAULT=m
+CONFIG_CRYPTO_AKCIPHER2=y
+CONFIG_CRYPTO_KPP2=y
+# CONFIG_CRYPTO_RSA is not set
+# CONFIG_CRYPTO_DH is not set
+# CONFIG_CRYPTO_ECDH is not set
+CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_USER is not set
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_NULL2=y
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_MCRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+# CONFIG_CRYPTO_CHACHA20POLY1305 is not set
+CONFIG_CRYPTO_SEQIV=m
+CONFIG_CRYPTO_ECHAINIV=m
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+CONFIG_CRYPTO_CTR=m
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+# CONFIG_CRYPTO_KEYWRAP is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_CMAC is not set
+CONFIG_CRYPTO_HMAC=m
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_CRC32 is not set
+CONFIG_CRYPTO_CRCT10DIF=y
+CONFIG_CRYPTO_GHASH=m
+# CONFIG_CRYPTO_POLY1305 is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=y
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_SHA3 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_CHACHA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_LZO=y
+# CONFIG_CRYPTO_842 is not set
+# CONFIG_CRYPTO_LZ4 is not set
+# CONFIG_CRYPTO_LZ4HC is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_DRBG_MENU=m
+CONFIG_CRYPTO_DRBG_HMAC=y
+# CONFIG_CRYPTO_DRBG_HASH is not set
+# CONFIG_CRYPTO_DRBG_CTR is not set
+CONFIG_CRYPTO_DRBG=m
+CONFIG_CRYPTO_JITTERENTROPY=m
+# CONFIG_CRYPTO_USER_API_HASH is not set
+# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
+# CONFIG_CRYPTO_USER_API_RNG is not set
+# CONFIG_CRYPTO_USER_API_AEAD is not set
+# CONFIG_CRYPTO_HW is not set
+# CONFIG_ASYMMETRIC_KEY_TYPE is not set
+
+#
+# Certificates for signature checking
+#
+# CONFIG_ARM_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_HAVE_ARCH_BITREVERSE=y
+CONFIG_RATIONAL=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_NET_UTILS=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IO=y
+CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=y
+# CONFIG_CRC8 is not set
+# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set
+# CONFIG_RANDOM32_SELFTEST is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_LZ4_DECOMPRESS=y
+CONFIG_XZ_DEC=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_BCJ=y
+# CONFIG_XZ_DEC_TEST is not set
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_LZ4=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_ASSOCIATIVE_ARRAY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_HAS_DMA=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
+# CONFIG_IRQ_POLL is not set
+CONFIG_LIBFDT=y
+CONFIG_OID_REGISTRY=y
+# CONFIG_SG_SPLIT is not set
+CONFIG_SG_POOL=y
+CONFIG_ARCH_HAS_SG_CHAIN=y
+CONFIG_SBITMAP=y
+# CONFIG_VIRTUALIZATION is not set
diff -urN linux-4.9.37/arch/arm/configs/gk7205v200_mini_defconfig linux-4.9.y/arch/arm/configs/gk7205v200_mini_defconfig
--- linux-4.9.37/arch/arm/configs/gk7205v200_mini_defconfig 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/arch/arm/configs/gk7205v200_mini_defconfig 2021-06-07 13:01:32.000000000 +0300
@@ -0,0 +1,2050 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/arm 4.9.37 Kernel Configuration
+#
+CONFIG_ARM=y
+CONFIG_ARM_HAS_SG_CHAIN=y
+CONFIG_MIGHT_HAVE_PCI=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_ARM_PATCH_PHYS_VIRT=y
+CONFIG_GENERIC_BUG=y
+CONFIG_PGTABLE_LEVELS=2
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_IRQ_WORK=y
+CONFIG_BUILDTIME_EXTABLE_SORT=y
+
+#
+# General setup
+#
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+# CONFIG_COMPILE_TEST is not set
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_HAVE_KERNEL_LZ4=y
+# CONFIG_KERNEL_GZIP is not set
+# CONFIG_KERNEL_LZMA is not set
+CONFIG_KERNEL_XZ=y
+# CONFIG_KERNEL_LZO is not set
+# CONFIG_KERNEL_LZ4 is not set
+CONFIG_DEFAULT_HOSTNAME="(none)"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_CROSS_MEMORY_ATTACH=y
+CONFIG_FHANDLE=y
+CONFIG_USELIB=y
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_ARCH_AUDITSYSCALL=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_IRQ_DOMAIN_HIERARCHY=y
+CONFIG_HANDLE_DOMAIN_IRQ=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_ARCH_CLOCKSOURCE_DATA=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+
+#
+# Timers subsystem
+#
+CONFIG_HZ_PERIODIC=y
+# CONFIG_NO_HZ_IDLE is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set
+# CONFIG_IRQ_TIME_ACCOUNTING is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TINY_RCU=y
+# CONFIG_RCU_EXPERT is not set
+CONFIG_SRCU=y
+# CONFIG_TASKS_RCU is not set
+# CONFIG_RCU_STALL_COMMON is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_RCU_EXPEDITE_BOOT is not set
+# CONFIG_BUILD_BIN2C is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_NMI_LOG_BUF_SHIFT=13
+CONFIG_GENERIC_SCHED_CLOCK=y
+CONFIG_CGROUPS=y
+# CONFIG_MEMCG is not set
+# CONFIG_BLK_CGROUP is not set
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUP_PIDS is not set
+# CONFIG_CGROUP_FREEZER is not set
+# CONFIG_CPUSETS is not set
+# CONFIG_CGROUP_DEVICE is not set
+# CONFIG_CGROUP_CPUACCT is not set
+# CONFIG_CGROUP_DEBUG is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+CONFIG_NAMESPACES=y
+CONFIG_UTS_NS=y
+CONFIG_IPC_NS=y
+# CONFIG_USER_NS is not set
+CONFIG_PID_NS=y
+CONFIG_NET_NS=y
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_HAVE_UID16=y
+CONFIG_BPF=y
+# CONFIG_EXPERT is not set
+CONFIG_UID16=y
+CONFIG_MULTIUSER=y
+# CONFIG_SGETMASK_SYSCALL is not set
+CONFIG_SYSFS_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set
+CONFIG_KALLSYMS_BASE_RELATIVE=y
+CONFIG_PRINTK=y
+CONFIG_PRINTK_NMI=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+# CONFIG_BPF_SYSCALL is not set
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_ADVISE_SYSCALLS=y
+# CONFIG_USERFAULTFD is not set
+CONFIG_MEMBARRIER=y
+# CONFIG_EMBEDDED is not set
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLAB_FREELIST_RANDOM is not set
+# CONFIG_SYSTEM_DATA_VERIFICATION is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+# CONFIG_JUMP_LABEL is not set
+# CONFIG_UPROBES is not set
+# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_ARCH_USE_BUILTIN_BSWAP=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_NMI=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_IDLE_POLL_SETUP=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_HAVE_GCC_PLUGINS=y
+# CONFIG_GCC_PLUGINS is not set
+CONFIG_HAVE_CC_STACKPROTECTOR=y
+CONFIG_CC_STACKPROTECTOR=y
+# CONFIG_CC_STACKPROTECTOR_NONE is not set
+# CONFIG_CC_STACKPROTECTOR_REGULAR is not set
+CONFIG_CC_STACKPROTECTOR_STRONG=y
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_MODULES_USE_ELF_REL=y
+CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_HAVE_ARCH_MMAP_RND_BITS=y
+CONFIG_HAVE_EXIT_THREAD=y
+CONFIG_ARCH_MMAP_RND_BITS_MIN=8
+CONFIG_ARCH_MMAP_RND_BITS_MAX=16
+CONFIG_ARCH_MMAP_RND_BITS=8
+# CONFIG_HAVE_ARCH_HASH is not set
+# CONFIG_ISA_BUS_API is not set
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_OLD_SIGACTION=y
+# CONFIG_CPU_NO_EFFICIENT_FFS is not set
+# CONFIG_HAVE_ARCH_VMAP_STACK is not set
+
+#
+# GCOV-based kernel profiling
+#
+CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_MODULE_SIG is not set
+# CONFIG_MODULE_COMPRESS is not set
+# CONFIG_TRIM_UNUSED_KSYMS is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+CONFIG_BLK_DEV_BSG=y
+# CONFIG_BLK_DEV_BSGLIB is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+CONFIG_BLK_CMDLINE_PARSER=y
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_AIX_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_CMDLINE_PARTITION=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+CONFIG_INLINE_READ_UNLOCK=y
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+CONFIG_INLINE_WRITE_UNLOCK=y
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+CONFIG_MMU=y
+CONFIG_ARCH_MULTIPLATFORM=y
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_LPC32XX is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C24XX is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP1 is not set
+
+#
+# Multiple platform selection
+#
+
+#
+# CPU Core family selection
+#
+# CONFIG_ARCH_MULTI_V6 is not set
+CONFIG_ARCH_MULTI_V7=y
+CONFIG_ARCH_MULTI_V6_V7=y
+# CONFIG_ARCH_MULTI_CPU_AUTO is not set
+# CONFIG_ARCH_VIRT is not set
+# CONFIG_ARCH_MVEBU is not set
+# CONFIG_ARCH_ALPINE is not set
+# CONFIG_ARCH_ARTPEC is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_BCM is not set
+# CONFIG_ARCH_BERLIN is not set
+# CONFIG_ARCH_DIGICOLOR is not set
+# CONFIG_ARCH_HIGHBANK is not set
+# CONFIG_ARCH_HISI is not set
+CONFIG_ARCH_GOKE=y
+
+#
+# Goke platform type
+#
+CONFIG_ARCH_GK7205V200=y
+# CONFIG_ARCH_GK7205V300 is not set
+# CONFIG_ARCH_GK7202V300 is not set
+# CONFIG_ARCH_GK7605V100 is not set
+# CONFIG_GOKE_MC is not set
+CONFIG_BSP_ZRELADDR=0x40008000
+CONFIG_BSP_PARAMS_PHYS=0x00000100
+CONFIG_BSP_INITRD_PHYS=0x00800000
+# CONFIG_ARCH_KEYSTONE is not set
+# CONFIG_ARCH_MESON is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_MEDIATEK is not set
+
+#
+# TI OMAP/AM/DM/DRA Family
+#
+# CONFIG_ARCH_OMAP3 is not set
+# CONFIG_ARCH_OMAP4 is not set
+# CONFIG_SOC_OMAP5 is not set
+# CONFIG_SOC_AM33XX is not set
+# CONFIG_SOC_AM43XX is not set
+# CONFIG_SOC_DRA7XX is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_QCOM is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_ROCKCHIP is not set
+# CONFIG_ARCH_SOCFPGA is not set
+# CONFIG_PLAT_SPEAR is not set
+# CONFIG_ARCH_STI is not set
+# CONFIG_ARCH_S5PV210 is not set
+# CONFIG_ARCH_EXYNOS is not set
+# CONFIG_ARCH_RENESAS is not set
+# CONFIG_ARCH_SUNXI is not set
+# CONFIG_ARCH_SIRF is not set
+# CONFIG_ARCH_TANGO is not set
+# CONFIG_ARCH_TEGRA is not set
+# CONFIG_ARCH_UNIPHIER is not set
+# CONFIG_ARCH_U8500 is not set
+# CONFIG_ARCH_VEXPRESS is not set
+# CONFIG_ARCH_WM8850 is not set
+# CONFIG_ARCH_ZX is not set
+# CONFIG_ARCH_ZYNQ is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_V7=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_LPAE is not set
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+# CONFIG_ARM_THUMB is not set
+# CONFIG_ARM_THUMBEE is not set
+CONFIG_ARM_VIRT_EXT=y
+# CONFIG_SWP_EMULATE is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_KUSER_HELPERS=y
+# CONFIG_VDSO is not set
+CONFIG_MIGHT_HAVE_CACHE_L2X0=y
+# CONFIG_CACHE_L2X0 is not set
+CONFIG_ARM_L1_CACHE_SHIFT_6=y
+CONFIG_ARM_L1_CACHE_SHIFT=6
+CONFIG_ARM_DMA_MEM_BUFFERABLE=y
+# CONFIG_DEBUG_RODATA is not set
+CONFIG_MULTI_IRQ_HANDLER=y
+# CONFIG_ARM_ERRATA_430973 is not set
+# CONFIG_ARM_ERRATA_720789 is not set
+# CONFIG_ARM_ERRATA_754322 is not set
+# CONFIG_ARM_ERRATA_775420 is not set
+# CONFIG_ARM_ERRATA_773022 is not set
+# CONFIG_ARM_ERRATA_818325_852422 is not set
+# CONFIG_ARM_ERRATA_821420 is not set
+# CONFIG_ARM_ERRATA_825619 is not set
+# CONFIG_ARM_ERRATA_852421 is not set
+# CONFIG_ARM_ERRATA_852423 is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS_GENERIC is not set
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_HAVE_SMP=y
+# CONFIG_SMP is not set
+CONFIG_HAVE_ARM_ARCH_TIMER=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_3G_OPT is not set
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_ARM_PSCI is not set
+CONFIG_ARCH_NR_GPIO=0
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ_FIXED=0
+CONFIG_HZ_100=y
+# CONFIG_HZ_200 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_500 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
+# CONFIG_SCHED_HRTICK is not set
+# CONFIG_THUMB2_KERNEL is not set
+# CONFIG_ARM_PATCH_IDIV is not set
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_HAVE_ARCH_PFN_VALID=y
+# CONFIG_HIGHMEM is not set
+# CONFIG_CPU_SW_DOMAIN_PAN is not set
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+# CONFIG_ARM_MODULE_PLTS is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_NO_BOOTMEM=y
+# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_COMPACTION=y
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NEED_PER_CPU_KM=y
+# CONFIG_CLEANCACHE is not set
+# CONFIG_CMA is not set
+# CONFIG_ZPOOL is not set
+# CONFIG_ZBUD is not set
+# CONFIG_ZSMALLOC is not set
+CONFIG_GENERIC_EARLY_IOREMAP=y
+# CONFIG_IDLE_PAGE_TRACKING is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+# CONFIG_SECCOMP is not set
+CONFIG_SWIOTLB=y
+CONFIG_IOMMU_HELPER=y
+# CONFIG_PARAVIRT is not set
+# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set
+# CONFIG_XEN is not set
+
+#
+# Boot options
+#
+CONFIG_USE_OF=y
+CONFIG_ATAGS=y
+# CONFIG_DEPRECATED_PARAM_STRUCT is not set
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER=y
+# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set
+CONFIG_CMDLINE=""
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_AUTO_ZRELADDR=y
+# CONFIG_EFI is not set
+
+#
+# CPU Power Management
+#
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# CPU Idle
+#
+# CONFIG_CPU_IDLE is not set
+# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+# CONFIG_KERNEL_MODE_NEON is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_ELFCORE=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
+CONFIG_BINFMT_SCRIPT=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_COREDUMP=y
+
+#
+# Power management options
+#
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_PM_SLEEP=y
+# CONFIG_PM_AUTOSLEEP is not set
+# CONFIG_PM_WAKELOCKS is not set
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_APM_EMULATION is not set
+CONFIG_PM_CLK=y
+# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_CPU_PM=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARM_CPU_SUSPEND=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+CONFIG_UNIX=y
+# CONFIG_UNIX_DIAG is not set
+# CONFIG_XFRM_USER is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
+# CONFIG_NET_IP_TUNNEL is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_NET_UDP_TUNNEL is not set
+# CONFIG_NET_FOU is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NET_PTP_CLASSIFY is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP is not set
+# CONFIG_BRIDGE is not set
+CONFIG_HAVE_NET_DSA=y
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+# CONFIG_VSOCKETS is not set
+# CONFIG_NETLINK_DIAG is not set
+# CONFIG_MPLS is not set
+# CONFIG_HSR is not set
+# CONFIG_NET_SWITCHDEV is not set
+# CONFIG_NET_L3_MASTER_DEV is not set
+# CONFIG_NET_NCSI is not set
+# CONFIG_SOCK_CGROUP_DATA is not set
+# CONFIG_CGROUP_NET_PRIO is not set
+# CONFIG_CGROUP_NET_CLASSID is not set
+CONFIG_NET_RX_BUSY_POLL=y
+CONFIG_BQL=y
+# CONFIG_BPF_JIT is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_AF_KCM is not set
+# CONFIG_STREAM_PARSER is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+# CONFIG_LWTUNNEL is not set
+# CONFIG_DST_CACHE is not set
+# CONFIG_NET_DEVLINK is not set
+CONFIG_MAY_USE_DEVLINK=y
+CONFIG_HAVE_CBPF_JIT=y
+
+#
+# Device Drivers
+#
+CONFIG_ARM_AMBA=y
+
+#
+# Generic Driver Options
+#
+# CONFIG_UEVENT_HELPER is not set
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_FW_LOADER=y
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set
+CONFIG_ALLOW_DEV_COREDUMP=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+CONFIG_REGMAP=y
+CONFIG_REGMAP_MMIO=y
+# CONFIG_DMA_SHARED_BUFFER is not set
+
+#
+# Bus devices
+#
+# CONFIG_BRCMSTB_GISB_ARB is not set
+# CONFIG_VEXPRESS_CONFIG is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+CONFIG_MTD_OF_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
+# CONFIG_MTD_OOPS is not set
+# CONFIG_MTD_PARTITIONED_MASTER is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SST25L is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOCG3 is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR & LPDDR2 PCM memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_LPDDR2_NVM is not set
+CONFIG_MTD_SPI_NOR=y
+# CONFIG_MTD_MT81xx_NOR is not set
+# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
+# CONFIG_SPI_CADENCE_QUADSPI is not set
+# CONFIG_SPI_GOKE_SFC is not set
+CONFIG_CLOSE_SPI_8PIN_4IO=y
+# CONFIG_MTD_UBI is not set
+CONFIG_DTC=y
+CONFIG_OF=y
+# CONFIG_OF_UNITTEST is not set
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_NET=y
+CONFIG_OF_MDIO=y
+CONFIG_OF_RESERVED_MEM=y
+# CONFIG_OF_OVERLAY is not set
+CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_NULL_BLK is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_DRBD is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=65536
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_BLK_DEV_RBD is not set
+# CONFIG_NVME_TARGET is not set
+
+#
+# Misc devices
+#
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_DUMMY_IRQ is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_APDS9802ALS is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_ISL29020 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_BH1770 is not set
+# CONFIG_SENSORS_APDS990X is not set
+# CONFIG_HMC6352 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_TI_DAC7512 is not set
+# CONFIG_USB_SWITCH_FSA9480 is not set
+# CONFIG_LATTICE_ECP3_CONFIG is not set
+# CONFIG_SRAM is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_EEPROM_93XX46 is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_SENSORS_LIS3_SPI is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
+
+#
+# Altera FPGA firmware download module
+#
+# CONFIG_ALTERA_STAPL is not set
+
+#
+# Intel MIC Bus Driver
+#
+
+#
+# SCIF Bus Driver
+#
+
+#
+# VOP Bus Driver
+#
+
+#
+# Intel MIC Host Driver
+#
+
+#
+# Intel MIC Card Driver
+#
+
+#
+# SCIF Driver
+#
+
+#
+# Intel MIC Coprocessor State Management (COSM) Drivers
+#
+
+#
+# VOP Driver
+#
+# CONFIG_ECHO is not set
+# CONFIG_CXL_BASE is not set
+# CONFIG_CXL_AFU_DRIVER_OPS is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NET_CORE is not set
+
+#
+# CAIF transport drivers
+#
+
+#
+# Distributed Switch Architecture drivers
+#
+CONFIG_ETHERNET=y
+# CONFIG_ALTERA_TSE is not set
+# CONFIG_NET_VENDOR_AMAZON is not set
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_AURORA is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_DM9000 is not set
+# CONFIG_DNET is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_HISILICON is not set
+CONFIG_NET_VENDOR_GOKE=y
+CONFIG_GOKE_FEMAC=y
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
+# CONFIG_ETHOC is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_PHYLIB=y
+CONFIG_SWPHY=y
+
+#
+# MDIO bus device drivers
+#
+# CONFIG_MDIO_BCM_UNIMAC is not set
+# CONFIG_MDIO_BITBANG is not set
+# CONFIG_MDIO_BUS_MUX_MMIOREG is not set
+CONFIG_MDIO_GOKE_FEMAC=y
+# CONFIG_MDIO_HISI_FEMAC is not set
+
+#
+# MII PHY device drivers
+#
+# CONFIG_AMD_PHY is not set
+# CONFIG_AQUANTIA_PHY is not set
+# CONFIG_AT803X_PHY is not set
+# CONFIG_BCM7XXX_PHY is not set
+# CONFIG_BCM87XX_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_DP83848_PHY is not set
+# CONFIG_DP83867_PHY is not set
+CONFIG_FIXED_PHY=y
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_INTEL_XWAY_PHY is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_MICREL_PHY is not set
+# CONFIG_MICROCHIP_PHY is not set
+# CONFIG_MICROSEMI_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_TERANETICS_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_XILINX_GMII2RGMII is not set
+# CONFIG_MICREL_KS8995MA is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Host-side USB support is needed for USB Network Adapter support
+#
+# CONFIG_WLAN is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_ISDN is not set
+# CONFIG_NVM is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+# CONFIG_INPUT_MATRIXKMAP is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+# CONFIG_RMI4_CORE is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_TTY=y
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_VT_CONSOLE_SLEEP=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVMEM=y
+# CONFIG_DEVKMEM is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_EARLYCON=y
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_AMBA_PL010 is not set
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set
+# CONFIG_SERIAL_MAX3100 is not set
+# CONFIG_SERIAL_MAX310X is not set
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_SCCNXP is not set
+# CONFIG_SERIAL_SC16IS7XX is not set
+# CONFIG_SERIAL_BCM63XX is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_XILINX_PS_UART is not set
+# CONFIG_SERIAL_ARC is not set
+# CONFIG_SERIAL_FSL_LPUART is not set
+# CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set
+# CONFIG_SERIAL_ST_ASC is not set
+# CONFIG_SERIAL_STM32 is not set
+# CONFIG_HVC_DCC is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_XILLYBUS is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MUX=y
+
+#
+# Multiplexer I2C Chip support
+#
+# CONFIG_I2C_MUX_PCA9541 is not set
+# CONFIG_I2C_MUX_PINCTRL is not set
+# CONFIG_I2C_MUX_REG is not set
+# CONFIG_I2C_DEMUX_PINCTRL is not set
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_DESIGNWARE_PLATFORM is not set
+# CONFIG_I2C_EMEV2 is not set
+CONFIG_I2C_GOKE=y
+# CONFIG_I2C_NOMADIK is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_PXA_PCI is not set
+# CONFIG_I2C_RK3X is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+CONFIG_DMA_MSG_MIN_LEN=5
+CONFIG_DMA_MSG_MAX_LEN=4090
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_SLAVE is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_ALTERA is not set
+# CONFIG_SPI_AXI_SPI_ENGINE is not set
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_CADENCE is not set
+# CONFIG_SPI_DESIGNWARE is not set
+# CONFIG_SPI_FSL_SPI is not set
+CONFIG_SPI_PL022=y
+# CONFIG_SPI_PXA2XX_PCI is not set
+# CONFIG_SPI_ROCKCHIP is not set
+# CONFIG_SPI_SC18IS602 is not set
+# CONFIG_SPI_XCOMM is not set
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_ZYNQMP_GQSPI is not set
+
+#
+# SPI Protocol Masters
+#
+CONFIG_SPI_SPIDEV=y
+# CONFIG_SPI_LOOPBACK_TEST is not set
+# CONFIG_SPI_TLE62X0 is not set
+# CONFIG_SPMI is not set
+# CONFIG_HSI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+# CONFIG_PTP_1588_CLOCK is not set
+
+#
+# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
+#
+CONFIG_PINCTRL=y
+
+#
+# Pin controllers
+#
+# CONFIG_DEBUG_PINCTRL is not set
+# CONFIG_PINCTRL_SINGLE is not set
+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
+# CONFIG_GPIOLIB is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_AVS is not set
+CONFIG_POWER_RESET=y
+# CONFIG_POWER_RESET_BRCMKONA is not set
+# CONFIG_POWER_RESET_BRCMSTB is not set
+CONFIG_POWER_RESET_GOKE=y
+# CONFIG_POWER_RESET_RESTART is not set
+# CONFIG_POWER_RESET_VERSATILE is not set
+# CONFIG_POWER_RESET_SYSCON is not set
+# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set
+# CONFIG_SYSCON_REBOOT_MODE is not set
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_TEST_POWER is not set
+# CONFIG_BATTERY_DS2780 is not set
+# CONFIG_BATTERY_DS2781 is not set
+# CONFIG_BATTERY_DS2782 is not set
+# CONFIG_BATTERY_SBS is not set
+# CONFIG_BATTERY_BQ27XXX is not set
+# CONFIG_BATTERY_MAX17040 is not set
+# CONFIG_BATTERY_MAX17042 is not set
+# CONFIG_CHARGER_MAX8903 is not set
+# CONFIG_CHARGER_LP8727 is not set
+# CONFIG_CHARGER_BQ2415X is not set
+# CONFIG_CHARGER_SMB347 is not set
+# CONFIG_BATTERY_GAUGE_LTC2941 is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_ACT8945A is not set
+# CONFIG_MFD_AS3711 is not set
+# CONFIG_MFD_AS3722 is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_ATMEL_FLEXCOM is not set
+# CONFIG_MFD_ATMEL_HLCDC is not set
+# CONFIG_MFD_BCM590XX is not set
+# CONFIG_MFD_AXP20X_I2C is not set
+# CONFIG_MFD_CROS_EC is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_DA9052_SPI is not set
+# CONFIG_MFD_DA9052_I2C is not set
+# CONFIG_MFD_DA9055 is not set
+# CONFIG_MFD_DA9062 is not set
+# CONFIG_MFD_DA9063 is not set
+# CONFIG_MFD_DA9150 is not set
+# CONFIG_MFD_EXYNOS_LPASS is not set
+# CONFIG_MFD_MC13XXX_SPI is not set
+# CONFIG_MFD_MC13XXX_I2C is not set
+# CONFIG_MFD_HI6421_PMIC is not set
+# CONFIG_MFD_GOKE_FMC is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_KEMPLD is not set
+# CONFIG_MFD_88PM800 is not set
+# CONFIG_MFD_88PM805 is not set
+# CONFIG_MFD_88PM860X is not set
+# CONFIG_MFD_MAX14577 is not set
+# CONFIG_MFD_MAX77620 is not set
+# CONFIG_MFD_MAX77686 is not set
+# CONFIG_MFD_MAX77693 is not set
+# CONFIG_MFD_MAX77843 is not set
+# CONFIG_MFD_MAX8907 is not set
+# CONFIG_MFD_MAX8925 is not set
+# CONFIG_MFD_MAX8997 is not set
+# CONFIG_MFD_MAX8998 is not set
+# CONFIG_MFD_MT6397 is not set
+# CONFIG_MFD_MENF21BMC is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_MFD_RETU is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_PM8921_CORE is not set
+# CONFIG_MFD_RT5033 is not set
+# CONFIG_MFD_RC5T583 is not set
+# CONFIG_MFD_RK808 is not set
+# CONFIG_MFD_RN5T618 is not set
+# CONFIG_MFD_SEC_CORE is not set
+# CONFIG_MFD_SI476X_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_SKY81452 is not set
+# CONFIG_MFD_SMSC is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_MFD_STMPE is not set
+CONFIG_MFD_SYSCON=y
+# CONFIG_MFD_TI_AM335X_TSCADC is not set
+# CONFIG_MFD_LP3943 is not set
+# CONFIG_MFD_LP8788 is not set
+# CONFIG_MFD_PALMAS is not set
+# CONFIG_TPS6105X is not set
+# CONFIG_TPS6507X is not set
+# CONFIG_MFD_TPS65086 is not set
+# CONFIG_MFD_TPS65090 is not set
+# CONFIG_MFD_TPS65217 is not set
+# CONFIG_MFD_TI_LP873X is not set
+# CONFIG_MFD_TPS65218 is not set
+# CONFIG_MFD_TPS6586X is not set
+# CONFIG_MFD_TPS65912_I2C is not set
+# CONFIG_MFD_TPS65912_SPI is not set
+# CONFIG_MFD_TPS80031 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_TWL6040_CORE is not set
+# CONFIG_MFD_WL1273_CORE is not set
+# CONFIG_MFD_LM3533 is not set
+# CONFIG_MFD_TC3589X is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_MFD_ARIZONA_I2C is not set
+# CONFIG_MFD_ARIZONA_SPI is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X_I2C is not set
+# CONFIG_MFD_WM831X_SPI is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8994 is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_IMX_IPUV3_CORE is not set
+# CONFIG_DRM is not set
+
+#
+# ACP (Audio CoProcessor) Configuration
+#
+
+#
+# Frame buffer Devices
+#
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB_CMDLINE=y
+CONFIG_FB_NOTIFY=y
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_ARMCLCD is not set
+# CONFIG_FB_OPENCORES is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_IBM_GXT4500 is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_FB_AUO_K190X is not set
+# CONFIG_FB_SIMPLE is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+# CONFIG_LOGO is not set
+# CONFIG_SOUND is not set
+
+#
+# HID support
+#
+# CONFIG_HID is not set
+
+#
+# I2C HID support
+#
+# CONFIG_I2C_HID is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_UWB is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_EDAC_ATOMIC_SCRUB=y
+CONFIG_EDAC_SUPPORT=y
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+
+#
+# DMABUF options
+#
+# CONFIG_SYNC_FILE is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+# CONFIG_VIRT_DRIVERS is not set
+
+#
+# Virtio drivers
+#
+# CONFIG_VIRTIO_MMIO is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_STAGING is not set
+# CONFIG_GOLDFISH is not set
+# CONFIG_CHROME_PLATFORMS is not set
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_COMMON_CLK=y
+
+#
+# Common Clock Framework
+#
+# CONFIG_COMMON_CLK_SI5351 is not set
+# CONFIG_COMMON_CLK_SI514 is not set
+# CONFIG_COMMON_CLK_SI570 is not set
+# CONFIG_COMMON_CLK_CDCE706 is not set
+# CONFIG_COMMON_CLK_CDCE925 is not set
+# CONFIG_COMMON_CLK_CS2000_CP is not set
+# CONFIG_CLK_QORIQ is not set
+# CONFIG_COMMON_CLK_NXP is not set
+# CONFIG_COMMON_CLK_PXA is not set
+# CONFIG_COMMON_CLK_PIC32 is not set
+CONFIG_COMMON_CLK_GK7205V200=y
+CONFIG_RESET_GOKE=y
+
+#
+# Hardware Spinlock drivers
+#
+
+#
+# Clock Source drivers
+#
+CONFIG_CLKSRC_OF=y
+CONFIG_CLKSRC_PROBE=y
+CONFIG_CLKSRC_MMIO=y
+CONFIG_ARM_ARCH_TIMER=y
+# CONFIG_ARM_ARCH_TIMER_EVTSTREAM is not set
+# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS is not set
+CONFIG_ARM_TIMER_SP804=y
+# CONFIG_ATMEL_PIT is not set
+# CONFIG_SH_TIMER_CMT is not set
+# CONFIG_SH_TIMER_MTU2 is not set
+# CONFIG_SH_TIMER_TMU is not set
+# CONFIG_EM_TIMER_STI is not set
+# CONFIG_MAILBOX is not set
+# CONFIG_IOMMU_SUPPORT is not set
+
+#
+# Remoteproc drivers
+#
+# CONFIG_STE_MODEM_RPROC is not set
+
+#
+# Rpmsg drivers
+#
+
+#
+# SOC (System On Chip) specific Drivers
+#
+
+#
+# Broadcom SoC drivers
+#
+# CONFIG_SOC_BRCMSTB is not set
+# CONFIG_SUNXI_SRAM is not set
+# CONFIG_SOC_TI is not set
+# CONFIG_PM_DEVFREQ is not set
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
+# CONFIG_IIO is not set
+# CONFIG_PWM is not set
+CONFIG_IRQCHIP=y
+CONFIG_ARM_GIC=y
+CONFIG_ARM_GIC_MAX_NR=1
+# CONFIG_IPACK_BUS is not set
+CONFIG_RESET_CONTROLLER=y
+# CONFIG_RESET_ATH79 is not set
+# CONFIG_RESET_BERLIN is not set
+# CONFIG_RESET_LPC18XX is not set
+# CONFIG_RESET_MESON is not set
+# CONFIG_RESET_PISTACHIO is not set
+# CONFIG_RESET_SOCFPGA is not set
+# CONFIG_RESET_STM32 is not set
+# CONFIG_RESET_SUNXI is not set
+# CONFIG_TI_SYSCON_RESET is not set
+# CONFIG_RESET_ZYNQ is not set
+# CONFIG_FMC is not set
+
+#
+# PHY Subsystem
+#
+# CONFIG_GENERIC_PHY is not set
+# CONFIG_PHY_PXA_28NM_HSIC is not set
+# CONFIG_PHY_PXA_28NM_USB2 is not set
+# CONFIG_BCM_KONA_USB2_PHY is not set
+# CONFIG_PHY_GOKE_USBP2 is not set
+# CONFIG_USB_MODE_OPTION is not set
+# CONFIG_POWERCAP is not set
+# CONFIG_MCB is not set
+
+#
+# Performance monitor support
+#
+# CONFIG_RAS is not set
+
+#
+# Android
+#
+# CONFIG_ANDROID is not set
+# CONFIG_NVMEM is not set
+# CONFIG_STM is not set
+# CONFIG_INTEL_TH is not set
+
+#
+# FPGA Configuration Support
+#
+# CONFIG_FPGA is not set
+
+#
+# goke driver support
+#
+
+#
+# Firmware Drivers
+#
+# CONFIG_FIRMWARE_MEMMAP is not set
+# CONFIG_FW_CFG_SYSFS is not set
+CONFIG_HAVE_ARM_SMCCC=y
+
+#
+# File systems
+#
+CONFIG_DCACHE_WORD_ACCESS=y
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+# CONFIG_F2FS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_EXPORTFS=y
+# CONFIG_EXPORTFS_BLOCK_OPS is not set
+CONFIG_FILE_LOCKING=y
+# CONFIG_MANDATORY_FILE_LOCKING is not set
+# CONFIG_FS_ENCRYPTION is not set
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_QUOTACTL is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+# CONFIG_OVERLAY_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_PROC_CHILDREN is not set
+CONFIG_KERNFS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=y
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ORANGEFS_FS is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_YAFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+# CONFIG_JFFS2_LZMA is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_LOGFS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX6FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_PSTORE is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD is not set
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_MAC_ROMAN is not set
+# CONFIG_NLS_MAC_CELTIC is not set
+# CONFIG_NLS_MAC_CENTEURO is not set
+# CONFIG_NLS_MAC_CROATIAN is not set
+# CONFIG_NLS_MAC_CYRILLIC is not set
+# CONFIG_NLS_MAC_GAELIC is not set
+# CONFIG_NLS_MAC_GREEK is not set
+# CONFIG_NLS_MAC_ICELAND is not set
+# CONFIG_NLS_MAC_INUIT is not set
+# CONFIG_NLS_MAC_ROMANIAN is not set
+# CONFIG_NLS_MAC_TURKISH is not set
+# CONFIG_NLS_UTF8 is not set
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+
+#
+# printk and dmesg options
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
+# CONFIG_BOOT_PRINTK_DELAY is not set
+
+#
+# Compile-time checks and compiler options
+#
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_READABLE_ASM is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_PAGE_OWNER is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_SECTION_MISMATCH_WARN_ONLY=y
+CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_DEBUG_KERNEL=y
+
+#
+# Memory Debugging
+#
+# CONFIG_PAGE_EXTENSION is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_PAGE_POISONING is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_SHIRQ is not set
+
+#
+# Debug Lockups and Hangs
+#
+# CONFIG_LOCKUP_DETECTOR is not set
+# CONFIG_DETECT_HUNG_TASK is not set
+# CONFIG_WQ_WATCHDOG is not set
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+CONFIG_PANIC_TIMEOUT=0
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHED_INFO is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_SCHED_STACK_END_CHECK is not set
+# CONFIG_DEBUG_TIMEKEEPING is not set
+# CONFIG_TIMER_STATS is not set
+
+#
+# Lock Debugging (spinlocks, mutexes, etc...)
+#
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_ATOMIC_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_LOCK_TORTURE_TEST is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_PI_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+
+#
+# RCU Debugging
+#
+# CONFIG_PROVE_RCU is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_TORTURE_TEST is not set
+# CONFIG_RCU_PERF_TEST is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_TRACE is not set
+# CONFIG_RCU_EQS_DEBUG is not set
+# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_NOTIFIER_ERROR_INJECTION is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+
+#
+# Runtime Testing
+#
+# CONFIG_TEST_LIST_SORT is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_RBTREE_TEST is not set
+# CONFIG_INTERVAL_TREE_TEST is not set
+# CONFIG_PERCPU_TEST is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_TEST_HEXDUMP is not set
+# CONFIG_TEST_STRING_HELPERS is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_TEST_PRINTF is not set
+# CONFIG_TEST_BITMAP is not set
+# CONFIG_TEST_UUID is not set
+# CONFIG_TEST_RHASHTABLE is not set
+# CONFIG_TEST_HASH is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_TEST_LKM is not set
+# CONFIG_TEST_USER_COPY is not set
+# CONFIG_TEST_BPF is not set
+# CONFIG_TEST_FIRMWARE is not set
+# CONFIG_TEST_UDELAY is not set
+# CONFIG_MEMTEST is not set
+# CONFIG_TEST_STATIC_KEYS is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set
+# CONFIG_UBSAN is not set
+CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
+CONFIG_STRICT_DEVMEM=y
+# CONFIG_IO_STRICT_DEVMEM is not set
+# CONFIG_ARM_PTDUMP is not set
+# CONFIG_ARM_UNWIND is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_LL is not set
+CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
+# CONFIG_DEBUG_UART_8250 is not set
+CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
+# CONFIG_PID_IN_CONTEXTIDR is not set
+# CONFIG_DEBUG_SET_MODULE_RONX is not set
+# CONFIG_CORESIGHT is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y
+CONFIG_HAVE_ARCH_HARDENED_USERCOPY=y
+# CONFIG_HARDENED_USERCOPY is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+# CONFIG_CRYPTO_RSA is not set
+# CONFIG_CRYPTO_DH is not set
+# CONFIG_CRYPTO_ECDH is not set
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
+# CONFIG_CRYPTO_USER is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_MCRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_CHACHA20POLY1305 is not set
+# CONFIG_CRYPTO_SEQIV is not set
+# CONFIG_CRYPTO_ECHAINIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+# CONFIG_CRYPTO_KEYWRAP is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_CMAC is not set
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_CRC32 is not set
+CONFIG_CRYPTO_CRCT10DIF=y
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_POLY1305 is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_SHA3 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_CHACHA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+# CONFIG_CRYPTO_842 is not set
+# CONFIG_CRYPTO_LZ4 is not set
+# CONFIG_CRYPTO_LZ4HC is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_DRBG_MENU is not set
+# CONFIG_CRYPTO_JITTERENTROPY is not set
+# CONFIG_CRYPTO_USER_API_HASH is not set
+# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
+# CONFIG_CRYPTO_USER_API_RNG is not set
+# CONFIG_CRYPTO_USER_API_AEAD is not set
+# CONFIG_CRYPTO_HW is not set
+
+#
+# Certificates for signature checking
+#
+# CONFIG_ARM_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_HAVE_ARCH_BITREVERSE=y
+CONFIG_RATIONAL=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_NET_UTILS=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IO=y
+CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+# CONFIG_CRC8 is not set
+# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set
+# CONFIG_RANDOM32_SELFTEST is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_XZ_DEC=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_BCJ=y
+# CONFIG_XZ_DEC_TEST is not set
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_HAS_DMA=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
+# CONFIG_IRQ_POLL is not set
+CONFIG_LIBFDT=y
+# CONFIG_SG_SPLIT is not set
+# CONFIG_SG_POOL is not set
+CONFIG_ARCH_HAS_SG_CHAIN=y
+CONFIG_SBITMAP=y
+# CONFIG_VIRTUALIZATION is not set
diff -urN linux-4.9.37/arch/arm/configs/gk7205v300_emmc_defconfig linux-4.9.y/arch/arm/configs/gk7205v300_emmc_defconfig
--- linux-4.9.37/arch/arm/configs/gk7205v300_emmc_defconfig 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/arch/arm/configs/gk7205v300_emmc_defconfig 2021-06-07 13:01:32.000000000 +0300
@@ -0,0 +1,2975 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/arm 4.9.37 Kernel Configuration
+#
+CONFIG_ARM=y
+CONFIG_ARM_HAS_SG_CHAIN=y
+CONFIG_MIGHT_HAVE_PCI=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_ARM_PATCH_PHYS_VIRT=y
+CONFIG_GENERIC_BUG=y
+CONFIG_PGTABLE_LEVELS=2
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_IRQ_WORK=y
+CONFIG_BUILDTIME_EXTABLE_SORT=y
+
+#
+# General setup
+#
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+# CONFIG_COMPILE_TEST is not set
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_HAVE_KERNEL_LZ4=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_XZ is not set
+# CONFIG_KERNEL_LZO is not set
+# CONFIG_KERNEL_LZ4 is not set
+CONFIG_DEFAULT_HOSTNAME="(none)"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_CROSS_MEMORY_ATTACH=y
+CONFIG_FHANDLE=y
+CONFIG_USELIB=y
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_ARCH_AUDITSYSCALL=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_IRQ_DOMAIN_HIERARCHY=y
+CONFIG_HANDLE_DOMAIN_IRQ=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_ARCH_CLOCKSOURCE_DATA=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+
+#
+# Timers subsystem
+#
+CONFIG_HZ_PERIODIC=y
+# CONFIG_NO_HZ_IDLE is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set
+# CONFIG_IRQ_TIME_ACCOUNTING is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TINY_RCU=y
+# CONFIG_RCU_EXPERT is not set
+CONFIG_SRCU=y
+# CONFIG_TASKS_RCU is not set
+# CONFIG_RCU_STALL_COMMON is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_RCU_EXPEDITE_BOOT is not set
+# CONFIG_BUILD_BIN2C is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_NMI_LOG_BUF_SHIFT=13
+CONFIG_GENERIC_SCHED_CLOCK=y
+CONFIG_CGROUPS=y
+# CONFIG_MEMCG is not set
+# CONFIG_BLK_CGROUP is not set
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUP_PIDS is not set
+CONFIG_CGROUP_FREEZER=y
+# CONFIG_CPUSETS is not set
+# CONFIG_CGROUP_DEVICE is not set
+# CONFIG_CGROUP_CPUACCT is not set
+# CONFIG_CGROUP_DEBUG is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+CONFIG_NAMESPACES=y
+CONFIG_UTS_NS=y
+CONFIG_IPC_NS=y
+# CONFIG_USER_NS is not set
+CONFIG_PID_NS=y
+CONFIG_NET_NS=y
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_RD_XZ is not set
+# CONFIG_RD_LZO is not set
+CONFIG_RD_LZ4=y
+CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_HAVE_UID16=y
+CONFIG_BPF=y
+# CONFIG_EXPERT is not set
+CONFIG_UID16=y
+CONFIG_MULTIUSER=y
+# CONFIG_SGETMASK_SYSCALL is not set
+CONFIG_SYSFS_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set
+CONFIG_KALLSYMS_BASE_RELATIVE=y
+CONFIG_PRINTK=y
+CONFIG_PRINTK_NMI=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+# CONFIG_BPF_SYSCALL is not set
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_ADVISE_SYSCALLS=y
+# CONFIG_USERFAULTFD is not set
+CONFIG_MEMBARRIER=y
+# CONFIG_EMBEDDED is not set
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLAB_FREELIST_RANDOM is not set
+# CONFIG_SYSTEM_DATA_VERIFICATION is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+# CONFIG_JUMP_LABEL is not set
+# CONFIG_UPROBES is not set
+# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_ARCH_USE_BUILTIN_BSWAP=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_NMI=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_IDLE_POLL_SETUP=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_HAVE_GCC_PLUGINS=y
+# CONFIG_GCC_PLUGINS is not set
+CONFIG_HAVE_CC_STACKPROTECTOR=y
+CONFIG_CC_STACKPROTECTOR=y
+# CONFIG_CC_STACKPROTECTOR_NONE is not set
+# CONFIG_CC_STACKPROTECTOR_REGULAR is not set
+CONFIG_CC_STACKPROTECTOR_STRONG=y
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_MODULES_USE_ELF_REL=y
+CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_HAVE_ARCH_MMAP_RND_BITS=y
+CONFIG_HAVE_EXIT_THREAD=y
+CONFIG_ARCH_MMAP_RND_BITS_MIN=8
+CONFIG_ARCH_MMAP_RND_BITS_MAX=16
+CONFIG_ARCH_MMAP_RND_BITS=8
+# CONFIG_HAVE_ARCH_HASH is not set
+# CONFIG_ISA_BUS_API is not set
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_OLD_SIGACTION=y
+# CONFIG_CPU_NO_EFFICIENT_FFS is not set
+# CONFIG_HAVE_ARCH_VMAP_STACK is not set
+
+#
+# GCOV-based kernel profiling
+#
+CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_MODULE_SIG is not set
+# CONFIG_MODULE_COMPRESS is not set
+# CONFIG_TRIM_UNUSED_KSYMS is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+CONFIG_BLK_DEV_BSG=y
+# CONFIG_BLK_DEV_BSGLIB is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+CONFIG_BLK_CMDLINE_PARSER=y
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_AIX_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_CMDLINE_PARTITION=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+CONFIG_INLINE_READ_UNLOCK=y
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+CONFIG_INLINE_WRITE_UNLOCK=y
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+CONFIG_MMU=y
+CONFIG_ARCH_MULTIPLATFORM=y
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_LPC32XX is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C24XX is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP1 is not set
+
+#
+# Multiple platform selection
+#
+
+#
+# CPU Core family selection
+#
+# CONFIG_ARCH_MULTI_V6 is not set
+CONFIG_ARCH_MULTI_V7=y
+CONFIG_ARCH_MULTI_V6_V7=y
+# CONFIG_ARCH_MULTI_CPU_AUTO is not set
+# CONFIG_ARCH_VIRT is not set
+# CONFIG_ARCH_MVEBU is not set
+# CONFIG_ARCH_ALPINE is not set
+# CONFIG_ARCH_ARTPEC is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_BCM is not set
+# CONFIG_ARCH_BERLIN is not set
+# CONFIG_ARCH_DIGICOLOR is not set
+# CONFIG_ARCH_HIGHBANK is not set
+# CONFIG_ARCH_HISI is not set
+CONFIG_ARCH_GOKE=y
+
+#
+# Goke platform type
+#
+# CONFIG_ARCH_GK7205V200 is not set
+CONFIG_ARCH_GK7205V300=y
+# CONFIG_ARCH_GK7202V300 is not set
+# CONFIG_ARCH_GK7605V100 is not set
+# CONFIG_GOKE_MC is not set
+CONFIG_BSP_ZRELADDR=0x40008000
+CONFIG_BSP_PARAMS_PHYS=0x00000100
+CONFIG_BSP_INITRD_PHYS=0x00800000
+# CONFIG_ARCH_KEYSTONE is not set
+# CONFIG_ARCH_MESON is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_MEDIATEK is not set
+
+#
+# TI OMAP/AM/DM/DRA Family
+#
+# CONFIG_ARCH_OMAP3 is not set
+# CONFIG_ARCH_OMAP4 is not set
+# CONFIG_SOC_OMAP5 is not set
+# CONFIG_SOC_AM33XX is not set
+# CONFIG_SOC_AM43XX is not set
+# CONFIG_SOC_DRA7XX is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_QCOM is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_ROCKCHIP is not set
+# CONFIG_ARCH_SOCFPGA is not set
+# CONFIG_PLAT_SPEAR is not set
+# CONFIG_ARCH_STI is not set
+# CONFIG_ARCH_S5PV210 is not set
+# CONFIG_ARCH_EXYNOS is not set
+# CONFIG_ARCH_RENESAS is not set
+# CONFIG_ARCH_SUNXI is not set
+# CONFIG_ARCH_SIRF is not set
+# CONFIG_ARCH_TANGO is not set
+# CONFIG_ARCH_TEGRA is not set
+# CONFIG_ARCH_UNIPHIER is not set
+# CONFIG_ARCH_U8500 is not set
+# CONFIG_ARCH_VEXPRESS is not set
+# CONFIG_ARCH_WM8850 is not set
+# CONFIG_ARCH_ZX is not set
+# CONFIG_ARCH_ZYNQ is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_V7=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_LPAE is not set
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+CONFIG_ARM_THUMB=y
+# CONFIG_ARM_THUMBEE is not set
+CONFIG_ARM_VIRT_EXT=y
+# CONFIG_SWP_EMULATE is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_KUSER_HELPERS=y
+CONFIG_VDSO=y
+CONFIG_MIGHT_HAVE_CACHE_L2X0=y
+# CONFIG_CACHE_L2X0 is not set
+CONFIG_ARM_L1_CACHE_SHIFT_6=y
+CONFIG_ARM_L1_CACHE_SHIFT=6
+CONFIG_ARM_DMA_MEM_BUFFERABLE=y
+# CONFIG_DEBUG_RODATA is not set
+CONFIG_MULTI_IRQ_HANDLER=y
+# CONFIG_ARM_ERRATA_430973 is not set
+# CONFIG_ARM_ERRATA_720789 is not set
+# CONFIG_ARM_ERRATA_754322 is not set
+# CONFIG_ARM_ERRATA_775420 is not set
+# CONFIG_ARM_ERRATA_773022 is not set
+# CONFIG_ARM_ERRATA_818325_852422 is not set
+# CONFIG_ARM_ERRATA_821420 is not set
+# CONFIG_ARM_ERRATA_825619 is not set
+# CONFIG_ARM_ERRATA_852421 is not set
+# CONFIG_ARM_ERRATA_852423 is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS_GENERIC is not set
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_HAVE_SMP=y
+# CONFIG_SMP is not set
+CONFIG_HAVE_ARM_ARCH_TIMER=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_3G_OPT is not set
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_ARM_PSCI is not set
+CONFIG_ARCH_NR_GPIO=0
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ_FIXED=0
+CONFIG_HZ_100=y
+# CONFIG_HZ_200 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_500 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
+# CONFIG_SCHED_HRTICK is not set
+# CONFIG_THUMB2_KERNEL is not set
+CONFIG_ARM_PATCH_IDIV=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_HAVE_ARCH_PFN_VALID=y
+# CONFIG_HIGHMEM is not set
+# CONFIG_CPU_SW_DOMAIN_PAN is not set
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+# CONFIG_ARM_MODULE_PLTS is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_NO_BOOTMEM=y
+# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_COMPACTION=y
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NEED_PER_CPU_KM=y
+# CONFIG_CLEANCACHE is not set
+# CONFIG_CMA is not set
+# CONFIG_ZPOOL is not set
+# CONFIG_ZBUD is not set
+# CONFIG_ZSMALLOC is not set
+CONFIG_GENERIC_EARLY_IOREMAP=y
+# CONFIG_IDLE_PAGE_TRACKING is not set
+CONFIG_FRAME_VECTOR=y
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+# CONFIG_SECCOMP is not set
+CONFIG_SWIOTLB=y
+CONFIG_IOMMU_HELPER=y
+# CONFIG_PARAVIRT is not set
+# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set
+# CONFIG_XEN is not set
+
+#
+# Boot options
+#
+CONFIG_USE_OF=y
+CONFIG_ATAGS=y
+# CONFIG_DEPRECATED_PARAM_STRUCT is not set
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER=y
+# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set
+CONFIG_CMDLINE=""
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_AUTO_ZRELADDR=y
+# CONFIG_EFI is not set
+
+#
+# CPU Power Management
+#
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# CPU Idle
+#
+# CONFIG_CPU_IDLE is not set
+# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+# CONFIG_KERNEL_MODE_NEON is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_ELFCORE=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
+CONFIG_BINFMT_SCRIPT=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_COREDUMP=y
+
+#
+# Power management options
+#
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_PM_SLEEP=y
+# CONFIG_PM_AUTOSLEEP is not set
+# CONFIG_PM_WAKELOCKS is not set
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_APM_EMULATION is not set
+CONFIG_PM_CLK=y
+# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_CPU_PM=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARM_CPU_SUSPEND=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_DIAG is not set
+CONFIG_UNIX=y
+# CONFIG_UNIX_DIAG is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_ALGO=y
+CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+# CONFIG_IP_FIB_TRIE_STATS is not set
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
+# CONFIG_NET_IP_TUNNEL is not set
+CONFIG_IP_MROUTE=y
+# CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_NET_UDP_TUNNEL is not set
+# CONFIG_NET_FOU is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_INET_UDP_DIAG is not set
+# CONFIG_INET_DIAG_DESTROY is not set
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BIC=m
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+# CONFIG_TCP_CONG_HSTCP is not set
+# CONFIG_TCP_CONG_HYBLA is not set
+# CONFIG_TCP_CONG_VEGAS is not set
+# CONFIG_TCP_CONG_NV is not set
+# CONFIG_TCP_CONG_SCALABLE is not set
+# CONFIG_TCP_CONG_LP is not set
+# CONFIG_TCP_CONG_VENO is not set
+# CONFIG_TCP_CONG_YEAH is not set
+# CONFIG_TCP_CONG_ILLINOIS is not set
+# CONFIG_TCP_CONG_DCTCP is not set
+# CONFIG_TCP_CONG_CDG is not set
+# CONFIG_TCP_CONG_BBR is not set
+CONFIG_DEFAULT_CUBIC=y
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NET_PTP_CLASSIFY is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP is not set
+# CONFIG_BRIDGE is not set
+CONFIG_HAVE_NET_DSA=y
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+CONFIG_DNS_RESOLVER=y
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+# CONFIG_VSOCKETS is not set
+# CONFIG_NETLINK_DIAG is not set
+# CONFIG_MPLS is not set
+# CONFIG_HSR is not set
+# CONFIG_NET_SWITCHDEV is not set
+# CONFIG_NET_L3_MASTER_DEV is not set
+# CONFIG_NET_NCSI is not set
+# CONFIG_SOCK_CGROUP_DATA is not set
+# CONFIG_CGROUP_NET_PRIO is not set
+# CONFIG_CGROUP_NET_CLASSID is not set
+CONFIG_NET_RX_BUSY_POLL=y
+CONFIG_BQL=y
+# CONFIG_BPF_JIT is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_AF_KCM is not set
+# CONFIG_STREAM_PARSER is not set
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_CFG80211=m
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+CONFIG_CFG80211_DEFAULT_PS=y
+# CONFIG_CFG80211_INTERNAL_REGDB is not set
+CONFIG_CFG80211_CRDA_SUPPORT=y
+CONFIG_CFG80211_WEXT=y
+# CONFIG_LIB80211 is not set
+CONFIG_MAC80211=m
+CONFIG_MAC80211_HAS_RC=y
+CONFIG_MAC80211_RC_MINSTREL=y
+CONFIG_MAC80211_RC_MINSTREL_HT=y
+# CONFIG_MAC80211_RC_MINSTREL_VHT is not set
+CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y
+CONFIG_MAC80211_RC_DEFAULT="minstrel_ht"
+CONFIG_MAC80211_MESH=y
+# CONFIG_MAC80211_MESSAGE_TRACING is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+CONFIG_MAC80211_STA_HASH_MAX_SIZE=0
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+# CONFIG_LWTUNNEL is not set
+# CONFIG_DST_CACHE is not set
+# CONFIG_NET_DEVLINK is not set
+CONFIG_MAY_USE_DEVLINK=y
+CONFIG_HAVE_CBPF_JIT=y
+
+#
+# Device Drivers
+#
+CONFIG_ARM_AMBA=y
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set
+CONFIG_ALLOW_DEV_COREDUMP=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+CONFIG_REGMAP=y
+CONFIG_REGMAP_I2C=y
+CONFIG_REGMAP_SPI=y
+CONFIG_REGMAP_MMIO=y
+CONFIG_DMA_SHARED_BUFFER=y
+# CONFIG_FENCE_TRACE is not set
+
+#
+# Bus devices
+#
+# CONFIG_BRCMSTB_GISB_ARB is not set
+# CONFIG_VEXPRESS_CONFIG is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+CONFIG_MTD_OF_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
+# CONFIG_MTD_OOPS is not set
+# CONFIG_MTD_PARTITIONED_MASTER is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SST25L is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOCG3 is not set
+CONFIG_MTD_NAND_ECC=y
+# CONFIG_MTD_NAND_ECC_SMC is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_ECC_BCH is not set
+# CONFIG_MTD_SM_COMMON is not set
+# CONFIG_MTD_NAND_DENALI_DT is not set
+# CONFIG_MTD_NAND_GPIO is not set
+# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_DOCG4 is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_BRCMNAND is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_NAND_HISI504 is not set
+# CONFIG_MTD_NAND_MTK is not set
+CONFIG_MTD_SPI_NAND_GOKE=y
+# CONFIG_GOKE_NAND_ECC_STATUS_REPORT is not set
+# CONFIG_GOKE_NAND_FS_MAY_NO_YAFFS2 is not set
+CONFIG_MTD_SPI_NAND_FMC100=y
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR & LPDDR2 PCM memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_LPDDR2_NVM is not set
+CONFIG_MTD_SPI_NOR=y
+# CONFIG_MTD_MT81xx_NOR is not set
+# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
+# CONFIG_SPI_CADENCE_QUADSPI is not set
+CONFIG_SPI_GOKE_SFC=y
+# CONFIG_CLOSE_SPI_8PIN_4IO is not set
+CONFIG_GOKE_SPI_BLOCK_PROTECT=y
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_LIMIT=20
+# CONFIG_MTD_UBI_FASTMAP is not set
+# CONFIG_MTD_UBI_GLUEBI is not set
+# CONFIG_MTD_UBI_BLOCK is not set
+CONFIG_DTC=y
+CONFIG_OF=y
+# CONFIG_OF_UNITTEST is not set
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_NET=y
+CONFIG_OF_MDIO=y
+CONFIG_OF_RESERVED_MEM=y
+# CONFIG_OF_OVERLAY is not set
+CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_NULL_BLK is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_DRBD is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=65536
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MG_DISK is not set
+# CONFIG_BLK_DEV_RBD is not set
+# CONFIG_NVME_TARGET is not set
+
+#
+# Misc devices
+#
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_DUMMY_IRQ is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_APDS9802ALS is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_ISL29020 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_BH1770 is not set
+# CONFIG_SENSORS_APDS990X is not set
+# CONFIG_HMC6352 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_TI_DAC7512 is not set
+# CONFIG_USB_SWITCH_FSA9480 is not set
+# CONFIG_LATTICE_ECP3_CONFIG is not set
+# CONFIG_SRAM is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_EEPROM_93XX46 is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+# CONFIG_SENSORS_LIS3_SPI is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
+
+#
+# Altera FPGA firmware download module
+#
+# CONFIG_ALTERA_STAPL is not set
+
+#
+# Intel MIC Bus Driver
+#
+
+#
+# SCIF Bus Driver
+#
+
+#
+# VOP Bus Driver
+#
+
+#
+# Intel MIC Host Driver
+#
+
+#
+# Intel MIC Card Driver
+#
+
+#
+# SCIF Driver
+#
+
+#
+# Intel MIC Coprocessor State Management (COSM) Drivers
+#
+
+#
+# VOP Driver
+#
+# CONFIG_ECHO is not set
+# CONFIG_CXL_BASE is not set
+# CONFIG_CXL_AFU_DRIVER_OPS is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+CONFIG_SCSI_NETLINK=y
+# CONFIG_SCSI_MQ_DEFAULT is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+CONFIG_SCSI_FC_ATTRS=y
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_ISCSI_BOOT_SYSFS is not set
+# CONFIG_SCSI_UFSHCD is not set
+# CONFIG_LIBFC is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_TARGET_CORE is not set
+CONFIG_NETDEVICES=y
+CONFIG_NET_CORE=y
+# CONFIG_BONDING is not set
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_NET_TEAM is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_VXLAN is not set
+# CONFIG_MACSEC is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_TUN is not set
+# CONFIG_TUN_VNET_CROSS_LE is not set
+# CONFIG_VETH is not set
+# CONFIG_NLMON is not set
+
+#
+# CAIF transport drivers
+#
+
+#
+# Distributed Switch Architecture drivers
+#
+CONFIG_ETHERNET=y
+# CONFIG_ALTERA_TSE is not set
+# CONFIG_NET_VENDOR_AMAZON is not set
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_AURORA is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_DM9000 is not set
+# CONFIG_DNET is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_HISILICON is not set
+CONFIG_NET_VENDOR_GOKE=y
+CONFIG_GOKE_FEMAC=y
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+CONFIG_NET_VENDOR_MICROCHIP=y
+# CONFIG_ENC28J60 is not set
+# CONFIG_ENCX24J600 is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
+# CONFIG_ETHOC is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_PHYLIB=y
+CONFIG_SWPHY=y
+
+#
+# MDIO bus device drivers
+#
+# CONFIG_MDIO_BCM_UNIMAC is not set
+# CONFIG_MDIO_BITBANG is not set
+# CONFIG_MDIO_BUS_MUX_GPIO is not set
+# CONFIG_MDIO_BUS_MUX_MMIOREG is not set
+CONFIG_MDIO_GOKE_FEMAC=y
+# CONFIG_MDIO_HISI_FEMAC is not set
+
+#
+# MII PHY device drivers
+#
+# CONFIG_AMD_PHY is not set
+# CONFIG_AQUANTIA_PHY is not set
+# CONFIG_AT803X_PHY is not set
+# CONFIG_BCM7XXX_PHY is not set
+# CONFIG_BCM87XX_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_DP83848_PHY is not set
+# CONFIG_DP83867_PHY is not set
+CONFIG_FIXED_PHY=y
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_INTEL_XWAY_PHY is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_MICREL_PHY is not set
+# CONFIG_MICROCHIP_PHY is not set
+# CONFIG_MICROSEMI_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_TERANETICS_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_XILINX_GMII2RGMII is not set
+# CONFIG_MICREL_KS8995MA is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_USB_NET_DRIVERS is not set
+# CONFIG_WLAN is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_ISDN is not set
+# CONFIG_NVM is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+# CONFIG_INPUT_MATRIXKMAP is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ADP5588 is not set
+# CONFIG_KEYBOARD_ADP5589 is not set
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_QT1070 is not set
+# CONFIG_KEYBOARD_QT2160 is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_KEYBOARD_GPIO_POLLED is not set
+# CONFIG_KEYBOARD_TCA6416 is not set
+# CONFIG_KEYBOARD_TCA8418 is not set
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_LM8333 is not set
+# CONFIG_KEYBOARD_MAX7359 is not set
+# CONFIG_KEYBOARD_MCS is not set
+# CONFIG_KEYBOARD_MPR121 is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_SAMSUNG is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_OMAP4 is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_CAP11XX is not set
+# CONFIG_KEYBOARD_BCM is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_BYD=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_CYPRESS=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_SENTELIC is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+CONFIG_MOUSE_PS2_FOCALTECH=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_CYAPA is not set
+# CONFIG_MOUSE_ELAN_I2C is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+# CONFIG_MOUSE_SYNAPTICS_I2C is not set
+# CONFIG_MOUSE_SYNAPTICS_USB is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_AD714X is not set
+# CONFIG_INPUT_ATMEL_CAPTOUCH is not set
+# CONFIG_INPUT_BMA150 is not set
+# CONFIG_INPUT_E3X0_BUTTON is not set
+# CONFIG_INPUT_MMA8450 is not set
+# CONFIG_INPUT_MPU3050 is not set
+# CONFIG_INPUT_GP2A is not set
+# CONFIG_INPUT_GPIO_BEEPER is not set
+# CONFIG_INPUT_GPIO_TILT_POLLED is not set
+# CONFIG_INPUT_GPIO_DECODER is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_KXTJ9 is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
+CONFIG_INPUT_UINPUT=y
+# CONFIG_INPUT_PCF8574 is not set
+# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
+# CONFIG_INPUT_ADXL34X is not set
+# CONFIG_INPUT_CMA3000 is not set
+# CONFIG_INPUT_DRV260X_HAPTICS is not set
+# CONFIG_INPUT_DRV2665_HAPTICS is not set
+# CONFIG_INPUT_DRV2667_HAPTICS is not set
+# CONFIG_RMI4_CORE is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_AMBAKMI is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_ALTERA_PS2 is not set
+# CONFIG_SERIO_PS2MULT is not set
+# CONFIG_SERIO_ARC_PS2 is not set
+# CONFIG_SERIO_APBPS2 is not set
+# CONFIG_USERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_TTY=y
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_VT_CONSOLE_SLEEP=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVMEM=y
+# CONFIG_DEVKMEM is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_EARLYCON=y
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_AMBA_PL010 is not set
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set
+# CONFIG_SERIAL_MAX3100 is not set
+# CONFIG_SERIAL_MAX310X is not set
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_SCCNXP is not set
+# CONFIG_SERIAL_SC16IS7XX is not set
+# CONFIG_SERIAL_BCM63XX is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_IFX6X60 is not set
+# CONFIG_SERIAL_XILINX_PS_UART is not set
+# CONFIG_SERIAL_ARC is not set
+# CONFIG_SERIAL_FSL_LPUART is not set
+# CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set
+# CONFIG_SERIAL_ST_ASC is not set
+# CONFIG_SERIAL_STM32 is not set
+# CONFIG_HVC_DCC is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_XILLYBUS is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MUX=y
+
+#
+# Multiplexer I2C Chip support
+#
+# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set
+# CONFIG_I2C_MUX_GPIO is not set
+# CONFIG_I2C_MUX_PCA9541 is not set
+# CONFIG_I2C_MUX_PCA954x is not set
+# CONFIG_I2C_MUX_PINCTRL is not set
+# CONFIG_I2C_MUX_REG is not set
+# CONFIG_I2C_DEMUX_PINCTRL is not set
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_CBUS_GPIO is not set
+# CONFIG_I2C_DESIGNWARE_PLATFORM is not set
+# CONFIG_I2C_EMEV2 is not set
+# CONFIG_I2C_GPIO is not set
+CONFIG_I2C_GOKE=y
+# CONFIG_I2C_NOMADIK is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_PXA_PCI is not set
+# CONFIG_I2C_RK3X is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_DIOLAN_U2C is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_ROBOTFUZZ_OSIF is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+CONFIG_DMA_MSG_MIN_LEN=5
+CONFIG_DMA_MSG_MAX_LEN=4090
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_SLAVE is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_ALTERA is not set
+# CONFIG_SPI_AXI_SPI_ENGINE is not set
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_CADENCE is not set
+# CONFIG_SPI_DESIGNWARE is not set
+# CONFIG_SPI_GPIO is not set
+# CONFIG_SPI_FSL_SPI is not set
+# CONFIG_SPI_OC_TINY is not set
+CONFIG_SPI_PL022=y
+# CONFIG_SPI_PXA2XX_PCI is not set
+# CONFIG_SPI_ROCKCHIP is not set
+# CONFIG_SPI_SC18IS602 is not set
+# CONFIG_SPI_XCOMM is not set
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_ZYNQMP_GQSPI is not set
+
+#
+# SPI Protocol Masters
+#
+CONFIG_SPI_SPIDEV=y
+# CONFIG_SPI_LOOPBACK_TEST is not set
+# CONFIG_SPI_TLE62X0 is not set
+# CONFIG_SPMI is not set
+# CONFIG_HSI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+# CONFIG_PTP_1588_CLOCK is not set
+
+#
+# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
+#
+CONFIG_PINCTRL=y
+
+#
+# Pin controllers
+#
+CONFIG_PINMUX=y
+CONFIG_PINCONF=y
+CONFIG_GENERIC_PINCONF=y
+# CONFIG_DEBUG_PINCTRL is not set
+# CONFIG_PINCTRL_AMD is not set
+CONFIG_PINCTRL_SINGLE=y
+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
+CONFIG_GPIOLIB=y
+CONFIG_OF_GPIO=y
+CONFIG_GPIOLIB_IRQCHIP=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO drivers
+#
+# CONFIG_GPIO_74XX_MMIO is not set
+# CONFIG_GPIO_ALTERA is not set
+# CONFIG_GPIO_DWAPB is not set
+# CONFIG_GPIO_EM is not set
+# CONFIG_GPIO_GENERIC_PLATFORM is not set
+# CONFIG_GPIO_GRGPIO is not set
+# CONFIG_GPIO_MOCKUP is not set
+# CONFIG_GPIO_MPC8XXX is not set
+CONFIG_GPIO_PL061=y
+# CONFIG_GPIO_SYSCON is not set
+# CONFIG_GPIO_XILINX is not set
+# CONFIG_GPIO_ZEVIO is not set
+# CONFIG_GPIO_ZX is not set
+
+#
+# I2C GPIO expanders
+#
+# CONFIG_GPIO_ADP5588 is not set
+# CONFIG_GPIO_ADNP is not set
+# CONFIG_GPIO_MAX7300 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_SX150X is not set
+# CONFIG_GPIO_TPIC2810 is not set
+# CONFIG_GPIO_TS4900 is not set
+
+#
+# MFD GPIO expanders
+#
+# CONFIG_HTC_EGPIO is not set
+
+#
+# SPI GPIO expanders
+#
+# CONFIG_GPIO_74X164 is not set
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MC33880 is not set
+# CONFIG_GPIO_PISOSR is not set
+
+#
+# SPI or I2C GPIO expanders
+#
+# CONFIG_GPIO_MCP23S08 is not set
+
+#
+# USB GPIO expanders
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_AVS is not set
+CONFIG_POWER_RESET=y
+# CONFIG_POWER_RESET_BRCMKONA is not set
+# CONFIG_POWER_RESET_BRCMSTB is not set
+CONFIG_POWER_RESET_GOKE=y
+# CONFIG_POWER_RESET_GPIO is not set
+# CONFIG_POWER_RESET_GPIO_RESTART is not set
+# CONFIG_POWER_RESET_LTC2952 is not set
+# CONFIG_POWER_RESET_RESTART is not set
+# CONFIG_POWER_RESET_VERSATILE is not set
+# CONFIG_POWER_RESET_SYSCON is not set
+# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set
+# CONFIG_SYSCON_REBOOT_MODE is not set
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_TEST_POWER is not set
+# CONFIG_BATTERY_DS2780 is not set
+# CONFIG_BATTERY_DS2781 is not set
+# CONFIG_BATTERY_DS2782 is not set
+# CONFIG_BATTERY_SBS is not set
+# CONFIG_BATTERY_BQ27XXX is not set
+# CONFIG_BATTERY_MAX17040 is not set
+# CONFIG_BATTERY_MAX17042 is not set
+# CONFIG_CHARGER_MAX8903 is not set
+# CONFIG_CHARGER_LP8727 is not set
+# CONFIG_CHARGER_GPIO is not set
+# CONFIG_CHARGER_BQ2415X is not set
+# CONFIG_CHARGER_BQ24190 is not set
+# CONFIG_CHARGER_BQ24257 is not set
+# CONFIG_CHARGER_BQ24735 is not set
+# CONFIG_CHARGER_BQ25890 is not set
+# CONFIG_CHARGER_SMB347 is not set
+# CONFIG_BATTERY_GAUGE_LTC2941 is not set
+# CONFIG_CHARGER_RT9455 is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+CONFIG_MFD_CORE=y
+# CONFIG_MFD_ACT8945A is not set
+# CONFIG_MFD_AS3711 is not set
+# CONFIG_MFD_AS3722 is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_AAT2870_CORE is not set
+# CONFIG_MFD_ATMEL_FLEXCOM is not set
+# CONFIG_MFD_ATMEL_HLCDC is not set
+# CONFIG_MFD_BCM590XX is not set
+# CONFIG_MFD_AXP20X_I2C is not set
+# CONFIG_MFD_CROS_EC is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_DA9052_SPI is not set
+# CONFIG_MFD_DA9052_I2C is not set
+# CONFIG_MFD_DA9055 is not set
+# CONFIG_MFD_DA9062 is not set
+# CONFIG_MFD_DA9063 is not set
+# CONFIG_MFD_DA9150 is not set
+# CONFIG_MFD_DLN2 is not set
+# CONFIG_MFD_EXYNOS_LPASS is not set
+# CONFIG_MFD_MC13XXX_SPI is not set
+# CONFIG_MFD_MC13XXX_I2C is not set
+# CONFIG_MFD_HI6421_PMIC is not set
+CONFIG_MFD_GOKE_FMC=y
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_HTC_I2CPLD is not set
+# CONFIG_INTEL_SOC_PMIC is not set
+# CONFIG_MFD_KEMPLD is not set
+# CONFIG_MFD_88PM800 is not set
+# CONFIG_MFD_88PM805 is not set
+# CONFIG_MFD_88PM860X is not set
+# CONFIG_MFD_MAX14577 is not set
+# CONFIG_MFD_MAX77620 is not set
+# CONFIG_MFD_MAX77686 is not set
+# CONFIG_MFD_MAX77693 is not set
+# CONFIG_MFD_MAX77843 is not set
+# CONFIG_MFD_MAX8907 is not set
+# CONFIG_MFD_MAX8925 is not set
+# CONFIG_MFD_MAX8997 is not set
+# CONFIG_MFD_MAX8998 is not set
+# CONFIG_MFD_MT6397 is not set
+# CONFIG_MFD_MENF21BMC is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_MFD_VIPERBOARD is not set
+# CONFIG_MFD_RETU is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_PM8921_CORE is not set
+# CONFIG_MFD_RT5033 is not set
+# CONFIG_MFD_RTSX_USB is not set
+# CONFIG_MFD_RC5T583 is not set
+# CONFIG_MFD_RK808 is not set
+# CONFIG_MFD_RN5T618 is not set
+# CONFIG_MFD_SEC_CORE is not set
+# CONFIG_MFD_SI476X_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_SKY81452 is not set
+# CONFIG_MFD_SMSC is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_MFD_STMPE is not set
+CONFIG_MFD_SYSCON=y
+# CONFIG_MFD_TI_AM335X_TSCADC is not set
+# CONFIG_MFD_LP3943 is not set
+# CONFIG_MFD_LP8788 is not set
+# CONFIG_MFD_PALMAS is not set
+# CONFIG_TPS6105X is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TPS6507X is not set
+# CONFIG_MFD_TPS65086 is not set
+# CONFIG_MFD_TPS65090 is not set
+# CONFIG_MFD_TPS65217 is not set
+# CONFIG_MFD_TI_LP873X is not set
+# CONFIG_MFD_TPS65218 is not set
+# CONFIG_MFD_TPS6586X is not set
+# CONFIG_MFD_TPS65910 is not set
+# CONFIG_MFD_TPS65912_I2C is not set
+# CONFIG_MFD_TPS65912_SPI is not set
+# CONFIG_MFD_TPS80031 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_TWL6040_CORE is not set
+# CONFIG_MFD_WL1273_CORE is not set
+# CONFIG_MFD_LM3533 is not set
+# CONFIG_MFD_TC3589X is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_MFD_ARIZONA_I2C is not set
+# CONFIG_MFD_ARIZONA_SPI is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X_I2C is not set
+# CONFIG_MFD_WM831X_SPI is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8994 is not set
+# CONFIG_REGULATOR is not set
+CONFIG_MEDIA_SUPPORT=y
+
+#
+# Multimedia core support
+#
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set
+# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set
+# CONFIG_MEDIA_RADIO_SUPPORT is not set
+# CONFIG_MEDIA_SDR_SUPPORT is not set
+# CONFIG_MEDIA_RC_SUPPORT is not set
+# CONFIG_MEDIA_CONTROLLER is not set
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L2=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEOBUF2_CORE=y
+CONFIG_VIDEOBUF2_MEMOPS=y
+CONFIG_VIDEOBUF2_VMALLOC=y
+# CONFIG_TTPCI_EEPROM is not set
+
+#
+# Media drivers
+#
+CONFIG_MEDIA_USB_SUPPORT=y
+
+#
+# Webcam devices
+#
+CONFIG_USB_VIDEO_CLASS=y
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+CONFIG_USB_GSPCA=m
+# CONFIG_USB_M5602 is not set
+# CONFIG_USB_STV06XX is not set
+# CONFIG_USB_GL860 is not set
+# CONFIG_USB_GSPCA_BENQ is not set
+# CONFIG_USB_GSPCA_CONEX is not set
+# CONFIG_USB_GSPCA_CPIA1 is not set
+# CONFIG_USB_GSPCA_DTCS033 is not set
+# CONFIG_USB_GSPCA_ETOMS is not set
+# CONFIG_USB_GSPCA_FINEPIX is not set
+# CONFIG_USB_GSPCA_JEILINJ is not set
+# CONFIG_USB_GSPCA_JL2005BCD is not set
+# CONFIG_USB_GSPCA_KINECT is not set
+# CONFIG_USB_GSPCA_KONICA is not set
+# CONFIG_USB_GSPCA_MARS is not set
+# CONFIG_USB_GSPCA_MR97310A is not set
+# CONFIG_USB_GSPCA_NW80X is not set
+# CONFIG_USB_GSPCA_OV519 is not set
+# CONFIG_USB_GSPCA_OV534 is not set
+# CONFIG_USB_GSPCA_OV534_9 is not set
+# CONFIG_USB_GSPCA_PAC207 is not set
+# CONFIG_USB_GSPCA_PAC7302 is not set
+# CONFIG_USB_GSPCA_PAC7311 is not set
+# CONFIG_USB_GSPCA_SE401 is not set
+# CONFIG_USB_GSPCA_SN9C2028 is not set
+# CONFIG_USB_GSPCA_SN9C20X is not set
+# CONFIG_USB_GSPCA_SONIXB is not set
+# CONFIG_USB_GSPCA_SONIXJ is not set
+# CONFIG_USB_GSPCA_SPCA500 is not set
+# CONFIG_USB_GSPCA_SPCA501 is not set
+# CONFIG_USB_GSPCA_SPCA505 is not set
+# CONFIG_USB_GSPCA_SPCA506 is not set
+# CONFIG_USB_GSPCA_SPCA508 is not set
+# CONFIG_USB_GSPCA_SPCA561 is not set
+# CONFIG_USB_GSPCA_SPCA1528 is not set
+# CONFIG_USB_GSPCA_SQ905 is not set
+# CONFIG_USB_GSPCA_SQ905C is not set
+# CONFIG_USB_GSPCA_SQ930X is not set
+# CONFIG_USB_GSPCA_STK014 is not set
+# CONFIG_USB_GSPCA_STK1135 is not set
+# CONFIG_USB_GSPCA_STV0680 is not set
+# CONFIG_USB_GSPCA_SUNPLUS is not set
+# CONFIG_USB_GSPCA_T613 is not set
+# CONFIG_USB_GSPCA_TOPRO is not set
+# CONFIG_USB_GSPCA_TOUPTEK is not set
+# CONFIG_USB_GSPCA_TV8532 is not set
+# CONFIG_USB_GSPCA_VC032X is not set
+# CONFIG_USB_GSPCA_VICAM is not set
+# CONFIG_USB_GSPCA_XIRLINK_CIT is not set
+# CONFIG_USB_GSPCA_ZC3XX is not set
+# CONFIG_USB_PWC is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_USB_ZR364XX is not set
+# CONFIG_USB_STKWEBCAM is not set
+# CONFIG_USB_S2255 is not set
+
+#
+# Webcam, TV (analog/digital) USB devices
+#
+# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_V4L_PLATFORM_DRIVERS is not set
+# CONFIG_V4L_MEM2MEM_DRIVERS is not set
+# CONFIG_V4L_TEST_DRIVERS is not set
+
+#
+# Supported MMC/SDIO adapters
+#
+# CONFIG_CYPRESS_FIRMWARE is not set
+
+#
+# Media ancillary drivers (tuners, sensors, i2c, spi, frontends)
+#
+CONFIG_MEDIA_SUBDRV_AUTOSELECT=y
+
+#
+# Audio decoders, processors and mixers
+#
+
+#
+# RDS decoders
+#
+
+#
+# Video decoders
+#
+
+#
+# Video and audio decoders
+#
+
+#
+# Video encoders
+#
+
+#
+# Camera sensor devices
+#
+
+#
+# Flash devices
+#
+
+#
+# Video improvement chips
+#
+
+#
+# Audio/Video compression chips
+#
+
+#
+# Miscellaneous helper chips
+#
+
+#
+# Sensors used on soc_camera driver
+#
+
+#
+# Tools to develop new frontends
+#
+# CONFIG_DVB_DUMMY_FE is not set
+
+#
+# Graphics support
+#
+# CONFIG_IMX_IPUV3_CORE is not set
+# CONFIG_DRM is not set
+
+#
+# ACP (Audio CoProcessor) Configuration
+#
+
+#
+# Frame buffer Devices
+#
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB_CMDLINE=y
+CONFIG_FB_NOTIFY=y
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_ARMCLCD is not set
+# CONFIG_FB_OPENCORES is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_SMSCUFX is not set
+# CONFIG_FB_UDL is not set
+# CONFIG_FB_IBM_GXT4500 is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_FB_AUO_K190X is not set
+# CONFIG_FB_SIMPLE is not set
+# CONFIG_FB_SSD1307 is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+# CONFIG_LOGO is not set
+# CONFIG_SOUND is not set
+
+#
+# HID support
+#
+CONFIG_HID=y
+# CONFIG_HID_BATTERY_STRENGTH is not set
+# CONFIG_HIDRAW is not set
+# CONFIG_UHID is not set
+CONFIG_HID_GENERIC=y
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_ACRUX is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_APPLEIR is not set
+# CONFIG_HID_AUREAL is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_BETOP_FF is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_CMEDIA is not set
+# CONFIG_HID_CP2112 is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EMS_FF is not set
+# CONFIG_HID_ELECOM is not set
+# CONFIG_HID_ELO is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_GEMBIRD is not set
+# CONFIG_HID_GFRM is not set
+# CONFIG_HID_HOLTEK is not set
+# CONFIG_HID_KEYTOUCH is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_UCLOGIC is not set
+# CONFIG_HID_WALTOP is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_ICADE is not set
+# CONFIG_HID_TWINHAN is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LCPOWER is not set
+# CONFIG_HID_LENOVO is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MAGICMOUSE is not set
+CONFIG_HID_MICROSOFT=y
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_MULTITOUCH is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_ORTEK is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PENMOUNT is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_PICOLCD is not set
+# CONFIG_HID_PLANTRONICS is not set
+# CONFIG_HID_PRIMAX is not set
+# CONFIG_HID_ROCCAT is not set
+# CONFIG_HID_SAITEK is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SPEEDLINK is not set
+# CONFIG_HID_STEELSERIES is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_RMI is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TIVO is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_WACOM is not set
+# CONFIG_HID_XINMO is not set
+# CONFIG_HID_ZEROPLUS is not set
+# CONFIG_HID_ZYDACRON is not set
+# CONFIG_HID_SENSOR_HUB is not set
+# CONFIG_HID_ALPS is not set
+
+#
+# USB HID support
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# I2C HID support
+#
+# CONFIG_I2C_HID is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_COMMON=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB=y
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEFAULT_PERSIST=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_PLATFORM=y
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+# CONFIG_USB_FOTG210_HCD is not set
+# CONFIG_USB_MAX3421_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HCD_TEST_MODE is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_REALTEK is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_STORAGE_ENE_UB6250 is not set
+# CONFIG_USB_UAS is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USBIP_CORE is not set
+# CONFIG_USB_MUSB_HDRC is not set
+CONFIG_USB_DWC3=y
+# CONFIG_USB_DWC3_HOST is not set
+# CONFIG_USB_DWC3_GADGET is not set
+CONFIG_USB_DWC3_DUAL_ROLE=y
+
+#
+# Platform Glue Driver Support
+#
+CONFIG_USB_DWC3_OF_SIMPLE=y
+# CONFIG_USB_DWC2 is not set
+# CONFIG_USB_CHIPIDEA is not set
+# CONFIG_USB_ISP1760 is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_EHSET_TEST_FIXTURE is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_YUREX is not set
+# CONFIG_USB_EZUSB_FX2 is not set
+# CONFIG_USB_HSIC_USB3503 is not set
+# CONFIG_USB_HSIC_USB4604 is not set
+# CONFIG_USB_LINK_LAYER_TEST is not set
+
+#
+# USB Physical Layer drivers
+#
+# CONFIG_USB_PHY is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_USB_ISP1301 is not set
+# CONFIG_USB_ULPI is not set
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2
+
+#
+# USB Peripheral Controller
+#
+# CONFIG_USB_FUSB300 is not set
+# CONFIG_USB_FOTG210_UDC is not set
+# CONFIG_USB_GR_UDC is not set
+# CONFIG_USB_R8A66597 is not set
+# CONFIG_USB_PXA27X is not set
+# CONFIG_USB_MV_UDC is not set
+# CONFIG_USB_MV_U3D is not set
+# CONFIG_USB_M66592 is not set
+# CONFIG_USB_BDC_UDC is not set
+# CONFIG_USB_NET2272 is not set
+# CONFIG_USB_GADGET_XILINX is not set
+# CONFIG_USB_DUMMY_HCD is not set
+CONFIG_USB_LIBCOMPOSITE=m
+CONFIG_USB_F_ACM=m
+CONFIG_USB_U_SERIAL=m
+CONFIG_USB_U_ETHER=m
+CONFIG_USB_F_ECM=m
+CONFIG_USB_F_RNDIS=m
+CONFIG_USB_F_MASS_STORAGE=m
+CONFIG_USB_CONFIGFS=m
+# CONFIG_USB_CONFIGFS_SERIAL is not set
+CONFIG_USB_CONFIGFS_ACM=y
+# CONFIG_USB_CONFIGFS_OBEX is not set
+# CONFIG_USB_CONFIGFS_NCM is not set
+CONFIG_USB_CONFIGFS_ECM=y
+# CONFIG_USB_CONFIGFS_ECM_SUBSET is not set
+CONFIG_USB_CONFIGFS_RNDIS=y
+# CONFIG_USB_CONFIGFS_EEM is not set
+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
+# CONFIG_USB_CONFIGFS_F_LB_SS is not set
+# CONFIG_USB_CONFIGFS_F_FS is not set
+# CONFIG_USB_CONFIGFS_F_HID is not set
+# CONFIG_USB_CONFIGFS_F_UVC is not set
+# CONFIG_USB_CONFIGFS_F_PRINTER is not set
+# CONFIG_USB_ULPI_BUS is not set
+# CONFIG_UWB is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_PWRSEQ_EMMC=y
+CONFIG_PWRSEQ_SIMPLE=y
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_MINORS=8
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_ARMMMCI is not set
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+# CONFIG_MMC_SDHCI_OF_ARASAN is not set
+# CONFIG_MMC_SDHCI_OF_AT91 is not set
+CONFIG_MMC_SDHCI_GOKE=y
+# CONFIG_MMC_SDHCI_F_SDH30 is not set
+# CONFIG_MMC_SPI is not set
+# CONFIG_MMC_DW is not set
+# CONFIG_MMC_VUB300 is not set
+# CONFIG_MMC_USHC is not set
+# CONFIG_MMC_USDHI6ROL0 is not set
+# CONFIG_MMC_MTK is not set
+# CONFIG_MMC_CQ_HCI is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_EDAC_ATOMIC_SCRUB=y
+CONFIG_EDAC_SUPPORT=y
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+CONFIG_RTC_SYSTOHC=y
+CONFIG_RTC_SYSTOHC_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_ABB5ZES3 is not set
+# CONFIG_RTC_DRV_ABX80X is not set
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_HYM8563 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_ISL12022 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8523 is not set
+# CONFIG_RTC_DRV_PCF85063 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_BQ32K is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8010 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+# CONFIG_RTC_DRV_EM3027 is not set
+# CONFIG_RTC_DRV_RV8803 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T93 is not set
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1302 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1343 is not set
+# CONFIG_RTC_DRV_DS1347 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6916 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RX4581 is not set
+# CONFIG_RTC_DRV_RX6110 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
+# CONFIG_RTC_DRV_MCP795 is not set
+CONFIG_RTC_I2C_AND_SPI=y
+
+#
+# SPI and I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS3232 is not set
+# CONFIG_RTC_DRV_PCF2127 is not set
+# CONFIG_RTC_DRV_RV3029C2 is not set
+
+#
+# Platform RTC drivers
+#
+CONFIG_RTC_DRV_GOKE=y
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1685_FAMILY is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_DS2404 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+# CONFIG_RTC_DRV_ZYNQMP is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_PL030 is not set
+# CONFIG_RTC_DRV_PL031 is not set
+# CONFIG_RTC_DRV_SNVS is not set
+
+#
+# HID Sensor RTC drivers
+#
+# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set
+# CONFIG_DMADEVICES is not set
+
+#
+# DMABUF options
+#
+# CONFIG_SYNC_FILE is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+# CONFIG_VIRT_DRIVERS is not set
+
+#
+# Virtio drivers
+#
+# CONFIG_VIRTIO_MMIO is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_STAGING is not set
+# CONFIG_GOLDFISH is not set
+# CONFIG_CHROME_PLATFORMS is not set
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_COMMON_CLK=y
+
+#
+# Common Clock Framework
+#
+# CONFIG_COMMON_CLK_SI5351 is not set
+# CONFIG_COMMON_CLK_SI514 is not set
+# CONFIG_COMMON_CLK_SI570 is not set
+# CONFIG_COMMON_CLK_CDCE706 is not set
+# CONFIG_COMMON_CLK_CDCE925 is not set
+# CONFIG_COMMON_CLK_CS2000_CP is not set
+# CONFIG_CLK_QORIQ is not set
+# CONFIG_COMMON_CLK_NXP is not set
+# CONFIG_COMMON_CLK_PXA is not set
+# CONFIG_COMMON_CLK_PIC32 is not set
+CONFIG_COMMON_CLK_GK7205V300=y
+CONFIG_RESET_GOKE=y
+
+#
+# Hardware Spinlock drivers
+#
+
+#
+# Clock Source drivers
+#
+CONFIG_CLKSRC_OF=y
+CONFIG_CLKSRC_PROBE=y
+CONFIG_CLKSRC_MMIO=y
+CONFIG_ARM_ARCH_TIMER=y
+CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y
+# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS is not set
+CONFIG_ARM_TIMER_SP804=y
+# CONFIG_ATMEL_PIT is not set
+# CONFIG_SH_TIMER_CMT is not set
+# CONFIG_SH_TIMER_MTU2 is not set
+# CONFIG_SH_TIMER_TMU is not set
+# CONFIG_EM_TIMER_STI is not set
+# CONFIG_MAILBOX is not set
+# CONFIG_IOMMU_SUPPORT is not set
+
+#
+# Remoteproc drivers
+#
+# CONFIG_STE_MODEM_RPROC is not set
+
+#
+# Rpmsg drivers
+#
+
+#
+# SOC (System On Chip) specific Drivers
+#
+
+#
+# Broadcom SoC drivers
+#
+# CONFIG_SOC_BRCMSTB is not set
+# CONFIG_SUNXI_SRAM is not set
+# CONFIG_SOC_TI is not set
+# CONFIG_PM_DEVFREQ is not set
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
+# CONFIG_IIO is not set
+# CONFIG_PWM is not set
+CONFIG_IRQCHIP=y
+CONFIG_ARM_GIC=y
+CONFIG_ARM_GIC_MAX_NR=1
+# CONFIG_IPACK_BUS is not set
+CONFIG_RESET_CONTROLLER=y
+# CONFIG_RESET_ATH79 is not set
+# CONFIG_RESET_BERLIN is not set
+# CONFIG_RESET_LPC18XX is not set
+# CONFIG_RESET_MESON is not set
+# CONFIG_RESET_PISTACHIO is not set
+# CONFIG_RESET_SOCFPGA is not set
+# CONFIG_RESET_STM32 is not set
+# CONFIG_RESET_SUNXI is not set
+# CONFIG_TI_SYSCON_RESET is not set
+# CONFIG_RESET_ZYNQ is not set
+# CONFIG_FMC is not set
+
+#
+# PHY Subsystem
+#
+CONFIG_GENERIC_PHY=y
+# CONFIG_PHY_PXA_28NM_HSIC is not set
+# CONFIG_PHY_PXA_28NM_USB2 is not set
+# CONFIG_BCM_KONA_USB2_PHY is not set
+CONFIG_PHY_GOKE_USBP2=y
+# CONFIG_USB_MODE_OPTION is not set
+# CONFIG_POWERCAP is not set
+# CONFIG_MCB is not set
+
+#
+# Performance monitor support
+#
+# CONFIG_RAS is not set
+
+#
+# Android
+#
+# CONFIG_ANDROID is not set
+# CONFIG_NVMEM is not set
+# CONFIG_STM is not set
+# CONFIG_INTEL_TH is not set
+
+#
+# FPGA Configuration Support
+#
+# CONFIG_FPGA is not set
+
+#
+# goke driver support
+#
+
+#
+# Firmware Drivers
+#
+# CONFIG_FIRMWARE_MEMMAP is not set
+# CONFIG_FW_CFG_SYSFS is not set
+CONFIG_HAVE_ARM_SMCCC=y
+
+#
+# File systems
+#
+CONFIG_DCACHE_WORD_ACCESS=y
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_USE_FOR_EXT2=y
+# CONFIG_EXT4_FS_POSIX_ACL is not set
+# CONFIG_EXT4_FS_SECURITY is not set
+# CONFIG_EXT4_ENCRYPTION is not set
+# CONFIG_EXT4_DEBUG is not set
+CONFIG_JBD2=y
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+# CONFIG_F2FS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_EXPORTFS=y
+# CONFIG_EXPORTFS_BLOCK_OPS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_MANDATORY_FILE_LOCKING=y
+# CONFIG_FS_ENCRYPTION is not set
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_QUOTACTL is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+# CONFIG_OVERLAY_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_FAT_DEFAULT_UTF8 is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_PROC_CHILDREN is not set
+CONFIG_KERNFS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_TMPFS_XATTR=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=y
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ORANGEFS_FS is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_YAFFS_FS=y
+CONFIG_YAFFS_YAFFS1=y
+# CONFIG_YAFFS_9BYTE_TAGS is not set
+# CONFIG_YAFFS_DOES_ECC is not set
+CONFIG_YAFFS_YAFFS2=y
+CONFIG_YAFFS_AUTO_YAFFS2=y
+# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set
+# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
+# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set
+# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set
+# CONFIG_YAFFS_DISABLE_BACKGROUND is not set
+# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set
+CONFIG_YAFFS_XATTR=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+# CONFIG_JFFS2_LZMA is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_UBIFS_FS=y
+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_ATIME_SUPPORT is not set
+# CONFIG_LOGFS is not set
+CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX6FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_PSTORE is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V2=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+# CONFIG_NFS_SWAP is not set
+# CONFIG_NFS_V4_1 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFS_USE_LEGACY_DNS is not set
+CONFIG_NFS_USE_KERNEL_DNS=y
+# CONFIG_NFSD is not set
+CONFIG_GRACE_PERIOD=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_ACL_SUPPORT=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_DEBUG is not set
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=y
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+# CONFIG_NLS_MAC_ROMAN is not set
+# CONFIG_NLS_MAC_CELTIC is not set
+# CONFIG_NLS_MAC_CENTEURO is not set
+# CONFIG_NLS_MAC_CROATIAN is not set
+# CONFIG_NLS_MAC_CYRILLIC is not set
+# CONFIG_NLS_MAC_GAELIC is not set
+# CONFIG_NLS_MAC_GREEK is not set
+# CONFIG_NLS_MAC_ICELAND is not set
+# CONFIG_NLS_MAC_INUIT is not set
+# CONFIG_NLS_MAC_ROMANIAN is not set
+# CONFIG_NLS_MAC_TURKISH is not set
+CONFIG_NLS_UTF8=y
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+
+#
+# printk and dmesg options
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
+# CONFIG_BOOT_PRINTK_DELAY is not set
+
+#
+# Compile-time checks and compiler options
+#
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_READABLE_ASM is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_PAGE_OWNER is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_SECTION_MISMATCH_WARN_ONLY=y
+CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_DEBUG_KERNEL=y
+
+#
+# Memory Debugging
+#
+# CONFIG_PAGE_EXTENSION is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_PAGE_POISONING is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_SHIRQ is not set
+
+#
+# Debug Lockups and Hangs
+#
+# CONFIG_LOCKUP_DETECTOR is not set
+# CONFIG_DETECT_HUNG_TASK is not set
+# CONFIG_WQ_WATCHDOG is not set
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+CONFIG_PANIC_TIMEOUT=0
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHED_INFO is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_SCHED_STACK_END_CHECK is not set
+# CONFIG_DEBUG_TIMEKEEPING is not set
+# CONFIG_TIMER_STATS is not set
+
+#
+# Lock Debugging (spinlocks, mutexes, etc...)
+#
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_ATOMIC_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_LOCK_TORTURE_TEST is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_PI_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+
+#
+# RCU Debugging
+#
+# CONFIG_PROVE_RCU is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_TORTURE_TEST is not set
+# CONFIG_RCU_PERF_TEST is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_TRACE is not set
+# CONFIG_RCU_EQS_DEBUG is not set
+# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_NOTIFIER_ERROR_INJECTION is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+
+#
+# Runtime Testing
+#
+# CONFIG_TEST_LIST_SORT is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_RBTREE_TEST is not set
+# CONFIG_INTERVAL_TREE_TEST is not set
+# CONFIG_PERCPU_TEST is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_TEST_HEXDUMP is not set
+# CONFIG_TEST_STRING_HELPERS is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_TEST_PRINTF is not set
+# CONFIG_TEST_BITMAP is not set
+# CONFIG_TEST_UUID is not set
+# CONFIG_TEST_RHASHTABLE is not set
+# CONFIG_TEST_HASH is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_TEST_LKM is not set
+# CONFIG_TEST_USER_COPY is not set
+# CONFIG_TEST_BPF is not set
+# CONFIG_TEST_FIRMWARE is not set
+# CONFIG_TEST_UDELAY is not set
+# CONFIG_MEMTEST is not set
+# CONFIG_TEST_STATIC_KEYS is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set
+# CONFIG_UBSAN is not set
+CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
+CONFIG_STRICT_DEVMEM=y
+# CONFIG_IO_STRICT_DEVMEM is not set
+# CONFIG_ARM_PTDUMP is not set
+# CONFIG_ARM_UNWIND is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_LL is not set
+CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
+# CONFIG_DEBUG_UART_8250 is not set
+CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
+# CONFIG_PID_IN_CONTEXTIDR is not set
+# CONFIG_DEBUG_SET_MODULE_RONX is not set
+# CONFIG_CORESIGHT is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_PERSISTENT_KEYRINGS is not set
+# CONFIG_ENCRYPTED_KEYS is not set
+# CONFIG_KEY_DH_OPERATIONS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y
+CONFIG_HAVE_ARCH_HARDENED_USERCOPY=y
+# CONFIG_HARDENED_USERCOPY is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_RNG_DEFAULT=m
+CONFIG_CRYPTO_AKCIPHER2=y
+CONFIG_CRYPTO_KPP2=y
+# CONFIG_CRYPTO_RSA is not set
+# CONFIG_CRYPTO_DH is not set
+# CONFIG_CRYPTO_ECDH is not set
+CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_USER is not set
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_NULL2=y
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_MCRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+# CONFIG_CRYPTO_CHACHA20POLY1305 is not set
+CONFIG_CRYPTO_SEQIV=m
+CONFIG_CRYPTO_ECHAINIV=m
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+CONFIG_CRYPTO_CTR=m
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+# CONFIG_CRYPTO_KEYWRAP is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_CMAC is not set
+CONFIG_CRYPTO_HMAC=m
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_CRC32 is not set
+CONFIG_CRYPTO_CRCT10DIF=y
+CONFIG_CRYPTO_GHASH=m
+# CONFIG_CRYPTO_POLY1305 is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=y
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_SHA3 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_CHACHA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_LZO=y
+# CONFIG_CRYPTO_842 is not set
+# CONFIG_CRYPTO_LZ4 is not set
+# CONFIG_CRYPTO_LZ4HC is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_DRBG_MENU=m
+CONFIG_CRYPTO_DRBG_HMAC=y
+# CONFIG_CRYPTO_DRBG_HASH is not set
+# CONFIG_CRYPTO_DRBG_CTR is not set
+CONFIG_CRYPTO_DRBG=m
+CONFIG_CRYPTO_JITTERENTROPY=m
+# CONFIG_CRYPTO_USER_API_HASH is not set
+# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
+# CONFIG_CRYPTO_USER_API_RNG is not set
+# CONFIG_CRYPTO_USER_API_AEAD is not set
+# CONFIG_CRYPTO_HW is not set
+# CONFIG_ASYMMETRIC_KEY_TYPE is not set
+
+#
+# Certificates for signature checking
+#
+# CONFIG_ARM_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_HAVE_ARCH_BITREVERSE=y
+CONFIG_RATIONAL=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_NET_UTILS=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IO=y
+CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=y
+# CONFIG_CRC8 is not set
+# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set
+# CONFIG_RANDOM32_SELFTEST is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_LZ4_DECOMPRESS=y
+CONFIG_XZ_DEC=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_BCJ=y
+# CONFIG_XZ_DEC_TEST is not set
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_LZ4=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_ASSOCIATIVE_ARRAY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_HAS_DMA=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
+# CONFIG_IRQ_POLL is not set
+CONFIG_LIBFDT=y
+CONFIG_OID_REGISTRY=y
+# CONFIG_SG_SPLIT is not set
+CONFIG_SG_POOL=y
+CONFIG_ARCH_HAS_SG_CHAIN=y
+CONFIG_SBITMAP=y
+# CONFIG_VIRTUALIZATION is not set
diff -urN linux-4.9.37/arch/arm/configs/gk7205v300_full_defconfig linux-4.9.y/arch/arm/configs/gk7205v300_full_defconfig
--- linux-4.9.37/arch/arm/configs/gk7205v300_full_defconfig 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/arch/arm/configs/gk7205v300_full_defconfig 2021-06-07 13:01:32.000000000 +0300
@@ -0,0 +1,2975 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/arm 4.9.37 Kernel Configuration
+#
+CONFIG_ARM=y
+CONFIG_ARM_HAS_SG_CHAIN=y
+CONFIG_MIGHT_HAVE_PCI=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_ARM_PATCH_PHYS_VIRT=y
+CONFIG_GENERIC_BUG=y
+CONFIG_PGTABLE_LEVELS=2
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_IRQ_WORK=y
+CONFIG_BUILDTIME_EXTABLE_SORT=y
+
+#
+# General setup
+#
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+# CONFIG_COMPILE_TEST is not set
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_HAVE_KERNEL_LZ4=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_XZ is not set
+# CONFIG_KERNEL_LZO is not set
+# CONFIG_KERNEL_LZ4 is not set
+CONFIG_DEFAULT_HOSTNAME="(none)"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_CROSS_MEMORY_ATTACH=y
+CONFIG_FHANDLE=y
+CONFIG_USELIB=y
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_ARCH_AUDITSYSCALL=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_IRQ_DOMAIN_HIERARCHY=y
+CONFIG_HANDLE_DOMAIN_IRQ=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_ARCH_CLOCKSOURCE_DATA=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+
+#
+# Timers subsystem
+#
+CONFIG_HZ_PERIODIC=y
+# CONFIG_NO_HZ_IDLE is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set
+# CONFIG_IRQ_TIME_ACCOUNTING is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TINY_RCU=y
+# CONFIG_RCU_EXPERT is not set
+CONFIG_SRCU=y
+# CONFIG_TASKS_RCU is not set
+# CONFIG_RCU_STALL_COMMON is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_RCU_EXPEDITE_BOOT is not set
+# CONFIG_BUILD_BIN2C is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_NMI_LOG_BUF_SHIFT=13
+CONFIG_GENERIC_SCHED_CLOCK=y
+CONFIG_CGROUPS=y
+# CONFIG_MEMCG is not set
+# CONFIG_BLK_CGROUP is not set
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUP_PIDS is not set
+CONFIG_CGROUP_FREEZER=y
+# CONFIG_CPUSETS is not set
+# CONFIG_CGROUP_DEVICE is not set
+# CONFIG_CGROUP_CPUACCT is not set
+# CONFIG_CGROUP_DEBUG is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+CONFIG_NAMESPACES=y
+CONFIG_UTS_NS=y
+CONFIG_IPC_NS=y
+# CONFIG_USER_NS is not set
+CONFIG_PID_NS=y
+CONFIG_NET_NS=y
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_RD_XZ is not set
+# CONFIG_RD_LZO is not set
+CONFIG_RD_LZ4=y
+CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_HAVE_UID16=y
+CONFIG_BPF=y
+# CONFIG_EXPERT is not set
+CONFIG_UID16=y
+CONFIG_MULTIUSER=y
+# CONFIG_SGETMASK_SYSCALL is not set
+CONFIG_SYSFS_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set
+CONFIG_KALLSYMS_BASE_RELATIVE=y
+CONFIG_PRINTK=y
+CONFIG_PRINTK_NMI=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+# CONFIG_BPF_SYSCALL is not set
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_ADVISE_SYSCALLS=y
+# CONFIG_USERFAULTFD is not set
+CONFIG_MEMBARRIER=y
+# CONFIG_EMBEDDED is not set
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLAB_FREELIST_RANDOM is not set
+# CONFIG_SYSTEM_DATA_VERIFICATION is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+# CONFIG_JUMP_LABEL is not set
+# CONFIG_UPROBES is not set
+# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_ARCH_USE_BUILTIN_BSWAP=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_NMI=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_IDLE_POLL_SETUP=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_HAVE_GCC_PLUGINS=y
+# CONFIG_GCC_PLUGINS is not set
+CONFIG_HAVE_CC_STACKPROTECTOR=y
+CONFIG_CC_STACKPROTECTOR=y
+# CONFIG_CC_STACKPROTECTOR_NONE is not set
+# CONFIG_CC_STACKPROTECTOR_REGULAR is not set
+CONFIG_CC_STACKPROTECTOR_STRONG=y
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_MODULES_USE_ELF_REL=y
+CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_HAVE_ARCH_MMAP_RND_BITS=y
+CONFIG_HAVE_EXIT_THREAD=y
+CONFIG_ARCH_MMAP_RND_BITS_MIN=8
+CONFIG_ARCH_MMAP_RND_BITS_MAX=16
+CONFIG_ARCH_MMAP_RND_BITS=8
+# CONFIG_HAVE_ARCH_HASH is not set
+# CONFIG_ISA_BUS_API is not set
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_OLD_SIGACTION=y
+# CONFIG_CPU_NO_EFFICIENT_FFS is not set
+# CONFIG_HAVE_ARCH_VMAP_STACK is not set
+
+#
+# GCOV-based kernel profiling
+#
+CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_MODULE_SIG is not set
+# CONFIG_MODULE_COMPRESS is not set
+# CONFIG_TRIM_UNUSED_KSYMS is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+CONFIG_BLK_DEV_BSG=y
+# CONFIG_BLK_DEV_BSGLIB is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+CONFIG_BLK_CMDLINE_PARSER=y
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_AIX_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_CMDLINE_PARTITION=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+CONFIG_INLINE_READ_UNLOCK=y
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+CONFIG_INLINE_WRITE_UNLOCK=y
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+CONFIG_MMU=y
+CONFIG_ARCH_MULTIPLATFORM=y
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_LPC32XX is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C24XX is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP1 is not set
+
+#
+# Multiple platform selection
+#
+
+#
+# CPU Core family selection
+#
+# CONFIG_ARCH_MULTI_V6 is not set
+CONFIG_ARCH_MULTI_V7=y
+CONFIG_ARCH_MULTI_V6_V7=y
+# CONFIG_ARCH_MULTI_CPU_AUTO is not set
+# CONFIG_ARCH_VIRT is not set
+# CONFIG_ARCH_MVEBU is not set
+# CONFIG_ARCH_ALPINE is not set
+# CONFIG_ARCH_ARTPEC is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_BCM is not set
+# CONFIG_ARCH_BERLIN is not set
+# CONFIG_ARCH_DIGICOLOR is not set
+# CONFIG_ARCH_HIGHBANK is not set
+# CONFIG_ARCH_HISI is not set
+CONFIG_ARCH_GOKE=y
+
+#
+# Goke platform type
+#
+# CONFIG_ARCH_GK7205V200 is not set
+CONFIG_ARCH_GK7205V300=y
+# CONFIG_ARCH_GK7202V300 is not set
+# CONFIG_ARCH_GK7605V100 is not set
+# CONFIG_GOKE_MC is not set
+CONFIG_BSP_ZRELADDR=0x40008000
+CONFIG_BSP_PARAMS_PHYS=0x00000100
+CONFIG_BSP_INITRD_PHYS=0x00800000
+# CONFIG_ARCH_KEYSTONE is not set
+# CONFIG_ARCH_MESON is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_MEDIATEK is not set
+
+#
+# TI OMAP/AM/DM/DRA Family
+#
+# CONFIG_ARCH_OMAP3 is not set
+# CONFIG_ARCH_OMAP4 is not set
+# CONFIG_SOC_OMAP5 is not set
+# CONFIG_SOC_AM33XX is not set
+# CONFIG_SOC_AM43XX is not set
+# CONFIG_SOC_DRA7XX is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_QCOM is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_ROCKCHIP is not set
+# CONFIG_ARCH_SOCFPGA is not set
+# CONFIG_PLAT_SPEAR is not set
+# CONFIG_ARCH_STI is not set
+# CONFIG_ARCH_S5PV210 is not set
+# CONFIG_ARCH_EXYNOS is not set
+# CONFIG_ARCH_RENESAS is not set
+# CONFIG_ARCH_SUNXI is not set
+# CONFIG_ARCH_SIRF is not set
+# CONFIG_ARCH_TANGO is not set
+# CONFIG_ARCH_TEGRA is not set
+# CONFIG_ARCH_UNIPHIER is not set
+# CONFIG_ARCH_U8500 is not set
+# CONFIG_ARCH_VEXPRESS is not set
+# CONFIG_ARCH_WM8850 is not set
+# CONFIG_ARCH_ZX is not set
+# CONFIG_ARCH_ZYNQ is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_V7=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_LPAE is not set
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+CONFIG_ARM_THUMB=y
+# CONFIG_ARM_THUMBEE is not set
+CONFIG_ARM_VIRT_EXT=y
+# CONFIG_SWP_EMULATE is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_KUSER_HELPERS=y
+CONFIG_VDSO=y
+CONFIG_MIGHT_HAVE_CACHE_L2X0=y
+# CONFIG_CACHE_L2X0 is not set
+CONFIG_ARM_L1_CACHE_SHIFT_6=y
+CONFIG_ARM_L1_CACHE_SHIFT=6
+CONFIG_ARM_DMA_MEM_BUFFERABLE=y
+# CONFIG_DEBUG_RODATA is not set
+CONFIG_MULTI_IRQ_HANDLER=y
+# CONFIG_ARM_ERRATA_430973 is not set
+# CONFIG_ARM_ERRATA_720789 is not set
+# CONFIG_ARM_ERRATA_754322 is not set
+# CONFIG_ARM_ERRATA_775420 is not set
+# CONFIG_ARM_ERRATA_773022 is not set
+# CONFIG_ARM_ERRATA_818325_852422 is not set
+# CONFIG_ARM_ERRATA_821420 is not set
+# CONFIG_ARM_ERRATA_825619 is not set
+# CONFIG_ARM_ERRATA_852421 is not set
+# CONFIG_ARM_ERRATA_852423 is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS_GENERIC is not set
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_HAVE_SMP=y
+# CONFIG_SMP is not set
+CONFIG_HAVE_ARM_ARCH_TIMER=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_3G_OPT is not set
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_ARM_PSCI is not set
+CONFIG_ARCH_NR_GPIO=0
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ_FIXED=0
+CONFIG_HZ_100=y
+# CONFIG_HZ_200 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_500 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
+# CONFIG_SCHED_HRTICK is not set
+# CONFIG_THUMB2_KERNEL is not set
+CONFIG_ARM_PATCH_IDIV=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_HAVE_ARCH_PFN_VALID=y
+# CONFIG_HIGHMEM is not set
+# CONFIG_CPU_SW_DOMAIN_PAN is not set
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+# CONFIG_ARM_MODULE_PLTS is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_NO_BOOTMEM=y
+# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_COMPACTION=y
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NEED_PER_CPU_KM=y
+# CONFIG_CLEANCACHE is not set
+# CONFIG_CMA is not set
+# CONFIG_ZPOOL is not set
+# CONFIG_ZBUD is not set
+# CONFIG_ZSMALLOC is not set
+CONFIG_GENERIC_EARLY_IOREMAP=y
+# CONFIG_IDLE_PAGE_TRACKING is not set
+CONFIG_FRAME_VECTOR=y
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+# CONFIG_SECCOMP is not set
+CONFIG_SWIOTLB=y
+CONFIG_IOMMU_HELPER=y
+# CONFIG_PARAVIRT is not set
+# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set
+# CONFIG_XEN is not set
+
+#
+# Boot options
+#
+CONFIG_USE_OF=y
+CONFIG_ATAGS=y
+# CONFIG_DEPRECATED_PARAM_STRUCT is not set
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER=y
+# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set
+CONFIG_CMDLINE=""
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_AUTO_ZRELADDR=y
+# CONFIG_EFI is not set
+
+#
+# CPU Power Management
+#
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# CPU Idle
+#
+# CONFIG_CPU_IDLE is not set
+# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+# CONFIG_KERNEL_MODE_NEON is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_ELFCORE=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
+CONFIG_BINFMT_SCRIPT=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_COREDUMP=y
+
+#
+# Power management options
+#
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_PM_SLEEP=y
+# CONFIG_PM_AUTOSLEEP is not set
+# CONFIG_PM_WAKELOCKS is not set
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_APM_EMULATION is not set
+CONFIG_PM_CLK=y
+# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_CPU_PM=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARM_CPU_SUSPEND=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_DIAG is not set
+CONFIG_UNIX=y
+# CONFIG_UNIX_DIAG is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_ALGO=y
+CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+# CONFIG_IP_FIB_TRIE_STATS is not set
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
+# CONFIG_NET_IP_TUNNEL is not set
+CONFIG_IP_MROUTE=y
+# CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_NET_UDP_TUNNEL is not set
+# CONFIG_NET_FOU is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_INET_UDP_DIAG is not set
+# CONFIG_INET_DIAG_DESTROY is not set
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BIC=m
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+# CONFIG_TCP_CONG_HSTCP is not set
+# CONFIG_TCP_CONG_HYBLA is not set
+# CONFIG_TCP_CONG_VEGAS is not set
+# CONFIG_TCP_CONG_NV is not set
+# CONFIG_TCP_CONG_SCALABLE is not set
+# CONFIG_TCP_CONG_LP is not set
+# CONFIG_TCP_CONG_VENO is not set
+# CONFIG_TCP_CONG_YEAH is not set
+# CONFIG_TCP_CONG_ILLINOIS is not set
+# CONFIG_TCP_CONG_DCTCP is not set
+# CONFIG_TCP_CONG_CDG is not set
+# CONFIG_TCP_CONG_BBR is not set
+CONFIG_DEFAULT_CUBIC=y
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NET_PTP_CLASSIFY is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP is not set
+# CONFIG_BRIDGE is not set
+CONFIG_HAVE_NET_DSA=y
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+CONFIG_DNS_RESOLVER=y
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+# CONFIG_VSOCKETS is not set
+# CONFIG_NETLINK_DIAG is not set
+# CONFIG_MPLS is not set
+# CONFIG_HSR is not set
+# CONFIG_NET_SWITCHDEV is not set
+# CONFIG_NET_L3_MASTER_DEV is not set
+# CONFIG_NET_NCSI is not set
+# CONFIG_SOCK_CGROUP_DATA is not set
+# CONFIG_CGROUP_NET_PRIO is not set
+# CONFIG_CGROUP_NET_CLASSID is not set
+CONFIG_NET_RX_BUSY_POLL=y
+CONFIG_BQL=y
+# CONFIG_BPF_JIT is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_AF_KCM is not set
+# CONFIG_STREAM_PARSER is not set
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_CFG80211=m
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+CONFIG_CFG80211_DEFAULT_PS=y
+# CONFIG_CFG80211_INTERNAL_REGDB is not set
+CONFIG_CFG80211_CRDA_SUPPORT=y
+CONFIG_CFG80211_WEXT=y
+# CONFIG_LIB80211 is not set
+CONFIG_MAC80211=m
+CONFIG_MAC80211_HAS_RC=y
+CONFIG_MAC80211_RC_MINSTREL=y
+CONFIG_MAC80211_RC_MINSTREL_HT=y
+# CONFIG_MAC80211_RC_MINSTREL_VHT is not set
+CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y
+CONFIG_MAC80211_RC_DEFAULT="minstrel_ht"
+CONFIG_MAC80211_MESH=y
+# CONFIG_MAC80211_MESSAGE_TRACING is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+CONFIG_MAC80211_STA_HASH_MAX_SIZE=0
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+# CONFIG_LWTUNNEL is not set
+# CONFIG_DST_CACHE is not set
+# CONFIG_NET_DEVLINK is not set
+CONFIG_MAY_USE_DEVLINK=y
+CONFIG_HAVE_CBPF_JIT=y
+
+#
+# Device Drivers
+#
+CONFIG_ARM_AMBA=y
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set
+CONFIG_ALLOW_DEV_COREDUMP=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+CONFIG_REGMAP=y
+CONFIG_REGMAP_I2C=y
+CONFIG_REGMAP_SPI=y
+CONFIG_REGMAP_MMIO=y
+CONFIG_DMA_SHARED_BUFFER=y
+# CONFIG_FENCE_TRACE is not set
+
+#
+# Bus devices
+#
+# CONFIG_BRCMSTB_GISB_ARB is not set
+# CONFIG_VEXPRESS_CONFIG is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+CONFIG_MTD_OF_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
+# CONFIG_MTD_OOPS is not set
+# CONFIG_MTD_PARTITIONED_MASTER is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SST25L is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOCG3 is not set
+CONFIG_MTD_NAND_ECC=y
+# CONFIG_MTD_NAND_ECC_SMC is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_ECC_BCH is not set
+# CONFIG_MTD_SM_COMMON is not set
+# CONFIG_MTD_NAND_DENALI_DT is not set
+# CONFIG_MTD_NAND_GPIO is not set
+# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_DOCG4 is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_BRCMNAND is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_NAND_HISI504 is not set
+# CONFIG_MTD_NAND_MTK is not set
+CONFIG_MTD_SPI_NAND_GOKE=y
+# CONFIG_GOKE_NAND_ECC_STATUS_REPORT is not set
+# CONFIG_GOKE_NAND_FS_MAY_NO_YAFFS2 is not set
+CONFIG_MTD_SPI_NAND_FMC100=y
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR & LPDDR2 PCM memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_LPDDR2_NVM is not set
+CONFIG_MTD_SPI_NOR=y
+# CONFIG_MTD_MT81xx_NOR is not set
+# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
+# CONFIG_SPI_CADENCE_QUADSPI is not set
+CONFIG_SPI_GOKE_SFC=y
+# CONFIG_CLOSE_SPI_8PIN_4IO is not set
+CONFIG_GOKE_SPI_BLOCK_PROTECT=y
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_LIMIT=20
+# CONFIG_MTD_UBI_FASTMAP is not set
+# CONFIG_MTD_UBI_GLUEBI is not set
+# CONFIG_MTD_UBI_BLOCK is not set
+CONFIG_DTC=y
+CONFIG_OF=y
+# CONFIG_OF_UNITTEST is not set
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_NET=y
+CONFIG_OF_MDIO=y
+CONFIG_OF_RESERVED_MEM=y
+# CONFIG_OF_OVERLAY is not set
+CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_NULL_BLK is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_DRBD is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=65536
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MG_DISK is not set
+# CONFIG_BLK_DEV_RBD is not set
+# CONFIG_NVME_TARGET is not set
+
+#
+# Misc devices
+#
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_DUMMY_IRQ is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_APDS9802ALS is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_ISL29020 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_BH1770 is not set
+# CONFIG_SENSORS_APDS990X is not set
+# CONFIG_HMC6352 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_TI_DAC7512 is not set
+# CONFIG_USB_SWITCH_FSA9480 is not set
+# CONFIG_LATTICE_ECP3_CONFIG is not set
+# CONFIG_SRAM is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_EEPROM_93XX46 is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+# CONFIG_SENSORS_LIS3_SPI is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
+
+#
+# Altera FPGA firmware download module
+#
+# CONFIG_ALTERA_STAPL is not set
+
+#
+# Intel MIC Bus Driver
+#
+
+#
+# SCIF Bus Driver
+#
+
+#
+# VOP Bus Driver
+#
+
+#
+# Intel MIC Host Driver
+#
+
+#
+# Intel MIC Card Driver
+#
+
+#
+# SCIF Driver
+#
+
+#
+# Intel MIC Coprocessor State Management (COSM) Drivers
+#
+
+#
+# VOP Driver
+#
+# CONFIG_ECHO is not set
+# CONFIG_CXL_BASE is not set
+# CONFIG_CXL_AFU_DRIVER_OPS is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+CONFIG_SCSI_NETLINK=y
+# CONFIG_SCSI_MQ_DEFAULT is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+CONFIG_SCSI_FC_ATTRS=y
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_ISCSI_BOOT_SYSFS is not set
+# CONFIG_SCSI_UFSHCD is not set
+# CONFIG_LIBFC is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_TARGET_CORE is not set
+CONFIG_NETDEVICES=y
+CONFIG_NET_CORE=y
+# CONFIG_BONDING is not set
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_NET_TEAM is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_VXLAN is not set
+# CONFIG_MACSEC is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_TUN is not set
+# CONFIG_TUN_VNET_CROSS_LE is not set
+# CONFIG_VETH is not set
+# CONFIG_NLMON is not set
+
+#
+# CAIF transport drivers
+#
+
+#
+# Distributed Switch Architecture drivers
+#
+CONFIG_ETHERNET=y
+# CONFIG_ALTERA_TSE is not set
+# CONFIG_NET_VENDOR_AMAZON is not set
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_AURORA is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_DM9000 is not set
+# CONFIG_DNET is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_HISILICON is not set
+CONFIG_NET_VENDOR_GOKE=y
+CONFIG_GOKE_FEMAC=y
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+CONFIG_NET_VENDOR_MICROCHIP=y
+# CONFIG_ENC28J60 is not set
+# CONFIG_ENCX24J600 is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
+# CONFIG_ETHOC is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_PHYLIB=y
+CONFIG_SWPHY=y
+
+#
+# MDIO bus device drivers
+#
+# CONFIG_MDIO_BCM_UNIMAC is not set
+# CONFIG_MDIO_BITBANG is not set
+# CONFIG_MDIO_BUS_MUX_GPIO is not set
+# CONFIG_MDIO_BUS_MUX_MMIOREG is not set
+CONFIG_MDIO_GOKE_FEMAC=y
+# CONFIG_MDIO_HISI_FEMAC is not set
+
+#
+# MII PHY device drivers
+#
+# CONFIG_AMD_PHY is not set
+# CONFIG_AQUANTIA_PHY is not set
+# CONFIG_AT803X_PHY is not set
+# CONFIG_BCM7XXX_PHY is not set
+# CONFIG_BCM87XX_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_DP83848_PHY is not set
+# CONFIG_DP83867_PHY is not set
+CONFIG_FIXED_PHY=y
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_INTEL_XWAY_PHY is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_MICREL_PHY is not set
+# CONFIG_MICROCHIP_PHY is not set
+# CONFIG_MICROSEMI_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_TERANETICS_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_XILINX_GMII2RGMII is not set
+# CONFIG_MICREL_KS8995MA is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_USB_NET_DRIVERS is not set
+# CONFIG_WLAN is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_ISDN is not set
+# CONFIG_NVM is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+# CONFIG_INPUT_MATRIXKMAP is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ADP5588 is not set
+# CONFIG_KEYBOARD_ADP5589 is not set
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_QT1070 is not set
+# CONFIG_KEYBOARD_QT2160 is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_KEYBOARD_GPIO_POLLED is not set
+# CONFIG_KEYBOARD_TCA6416 is not set
+# CONFIG_KEYBOARD_TCA8418 is not set
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_LM8333 is not set
+# CONFIG_KEYBOARD_MAX7359 is not set
+# CONFIG_KEYBOARD_MCS is not set
+# CONFIG_KEYBOARD_MPR121 is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_SAMSUNG is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_OMAP4 is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_CAP11XX is not set
+# CONFIG_KEYBOARD_BCM is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_BYD=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_CYPRESS=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_SENTELIC is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+CONFIG_MOUSE_PS2_FOCALTECH=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_CYAPA is not set
+# CONFIG_MOUSE_ELAN_I2C is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+# CONFIG_MOUSE_SYNAPTICS_I2C is not set
+# CONFIG_MOUSE_SYNAPTICS_USB is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_AD714X is not set
+# CONFIG_INPUT_ATMEL_CAPTOUCH is not set
+# CONFIG_INPUT_BMA150 is not set
+# CONFIG_INPUT_E3X0_BUTTON is not set
+# CONFIG_INPUT_MMA8450 is not set
+# CONFIG_INPUT_MPU3050 is not set
+# CONFIG_INPUT_GP2A is not set
+# CONFIG_INPUT_GPIO_BEEPER is not set
+# CONFIG_INPUT_GPIO_TILT_POLLED is not set
+# CONFIG_INPUT_GPIO_DECODER is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_KXTJ9 is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
+CONFIG_INPUT_UINPUT=y
+# CONFIG_INPUT_PCF8574 is not set
+# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
+# CONFIG_INPUT_ADXL34X is not set
+# CONFIG_INPUT_CMA3000 is not set
+# CONFIG_INPUT_DRV260X_HAPTICS is not set
+# CONFIG_INPUT_DRV2665_HAPTICS is not set
+# CONFIG_INPUT_DRV2667_HAPTICS is not set
+# CONFIG_RMI4_CORE is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_AMBAKMI is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_ALTERA_PS2 is not set
+# CONFIG_SERIO_PS2MULT is not set
+# CONFIG_SERIO_ARC_PS2 is not set
+# CONFIG_SERIO_APBPS2 is not set
+# CONFIG_USERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_TTY=y
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_VT_CONSOLE_SLEEP=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVMEM=y
+# CONFIG_DEVKMEM is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_EARLYCON=y
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_AMBA_PL010 is not set
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set
+# CONFIG_SERIAL_MAX3100 is not set
+# CONFIG_SERIAL_MAX310X is not set
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_SCCNXP is not set
+# CONFIG_SERIAL_SC16IS7XX is not set
+# CONFIG_SERIAL_BCM63XX is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_IFX6X60 is not set
+# CONFIG_SERIAL_XILINX_PS_UART is not set
+# CONFIG_SERIAL_ARC is not set
+# CONFIG_SERIAL_FSL_LPUART is not set
+# CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set
+# CONFIG_SERIAL_ST_ASC is not set
+# CONFIG_SERIAL_STM32 is not set
+# CONFIG_HVC_DCC is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_XILLYBUS is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MUX=y
+
+#
+# Multiplexer I2C Chip support
+#
+# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set
+# CONFIG_I2C_MUX_GPIO is not set
+# CONFIG_I2C_MUX_PCA9541 is not set
+# CONFIG_I2C_MUX_PCA954x is not set
+# CONFIG_I2C_MUX_PINCTRL is not set
+# CONFIG_I2C_MUX_REG is not set
+# CONFIG_I2C_DEMUX_PINCTRL is not set
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_CBUS_GPIO is not set
+# CONFIG_I2C_DESIGNWARE_PLATFORM is not set
+# CONFIG_I2C_EMEV2 is not set
+# CONFIG_I2C_GPIO is not set
+CONFIG_I2C_GOKE=y
+# CONFIG_I2C_NOMADIK is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_PXA_PCI is not set
+# CONFIG_I2C_RK3X is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_DIOLAN_U2C is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_ROBOTFUZZ_OSIF is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+CONFIG_DMA_MSG_MIN_LEN=5
+CONFIG_DMA_MSG_MAX_LEN=4090
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_SLAVE is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_ALTERA is not set
+# CONFIG_SPI_AXI_SPI_ENGINE is not set
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_CADENCE is not set
+# CONFIG_SPI_DESIGNWARE is not set
+# CONFIG_SPI_GPIO is not set
+# CONFIG_SPI_FSL_SPI is not set
+# CONFIG_SPI_OC_TINY is not set
+CONFIG_SPI_PL022=y
+# CONFIG_SPI_PXA2XX_PCI is not set
+# CONFIG_SPI_ROCKCHIP is not set
+# CONFIG_SPI_SC18IS602 is not set
+# CONFIG_SPI_XCOMM is not set
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_ZYNQMP_GQSPI is not set
+
+#
+# SPI Protocol Masters
+#
+CONFIG_SPI_SPIDEV=y
+# CONFIG_SPI_LOOPBACK_TEST is not set
+# CONFIG_SPI_TLE62X0 is not set
+# CONFIG_SPMI is not set
+# CONFIG_HSI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+# CONFIG_PTP_1588_CLOCK is not set
+
+#
+# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
+#
+CONFIG_PINCTRL=y
+
+#
+# Pin controllers
+#
+CONFIG_PINMUX=y
+CONFIG_PINCONF=y
+CONFIG_GENERIC_PINCONF=y
+# CONFIG_DEBUG_PINCTRL is not set
+# CONFIG_PINCTRL_AMD is not set
+CONFIG_PINCTRL_SINGLE=y
+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
+CONFIG_GPIOLIB=y
+CONFIG_OF_GPIO=y
+CONFIG_GPIOLIB_IRQCHIP=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO drivers
+#
+# CONFIG_GPIO_74XX_MMIO is not set
+# CONFIG_GPIO_ALTERA is not set
+# CONFIG_GPIO_DWAPB is not set
+# CONFIG_GPIO_EM is not set
+# CONFIG_GPIO_GENERIC_PLATFORM is not set
+# CONFIG_GPIO_GRGPIO is not set
+# CONFIG_GPIO_MOCKUP is not set
+# CONFIG_GPIO_MPC8XXX is not set
+CONFIG_GPIO_PL061=y
+# CONFIG_GPIO_SYSCON is not set
+# CONFIG_GPIO_XILINX is not set
+# CONFIG_GPIO_ZEVIO is not set
+# CONFIG_GPIO_ZX is not set
+
+#
+# I2C GPIO expanders
+#
+# CONFIG_GPIO_ADP5588 is not set
+# CONFIG_GPIO_ADNP is not set
+# CONFIG_GPIO_MAX7300 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_SX150X is not set
+# CONFIG_GPIO_TPIC2810 is not set
+# CONFIG_GPIO_TS4900 is not set
+
+#
+# MFD GPIO expanders
+#
+# CONFIG_HTC_EGPIO is not set
+
+#
+# SPI GPIO expanders
+#
+# CONFIG_GPIO_74X164 is not set
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MC33880 is not set
+# CONFIG_GPIO_PISOSR is not set
+
+#
+# SPI or I2C GPIO expanders
+#
+# CONFIG_GPIO_MCP23S08 is not set
+
+#
+# USB GPIO expanders
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_AVS is not set
+CONFIG_POWER_RESET=y
+# CONFIG_POWER_RESET_BRCMKONA is not set
+# CONFIG_POWER_RESET_BRCMSTB is not set
+CONFIG_POWER_RESET_GOKE=y
+# CONFIG_POWER_RESET_GPIO is not set
+# CONFIG_POWER_RESET_GPIO_RESTART is not set
+# CONFIG_POWER_RESET_LTC2952 is not set
+# CONFIG_POWER_RESET_RESTART is not set
+# CONFIG_POWER_RESET_VERSATILE is not set
+# CONFIG_POWER_RESET_SYSCON is not set
+# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set
+# CONFIG_SYSCON_REBOOT_MODE is not set
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_TEST_POWER is not set
+# CONFIG_BATTERY_DS2780 is not set
+# CONFIG_BATTERY_DS2781 is not set
+# CONFIG_BATTERY_DS2782 is not set
+# CONFIG_BATTERY_SBS is not set
+# CONFIG_BATTERY_BQ27XXX is not set
+# CONFIG_BATTERY_MAX17040 is not set
+# CONFIG_BATTERY_MAX17042 is not set
+# CONFIG_CHARGER_MAX8903 is not set
+# CONFIG_CHARGER_LP8727 is not set
+# CONFIG_CHARGER_GPIO is not set
+# CONFIG_CHARGER_BQ2415X is not set
+# CONFIG_CHARGER_BQ24190 is not set
+# CONFIG_CHARGER_BQ24257 is not set
+# CONFIG_CHARGER_BQ24735 is not set
+# CONFIG_CHARGER_BQ25890 is not set
+# CONFIG_CHARGER_SMB347 is not set
+# CONFIG_BATTERY_GAUGE_LTC2941 is not set
+# CONFIG_CHARGER_RT9455 is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+CONFIG_MFD_CORE=y
+# CONFIG_MFD_ACT8945A is not set
+# CONFIG_MFD_AS3711 is not set
+# CONFIG_MFD_AS3722 is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_AAT2870_CORE is not set
+# CONFIG_MFD_ATMEL_FLEXCOM is not set
+# CONFIG_MFD_ATMEL_HLCDC is not set
+# CONFIG_MFD_BCM590XX is not set
+# CONFIG_MFD_AXP20X_I2C is not set
+# CONFIG_MFD_CROS_EC is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_DA9052_SPI is not set
+# CONFIG_MFD_DA9052_I2C is not set
+# CONFIG_MFD_DA9055 is not set
+# CONFIG_MFD_DA9062 is not set
+# CONFIG_MFD_DA9063 is not set
+# CONFIG_MFD_DA9150 is not set
+# CONFIG_MFD_DLN2 is not set
+# CONFIG_MFD_EXYNOS_LPASS is not set
+# CONFIG_MFD_MC13XXX_SPI is not set
+# CONFIG_MFD_MC13XXX_I2C is not set
+# CONFIG_MFD_HI6421_PMIC is not set
+CONFIG_MFD_GOKE_FMC=y
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_HTC_I2CPLD is not set
+# CONFIG_INTEL_SOC_PMIC is not set
+# CONFIG_MFD_KEMPLD is not set
+# CONFIG_MFD_88PM800 is not set
+# CONFIG_MFD_88PM805 is not set
+# CONFIG_MFD_88PM860X is not set
+# CONFIG_MFD_MAX14577 is not set
+# CONFIG_MFD_MAX77620 is not set
+# CONFIG_MFD_MAX77686 is not set
+# CONFIG_MFD_MAX77693 is not set
+# CONFIG_MFD_MAX77843 is not set
+# CONFIG_MFD_MAX8907 is not set
+# CONFIG_MFD_MAX8925 is not set
+# CONFIG_MFD_MAX8997 is not set
+# CONFIG_MFD_MAX8998 is not set
+# CONFIG_MFD_MT6397 is not set
+# CONFIG_MFD_MENF21BMC is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_MFD_VIPERBOARD is not set
+# CONFIG_MFD_RETU is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_PM8921_CORE is not set
+# CONFIG_MFD_RT5033 is not set
+# CONFIG_MFD_RTSX_USB is not set
+# CONFIG_MFD_RC5T583 is not set
+# CONFIG_MFD_RK808 is not set
+# CONFIG_MFD_RN5T618 is not set
+# CONFIG_MFD_SEC_CORE is not set
+# CONFIG_MFD_SI476X_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_SKY81452 is not set
+# CONFIG_MFD_SMSC is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_MFD_STMPE is not set
+CONFIG_MFD_SYSCON=y
+# CONFIG_MFD_TI_AM335X_TSCADC is not set
+# CONFIG_MFD_LP3943 is not set
+# CONFIG_MFD_LP8788 is not set
+# CONFIG_MFD_PALMAS is not set
+# CONFIG_TPS6105X is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TPS6507X is not set
+# CONFIG_MFD_TPS65086 is not set
+# CONFIG_MFD_TPS65090 is not set
+# CONFIG_MFD_TPS65217 is not set
+# CONFIG_MFD_TI_LP873X is not set
+# CONFIG_MFD_TPS65218 is not set
+# CONFIG_MFD_TPS6586X is not set
+# CONFIG_MFD_TPS65910 is not set
+# CONFIG_MFD_TPS65912_I2C is not set
+# CONFIG_MFD_TPS65912_SPI is not set
+# CONFIG_MFD_TPS80031 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_TWL6040_CORE is not set
+# CONFIG_MFD_WL1273_CORE is not set
+# CONFIG_MFD_LM3533 is not set
+# CONFIG_MFD_TC3589X is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_MFD_ARIZONA_I2C is not set
+# CONFIG_MFD_ARIZONA_SPI is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X_I2C is not set
+# CONFIG_MFD_WM831X_SPI is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8994 is not set
+# CONFIG_REGULATOR is not set
+CONFIG_MEDIA_SUPPORT=y
+
+#
+# Multimedia core support
+#
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set
+# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set
+# CONFIG_MEDIA_RADIO_SUPPORT is not set
+# CONFIG_MEDIA_SDR_SUPPORT is not set
+# CONFIG_MEDIA_RC_SUPPORT is not set
+# CONFIG_MEDIA_CONTROLLER is not set
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L2=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEOBUF2_CORE=y
+CONFIG_VIDEOBUF2_MEMOPS=y
+CONFIG_VIDEOBUF2_VMALLOC=y
+# CONFIG_TTPCI_EEPROM is not set
+
+#
+# Media drivers
+#
+CONFIG_MEDIA_USB_SUPPORT=y
+
+#
+# Webcam devices
+#
+CONFIG_USB_VIDEO_CLASS=y
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+CONFIG_USB_GSPCA=m
+# CONFIG_USB_M5602 is not set
+# CONFIG_USB_STV06XX is not set
+# CONFIG_USB_GL860 is not set
+# CONFIG_USB_GSPCA_BENQ is not set
+# CONFIG_USB_GSPCA_CONEX is not set
+# CONFIG_USB_GSPCA_CPIA1 is not set
+# CONFIG_USB_GSPCA_DTCS033 is not set
+# CONFIG_USB_GSPCA_ETOMS is not set
+# CONFIG_USB_GSPCA_FINEPIX is not set
+# CONFIG_USB_GSPCA_JEILINJ is not set
+# CONFIG_USB_GSPCA_JL2005BCD is not set
+# CONFIG_USB_GSPCA_KINECT is not set
+# CONFIG_USB_GSPCA_KONICA is not set
+# CONFIG_USB_GSPCA_MARS is not set
+# CONFIG_USB_GSPCA_MR97310A is not set
+# CONFIG_USB_GSPCA_NW80X is not set
+# CONFIG_USB_GSPCA_OV519 is not set
+# CONFIG_USB_GSPCA_OV534 is not set
+# CONFIG_USB_GSPCA_OV534_9 is not set
+# CONFIG_USB_GSPCA_PAC207 is not set
+# CONFIG_USB_GSPCA_PAC7302 is not set
+# CONFIG_USB_GSPCA_PAC7311 is not set
+# CONFIG_USB_GSPCA_SE401 is not set
+# CONFIG_USB_GSPCA_SN9C2028 is not set
+# CONFIG_USB_GSPCA_SN9C20X is not set
+# CONFIG_USB_GSPCA_SONIXB is not set
+# CONFIG_USB_GSPCA_SONIXJ is not set
+# CONFIG_USB_GSPCA_SPCA500 is not set
+# CONFIG_USB_GSPCA_SPCA501 is not set
+# CONFIG_USB_GSPCA_SPCA505 is not set
+# CONFIG_USB_GSPCA_SPCA506 is not set
+# CONFIG_USB_GSPCA_SPCA508 is not set
+# CONFIG_USB_GSPCA_SPCA561 is not set
+# CONFIG_USB_GSPCA_SPCA1528 is not set
+# CONFIG_USB_GSPCA_SQ905 is not set
+# CONFIG_USB_GSPCA_SQ905C is not set
+# CONFIG_USB_GSPCA_SQ930X is not set
+# CONFIG_USB_GSPCA_STK014 is not set
+# CONFIG_USB_GSPCA_STK1135 is not set
+# CONFIG_USB_GSPCA_STV0680 is not set
+# CONFIG_USB_GSPCA_SUNPLUS is not set
+# CONFIG_USB_GSPCA_T613 is not set
+# CONFIG_USB_GSPCA_TOPRO is not set
+# CONFIG_USB_GSPCA_TOUPTEK is not set
+# CONFIG_USB_GSPCA_TV8532 is not set
+# CONFIG_USB_GSPCA_VC032X is not set
+# CONFIG_USB_GSPCA_VICAM is not set
+# CONFIG_USB_GSPCA_XIRLINK_CIT is not set
+# CONFIG_USB_GSPCA_ZC3XX is not set
+# CONFIG_USB_PWC is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_USB_ZR364XX is not set
+# CONFIG_USB_STKWEBCAM is not set
+# CONFIG_USB_S2255 is not set
+
+#
+# Webcam, TV (analog/digital) USB devices
+#
+# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_V4L_PLATFORM_DRIVERS is not set
+# CONFIG_V4L_MEM2MEM_DRIVERS is not set
+# CONFIG_V4L_TEST_DRIVERS is not set
+
+#
+# Supported MMC/SDIO adapters
+#
+# CONFIG_CYPRESS_FIRMWARE is not set
+
+#
+# Media ancillary drivers (tuners, sensors, i2c, spi, frontends)
+#
+CONFIG_MEDIA_SUBDRV_AUTOSELECT=y
+
+#
+# Audio decoders, processors and mixers
+#
+
+#
+# RDS decoders
+#
+
+#
+# Video decoders
+#
+
+#
+# Video and audio decoders
+#
+
+#
+# Video encoders
+#
+
+#
+# Camera sensor devices
+#
+
+#
+# Flash devices
+#
+
+#
+# Video improvement chips
+#
+
+#
+# Audio/Video compression chips
+#
+
+#
+# Miscellaneous helper chips
+#
+
+#
+# Sensors used on soc_camera driver
+#
+
+#
+# Tools to develop new frontends
+#
+# CONFIG_DVB_DUMMY_FE is not set
+
+#
+# Graphics support
+#
+# CONFIG_IMX_IPUV3_CORE is not set
+# CONFIG_DRM is not set
+
+#
+# ACP (Audio CoProcessor) Configuration
+#
+
+#
+# Frame buffer Devices
+#
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB_CMDLINE=y
+CONFIG_FB_NOTIFY=y
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_ARMCLCD is not set
+# CONFIG_FB_OPENCORES is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_SMSCUFX is not set
+# CONFIG_FB_UDL is not set
+# CONFIG_FB_IBM_GXT4500 is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_FB_AUO_K190X is not set
+# CONFIG_FB_SIMPLE is not set
+# CONFIG_FB_SSD1307 is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+# CONFIG_LOGO is not set
+# CONFIG_SOUND is not set
+
+#
+# HID support
+#
+CONFIG_HID=y
+# CONFIG_HID_BATTERY_STRENGTH is not set
+# CONFIG_HIDRAW is not set
+# CONFIG_UHID is not set
+CONFIG_HID_GENERIC=y
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_ACRUX is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_APPLEIR is not set
+# CONFIG_HID_AUREAL is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_BETOP_FF is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_CMEDIA is not set
+# CONFIG_HID_CP2112 is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EMS_FF is not set
+# CONFIG_HID_ELECOM is not set
+# CONFIG_HID_ELO is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_GEMBIRD is not set
+# CONFIG_HID_GFRM is not set
+# CONFIG_HID_HOLTEK is not set
+# CONFIG_HID_KEYTOUCH is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_UCLOGIC is not set
+# CONFIG_HID_WALTOP is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_ICADE is not set
+# CONFIG_HID_TWINHAN is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LCPOWER is not set
+# CONFIG_HID_LENOVO is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MAGICMOUSE is not set
+CONFIG_HID_MICROSOFT=y
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_MULTITOUCH is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_ORTEK is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PENMOUNT is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_PICOLCD is not set
+# CONFIG_HID_PLANTRONICS is not set
+# CONFIG_HID_PRIMAX is not set
+# CONFIG_HID_ROCCAT is not set
+# CONFIG_HID_SAITEK is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SPEEDLINK is not set
+# CONFIG_HID_STEELSERIES is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_RMI is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TIVO is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_WACOM is not set
+# CONFIG_HID_XINMO is not set
+# CONFIG_HID_ZEROPLUS is not set
+# CONFIG_HID_ZYDACRON is not set
+# CONFIG_HID_SENSOR_HUB is not set
+# CONFIG_HID_ALPS is not set
+
+#
+# USB HID support
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# I2C HID support
+#
+# CONFIG_I2C_HID is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_COMMON=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB=y
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEFAULT_PERSIST=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_PLATFORM=y
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+# CONFIG_USB_FOTG210_HCD is not set
+# CONFIG_USB_MAX3421_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HCD_TEST_MODE is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_REALTEK is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_STORAGE_ENE_UB6250 is not set
+# CONFIG_USB_UAS is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USBIP_CORE is not set
+# CONFIG_USB_MUSB_HDRC is not set
+CONFIG_USB_DWC3=y
+# CONFIG_USB_DWC3_HOST is not set
+# CONFIG_USB_DWC3_GADGET is not set
+CONFIG_USB_DWC3_DUAL_ROLE=y
+
+#
+# Platform Glue Driver Support
+#
+CONFIG_USB_DWC3_OF_SIMPLE=y
+# CONFIG_USB_DWC2 is not set
+# CONFIG_USB_CHIPIDEA is not set
+# CONFIG_USB_ISP1760 is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_EHSET_TEST_FIXTURE is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_YUREX is not set
+# CONFIG_USB_EZUSB_FX2 is not set
+# CONFIG_USB_HSIC_USB3503 is not set
+# CONFIG_USB_HSIC_USB4604 is not set
+# CONFIG_USB_LINK_LAYER_TEST is not set
+
+#
+# USB Physical Layer drivers
+#
+# CONFIG_USB_PHY is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_USB_ISP1301 is not set
+# CONFIG_USB_ULPI is not set
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2
+
+#
+# USB Peripheral Controller
+#
+# CONFIG_USB_FUSB300 is not set
+# CONFIG_USB_FOTG210_UDC is not set
+# CONFIG_USB_GR_UDC is not set
+# CONFIG_USB_R8A66597 is not set
+# CONFIG_USB_PXA27X is not set
+# CONFIG_USB_MV_UDC is not set
+# CONFIG_USB_MV_U3D is not set
+# CONFIG_USB_M66592 is not set
+# CONFIG_USB_BDC_UDC is not set
+# CONFIG_USB_NET2272 is not set
+# CONFIG_USB_GADGET_XILINX is not set
+# CONFIG_USB_DUMMY_HCD is not set
+CONFIG_USB_LIBCOMPOSITE=m
+CONFIG_USB_F_ACM=m
+CONFIG_USB_U_SERIAL=m
+CONFIG_USB_U_ETHER=m
+CONFIG_USB_F_ECM=m
+CONFIG_USB_F_RNDIS=m
+CONFIG_USB_F_MASS_STORAGE=m
+CONFIG_USB_CONFIGFS=m
+# CONFIG_USB_CONFIGFS_SERIAL is not set
+CONFIG_USB_CONFIGFS_ACM=y
+# CONFIG_USB_CONFIGFS_OBEX is not set
+# CONFIG_USB_CONFIGFS_NCM is not set
+CONFIG_USB_CONFIGFS_ECM=y
+# CONFIG_USB_CONFIGFS_ECM_SUBSET is not set
+CONFIG_USB_CONFIGFS_RNDIS=y
+# CONFIG_USB_CONFIGFS_EEM is not set
+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
+# CONFIG_USB_CONFIGFS_F_LB_SS is not set
+# CONFIG_USB_CONFIGFS_F_FS is not set
+# CONFIG_USB_CONFIGFS_F_HID is not set
+# CONFIG_USB_CONFIGFS_F_UVC is not set
+# CONFIG_USB_CONFIGFS_F_PRINTER is not set
+# CONFIG_USB_ULPI_BUS is not set
+# CONFIG_UWB is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_PWRSEQ_EMMC=y
+CONFIG_PWRSEQ_SIMPLE=y
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_MINORS=8
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_ARMMMCI is not set
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+# CONFIG_MMC_SDHCI_OF_ARASAN is not set
+# CONFIG_MMC_SDHCI_OF_AT91 is not set
+CONFIG_MMC_SDHCI_GOKE=y
+# CONFIG_MMC_SDHCI_F_SDH30 is not set
+# CONFIG_MMC_SPI is not set
+# CONFIG_MMC_DW is not set
+# CONFIG_MMC_VUB300 is not set
+# CONFIG_MMC_USHC is not set
+# CONFIG_MMC_USDHI6ROL0 is not set
+# CONFIG_MMC_MTK is not set
+# CONFIG_MMC_CQ_HCI is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_EDAC_ATOMIC_SCRUB=y
+CONFIG_EDAC_SUPPORT=y
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+CONFIG_RTC_SYSTOHC=y
+CONFIG_RTC_SYSTOHC_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_ABB5ZES3 is not set
+# CONFIG_RTC_DRV_ABX80X is not set
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_HYM8563 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_ISL12022 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8523 is not set
+# CONFIG_RTC_DRV_PCF85063 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_BQ32K is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8010 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+# CONFIG_RTC_DRV_EM3027 is not set
+# CONFIG_RTC_DRV_RV8803 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T93 is not set
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1302 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1343 is not set
+# CONFIG_RTC_DRV_DS1347 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6916 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RX4581 is not set
+# CONFIG_RTC_DRV_RX6110 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
+# CONFIG_RTC_DRV_MCP795 is not set
+CONFIG_RTC_I2C_AND_SPI=y
+
+#
+# SPI and I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS3232 is not set
+# CONFIG_RTC_DRV_PCF2127 is not set
+# CONFIG_RTC_DRV_RV3029C2 is not set
+
+#
+# Platform RTC drivers
+#
+CONFIG_RTC_DRV_GOKE=y
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1685_FAMILY is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_DS2404 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+# CONFIG_RTC_DRV_ZYNQMP is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_PL030 is not set
+# CONFIG_RTC_DRV_PL031 is not set
+# CONFIG_RTC_DRV_SNVS is not set
+
+#
+# HID Sensor RTC drivers
+#
+# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set
+# CONFIG_DMADEVICES is not set
+
+#
+# DMABUF options
+#
+# CONFIG_SYNC_FILE is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+# CONFIG_VIRT_DRIVERS is not set
+
+#
+# Virtio drivers
+#
+# CONFIG_VIRTIO_MMIO is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_STAGING is not set
+# CONFIG_GOLDFISH is not set
+# CONFIG_CHROME_PLATFORMS is not set
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_COMMON_CLK=y
+
+#
+# Common Clock Framework
+#
+# CONFIG_COMMON_CLK_SI5351 is not set
+# CONFIG_COMMON_CLK_SI514 is not set
+# CONFIG_COMMON_CLK_SI570 is not set
+# CONFIG_COMMON_CLK_CDCE706 is not set
+# CONFIG_COMMON_CLK_CDCE925 is not set
+# CONFIG_COMMON_CLK_CS2000_CP is not set
+# CONFIG_CLK_QORIQ is not set
+# CONFIG_COMMON_CLK_NXP is not set
+# CONFIG_COMMON_CLK_PXA is not set
+# CONFIG_COMMON_CLK_PIC32 is not set
+CONFIG_COMMON_CLK_GK7205V300=y
+CONFIG_RESET_GOKE=y
+
+#
+# Hardware Spinlock drivers
+#
+
+#
+# Clock Source drivers
+#
+CONFIG_CLKSRC_OF=y
+CONFIG_CLKSRC_PROBE=y
+CONFIG_CLKSRC_MMIO=y
+CONFIG_ARM_ARCH_TIMER=y
+CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y
+# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS is not set
+CONFIG_ARM_TIMER_SP804=y
+# CONFIG_ATMEL_PIT is not set
+# CONFIG_SH_TIMER_CMT is not set
+# CONFIG_SH_TIMER_MTU2 is not set
+# CONFIG_SH_TIMER_TMU is not set
+# CONFIG_EM_TIMER_STI is not set
+# CONFIG_MAILBOX is not set
+# CONFIG_IOMMU_SUPPORT is not set
+
+#
+# Remoteproc drivers
+#
+# CONFIG_STE_MODEM_RPROC is not set
+
+#
+# Rpmsg drivers
+#
+
+#
+# SOC (System On Chip) specific Drivers
+#
+
+#
+# Broadcom SoC drivers
+#
+# CONFIG_SOC_BRCMSTB is not set
+# CONFIG_SUNXI_SRAM is not set
+# CONFIG_SOC_TI is not set
+# CONFIG_PM_DEVFREQ is not set
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
+# CONFIG_IIO is not set
+# CONFIG_PWM is not set
+CONFIG_IRQCHIP=y
+CONFIG_ARM_GIC=y
+CONFIG_ARM_GIC_MAX_NR=1
+# CONFIG_IPACK_BUS is not set
+CONFIG_RESET_CONTROLLER=y
+# CONFIG_RESET_ATH79 is not set
+# CONFIG_RESET_BERLIN is not set
+# CONFIG_RESET_LPC18XX is not set
+# CONFIG_RESET_MESON is not set
+# CONFIG_RESET_PISTACHIO is not set
+# CONFIG_RESET_SOCFPGA is not set
+# CONFIG_RESET_STM32 is not set
+# CONFIG_RESET_SUNXI is not set
+# CONFIG_TI_SYSCON_RESET is not set
+# CONFIG_RESET_ZYNQ is not set
+# CONFIG_FMC is not set
+
+#
+# PHY Subsystem
+#
+CONFIG_GENERIC_PHY=y
+# CONFIG_PHY_PXA_28NM_HSIC is not set
+# CONFIG_PHY_PXA_28NM_USB2 is not set
+# CONFIG_BCM_KONA_USB2_PHY is not set
+CONFIG_PHY_GOKE_USBP2=y
+# CONFIG_USB_MODE_OPTION is not set
+# CONFIG_POWERCAP is not set
+# CONFIG_MCB is not set
+
+#
+# Performance monitor support
+#
+# CONFIG_RAS is not set
+
+#
+# Android
+#
+# CONFIG_ANDROID is not set
+# CONFIG_NVMEM is not set
+# CONFIG_STM is not set
+# CONFIG_INTEL_TH is not set
+
+#
+# FPGA Configuration Support
+#
+# CONFIG_FPGA is not set
+
+#
+# goke driver support
+#
+
+#
+# Firmware Drivers
+#
+# CONFIG_FIRMWARE_MEMMAP is not set
+# CONFIG_FW_CFG_SYSFS is not set
+CONFIG_HAVE_ARM_SMCCC=y
+
+#
+# File systems
+#
+CONFIG_DCACHE_WORD_ACCESS=y
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_USE_FOR_EXT2=y
+# CONFIG_EXT4_FS_POSIX_ACL is not set
+# CONFIG_EXT4_FS_SECURITY is not set
+# CONFIG_EXT4_ENCRYPTION is not set
+# CONFIG_EXT4_DEBUG is not set
+CONFIG_JBD2=y
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+# CONFIG_F2FS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_EXPORTFS=y
+# CONFIG_EXPORTFS_BLOCK_OPS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_MANDATORY_FILE_LOCKING=y
+# CONFIG_FS_ENCRYPTION is not set
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_QUOTACTL is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+# CONFIG_OVERLAY_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_FAT_DEFAULT_UTF8 is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_PROC_CHILDREN is not set
+CONFIG_KERNFS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_TMPFS_XATTR=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=y
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ORANGEFS_FS is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_YAFFS_FS=y
+CONFIG_YAFFS_YAFFS1=y
+# CONFIG_YAFFS_9BYTE_TAGS is not set
+# CONFIG_YAFFS_DOES_ECC is not set
+CONFIG_YAFFS_YAFFS2=y
+CONFIG_YAFFS_AUTO_YAFFS2=y
+# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set
+# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
+# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set
+# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set
+# CONFIG_YAFFS_DISABLE_BACKGROUND is not set
+# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set
+CONFIG_YAFFS_XATTR=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+# CONFIG_JFFS2_LZMA is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_UBIFS_FS=y
+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_ATIME_SUPPORT is not set
+# CONFIG_LOGFS is not set
+CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX6FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_PSTORE is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V2=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+# CONFIG_NFS_SWAP is not set
+# CONFIG_NFS_V4_1 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFS_USE_LEGACY_DNS is not set
+CONFIG_NFS_USE_KERNEL_DNS=y
+# CONFIG_NFSD is not set
+CONFIG_GRACE_PERIOD=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_ACL_SUPPORT=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_DEBUG is not set
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=y
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+# CONFIG_NLS_MAC_ROMAN is not set
+# CONFIG_NLS_MAC_CELTIC is not set
+# CONFIG_NLS_MAC_CENTEURO is not set
+# CONFIG_NLS_MAC_CROATIAN is not set
+# CONFIG_NLS_MAC_CYRILLIC is not set
+# CONFIG_NLS_MAC_GAELIC is not set
+# CONFIG_NLS_MAC_GREEK is not set
+# CONFIG_NLS_MAC_ICELAND is not set
+# CONFIG_NLS_MAC_INUIT is not set
+# CONFIG_NLS_MAC_ROMANIAN is not set
+# CONFIG_NLS_MAC_TURKISH is not set
+CONFIG_NLS_UTF8=y
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+
+#
+# printk and dmesg options
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
+# CONFIG_BOOT_PRINTK_DELAY is not set
+
+#
+# Compile-time checks and compiler options
+#
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_READABLE_ASM is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_PAGE_OWNER is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_SECTION_MISMATCH_WARN_ONLY=y
+CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_DEBUG_KERNEL=y
+
+#
+# Memory Debugging
+#
+# CONFIG_PAGE_EXTENSION is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_PAGE_POISONING is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_SHIRQ is not set
+
+#
+# Debug Lockups and Hangs
+#
+# CONFIG_LOCKUP_DETECTOR is not set
+# CONFIG_DETECT_HUNG_TASK is not set
+# CONFIG_WQ_WATCHDOG is not set
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+CONFIG_PANIC_TIMEOUT=0
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHED_INFO is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_SCHED_STACK_END_CHECK is not set
+# CONFIG_DEBUG_TIMEKEEPING is not set
+# CONFIG_TIMER_STATS is not set
+
+#
+# Lock Debugging (spinlocks, mutexes, etc...)
+#
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_ATOMIC_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_LOCK_TORTURE_TEST is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_PI_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+
+#
+# RCU Debugging
+#
+# CONFIG_PROVE_RCU is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_TORTURE_TEST is not set
+# CONFIG_RCU_PERF_TEST is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_TRACE is not set
+# CONFIG_RCU_EQS_DEBUG is not set
+# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_NOTIFIER_ERROR_INJECTION is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+
+#
+# Runtime Testing
+#
+# CONFIG_TEST_LIST_SORT is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_RBTREE_TEST is not set
+# CONFIG_INTERVAL_TREE_TEST is not set
+# CONFIG_PERCPU_TEST is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_TEST_HEXDUMP is not set
+# CONFIG_TEST_STRING_HELPERS is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_TEST_PRINTF is not set
+# CONFIG_TEST_BITMAP is not set
+# CONFIG_TEST_UUID is not set
+# CONFIG_TEST_RHASHTABLE is not set
+# CONFIG_TEST_HASH is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_TEST_LKM is not set
+# CONFIG_TEST_USER_COPY is not set
+# CONFIG_TEST_BPF is not set
+# CONFIG_TEST_FIRMWARE is not set
+# CONFIG_TEST_UDELAY is not set
+# CONFIG_MEMTEST is not set
+# CONFIG_TEST_STATIC_KEYS is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set
+# CONFIG_UBSAN is not set
+CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
+CONFIG_STRICT_DEVMEM=y
+# CONFIG_IO_STRICT_DEVMEM is not set
+# CONFIG_ARM_PTDUMP is not set
+# CONFIG_ARM_UNWIND is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_LL is not set
+CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
+# CONFIG_DEBUG_UART_8250 is not set
+CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
+# CONFIG_PID_IN_CONTEXTIDR is not set
+# CONFIG_DEBUG_SET_MODULE_RONX is not set
+# CONFIG_CORESIGHT is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_PERSISTENT_KEYRINGS is not set
+# CONFIG_ENCRYPTED_KEYS is not set
+# CONFIG_KEY_DH_OPERATIONS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y
+CONFIG_HAVE_ARCH_HARDENED_USERCOPY=y
+# CONFIG_HARDENED_USERCOPY is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_RNG_DEFAULT=m
+CONFIG_CRYPTO_AKCIPHER2=y
+CONFIG_CRYPTO_KPP2=y
+# CONFIG_CRYPTO_RSA is not set
+# CONFIG_CRYPTO_DH is not set
+# CONFIG_CRYPTO_ECDH is not set
+CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_USER is not set
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_NULL2=y
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_MCRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+# CONFIG_CRYPTO_CHACHA20POLY1305 is not set
+CONFIG_CRYPTO_SEQIV=m
+CONFIG_CRYPTO_ECHAINIV=m
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+CONFIG_CRYPTO_CTR=m
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+# CONFIG_CRYPTO_KEYWRAP is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_CMAC is not set
+CONFIG_CRYPTO_HMAC=m
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_CRC32 is not set
+CONFIG_CRYPTO_CRCT10DIF=y
+CONFIG_CRYPTO_GHASH=m
+# CONFIG_CRYPTO_POLY1305 is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=y
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_SHA3 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_CHACHA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_LZO=y
+# CONFIG_CRYPTO_842 is not set
+# CONFIG_CRYPTO_LZ4 is not set
+# CONFIG_CRYPTO_LZ4HC is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_DRBG_MENU=m
+CONFIG_CRYPTO_DRBG_HMAC=y
+# CONFIG_CRYPTO_DRBG_HASH is not set
+# CONFIG_CRYPTO_DRBG_CTR is not set
+CONFIG_CRYPTO_DRBG=m
+CONFIG_CRYPTO_JITTERENTROPY=m
+# CONFIG_CRYPTO_USER_API_HASH is not set
+# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
+# CONFIG_CRYPTO_USER_API_RNG is not set
+# CONFIG_CRYPTO_USER_API_AEAD is not set
+# CONFIG_CRYPTO_HW is not set
+# CONFIG_ASYMMETRIC_KEY_TYPE is not set
+
+#
+# Certificates for signature checking
+#
+# CONFIG_ARM_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_HAVE_ARCH_BITREVERSE=y
+CONFIG_RATIONAL=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_NET_UTILS=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IO=y
+CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=y
+# CONFIG_CRC8 is not set
+# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set
+# CONFIG_RANDOM32_SELFTEST is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_LZ4_DECOMPRESS=y
+CONFIG_XZ_DEC=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_BCJ=y
+# CONFIG_XZ_DEC_TEST is not set
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_LZ4=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_ASSOCIATIVE_ARRAY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_HAS_DMA=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
+# CONFIG_IRQ_POLL is not set
+CONFIG_LIBFDT=y
+CONFIG_OID_REGISTRY=y
+# CONFIG_SG_SPLIT is not set
+CONFIG_SG_POOL=y
+CONFIG_ARCH_HAS_SG_CHAIN=y
+CONFIG_SBITMAP=y
+# CONFIG_VIRTUALIZATION is not set
diff -urN linux-4.9.37/arch/arm/configs/gk7605v100_emmc_defconfig linux-4.9.y/arch/arm/configs/gk7605v100_emmc_defconfig
--- linux-4.9.37/arch/arm/configs/gk7605v100_emmc_defconfig 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/arch/arm/configs/gk7605v100_emmc_defconfig 2021-06-07 13:01:32.000000000 +0300
@@ -0,0 +1,2975 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/arm 4.9.37 Kernel Configuration
+#
+CONFIG_ARM=y
+CONFIG_ARM_HAS_SG_CHAIN=y
+CONFIG_MIGHT_HAVE_PCI=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_ARM_PATCH_PHYS_VIRT=y
+CONFIG_GENERIC_BUG=y
+CONFIG_PGTABLE_LEVELS=2
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_IRQ_WORK=y
+CONFIG_BUILDTIME_EXTABLE_SORT=y
+
+#
+# General setup
+#
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+# CONFIG_COMPILE_TEST is not set
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_HAVE_KERNEL_LZ4=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_XZ is not set
+# CONFIG_KERNEL_LZO is not set
+# CONFIG_KERNEL_LZ4 is not set
+CONFIG_DEFAULT_HOSTNAME="(none)"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_CROSS_MEMORY_ATTACH=y
+CONFIG_FHANDLE=y
+CONFIG_USELIB=y
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_ARCH_AUDITSYSCALL=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_IRQ_DOMAIN_HIERARCHY=y
+CONFIG_HANDLE_DOMAIN_IRQ=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_ARCH_CLOCKSOURCE_DATA=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+
+#
+# Timers subsystem
+#
+CONFIG_HZ_PERIODIC=y
+# CONFIG_NO_HZ_IDLE is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set
+# CONFIG_IRQ_TIME_ACCOUNTING is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TINY_RCU=y
+# CONFIG_RCU_EXPERT is not set
+CONFIG_SRCU=y
+# CONFIG_TASKS_RCU is not set
+# CONFIG_RCU_STALL_COMMON is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_RCU_EXPEDITE_BOOT is not set
+# CONFIG_BUILD_BIN2C is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_NMI_LOG_BUF_SHIFT=13
+CONFIG_GENERIC_SCHED_CLOCK=y
+CONFIG_CGROUPS=y
+# CONFIG_MEMCG is not set
+# CONFIG_BLK_CGROUP is not set
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUP_PIDS is not set
+CONFIG_CGROUP_FREEZER=y
+# CONFIG_CPUSETS is not set
+# CONFIG_CGROUP_DEVICE is not set
+# CONFIG_CGROUP_CPUACCT is not set
+# CONFIG_CGROUP_DEBUG is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+CONFIG_NAMESPACES=y
+CONFIG_UTS_NS=y
+CONFIG_IPC_NS=y
+# CONFIG_USER_NS is not set
+CONFIG_PID_NS=y
+CONFIG_NET_NS=y
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_RD_XZ is not set
+# CONFIG_RD_LZO is not set
+CONFIG_RD_LZ4=y
+CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_HAVE_UID16=y
+CONFIG_BPF=y
+# CONFIG_EXPERT is not set
+CONFIG_UID16=y
+CONFIG_MULTIUSER=y
+# CONFIG_SGETMASK_SYSCALL is not set
+CONFIG_SYSFS_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set
+CONFIG_KALLSYMS_BASE_RELATIVE=y
+CONFIG_PRINTK=y
+CONFIG_PRINTK_NMI=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+# CONFIG_BPF_SYSCALL is not set
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_ADVISE_SYSCALLS=y
+# CONFIG_USERFAULTFD is not set
+CONFIG_MEMBARRIER=y
+# CONFIG_EMBEDDED is not set
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLAB_FREELIST_RANDOM is not set
+# CONFIG_SYSTEM_DATA_VERIFICATION is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+# CONFIG_JUMP_LABEL is not set
+# CONFIG_UPROBES is not set
+# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_ARCH_USE_BUILTIN_BSWAP=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_NMI=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_IDLE_POLL_SETUP=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_HAVE_GCC_PLUGINS=y
+# CONFIG_GCC_PLUGINS is not set
+CONFIG_HAVE_CC_STACKPROTECTOR=y
+CONFIG_CC_STACKPROTECTOR=y
+# CONFIG_CC_STACKPROTECTOR_NONE is not set
+# CONFIG_CC_STACKPROTECTOR_REGULAR is not set
+CONFIG_CC_STACKPROTECTOR_STRONG=y
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_MODULES_USE_ELF_REL=y
+CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_HAVE_ARCH_MMAP_RND_BITS=y
+CONFIG_HAVE_EXIT_THREAD=y
+CONFIG_ARCH_MMAP_RND_BITS_MIN=8
+CONFIG_ARCH_MMAP_RND_BITS_MAX=16
+CONFIG_ARCH_MMAP_RND_BITS=8
+# CONFIG_HAVE_ARCH_HASH is not set
+# CONFIG_ISA_BUS_API is not set
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_OLD_SIGACTION=y
+# CONFIG_CPU_NO_EFFICIENT_FFS is not set
+# CONFIG_HAVE_ARCH_VMAP_STACK is not set
+
+#
+# GCOV-based kernel profiling
+#
+CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_MODULE_SIG is not set
+# CONFIG_MODULE_COMPRESS is not set
+# CONFIG_TRIM_UNUSED_KSYMS is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+CONFIG_BLK_DEV_BSG=y
+# CONFIG_BLK_DEV_BSGLIB is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+CONFIG_BLK_CMDLINE_PARSER=y
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_AIX_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_CMDLINE_PARTITION=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+CONFIG_INLINE_READ_UNLOCK=y
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+CONFIG_INLINE_WRITE_UNLOCK=y
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+CONFIG_MMU=y
+CONFIG_ARCH_MULTIPLATFORM=y
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_LPC32XX is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C24XX is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP1 is not set
+
+#
+# Multiple platform selection
+#
+
+#
+# CPU Core family selection
+#
+# CONFIG_ARCH_MULTI_V6 is not set
+CONFIG_ARCH_MULTI_V7=y
+CONFIG_ARCH_MULTI_V6_V7=y
+# CONFIG_ARCH_MULTI_CPU_AUTO is not set
+# CONFIG_ARCH_VIRT is not set
+# CONFIG_ARCH_MVEBU is not set
+# CONFIG_ARCH_ALPINE is not set
+# CONFIG_ARCH_ARTPEC is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_BCM is not set
+# CONFIG_ARCH_BERLIN is not set
+# CONFIG_ARCH_DIGICOLOR is not set
+# CONFIG_ARCH_HIGHBANK is not set
+# CONFIG_ARCH_HISI is not set
+CONFIG_ARCH_GOKE=y
+
+#
+# Goke platform type
+#
+# CONFIG_ARCH_GK7205V200 is not set
+# CONFIG_ARCH_GK7205V300 is not set
+# CONFIG_ARCH_GK7202V300 is not set
+CONFIG_ARCH_GK7605V100=y
+# CONFIG_GOKE_MC is not set
+CONFIG_BSP_ZRELADDR=0x40008000
+CONFIG_BSP_PARAMS_PHYS=0x00000100
+CONFIG_BSP_INITRD_PHYS=0x00800000
+# CONFIG_ARCH_KEYSTONE is not set
+# CONFIG_ARCH_MESON is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_MEDIATEK is not set
+
+#
+# TI OMAP/AM/DM/DRA Family
+#
+# CONFIG_ARCH_OMAP3 is not set
+# CONFIG_ARCH_OMAP4 is not set
+# CONFIG_SOC_OMAP5 is not set
+# CONFIG_SOC_AM33XX is not set
+# CONFIG_SOC_AM43XX is not set
+# CONFIG_SOC_DRA7XX is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_QCOM is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_ROCKCHIP is not set
+# CONFIG_ARCH_SOCFPGA is not set
+# CONFIG_PLAT_SPEAR is not set
+# CONFIG_ARCH_STI is not set
+# CONFIG_ARCH_S5PV210 is not set
+# CONFIG_ARCH_EXYNOS is not set
+# CONFIG_ARCH_RENESAS is not set
+# CONFIG_ARCH_SUNXI is not set
+# CONFIG_ARCH_SIRF is not set
+# CONFIG_ARCH_TANGO is not set
+# CONFIG_ARCH_TEGRA is not set
+# CONFIG_ARCH_UNIPHIER is not set
+# CONFIG_ARCH_U8500 is not set
+# CONFIG_ARCH_VEXPRESS is not set
+# CONFIG_ARCH_WM8850 is not set
+# CONFIG_ARCH_ZX is not set
+# CONFIG_ARCH_ZYNQ is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_V7=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_LPAE is not set
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+CONFIG_ARM_THUMB=y
+# CONFIG_ARM_THUMBEE is not set
+CONFIG_ARM_VIRT_EXT=y
+# CONFIG_SWP_EMULATE is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_KUSER_HELPERS=y
+CONFIG_VDSO=y
+CONFIG_MIGHT_HAVE_CACHE_L2X0=y
+# CONFIG_CACHE_L2X0 is not set
+CONFIG_ARM_L1_CACHE_SHIFT_6=y
+CONFIG_ARM_L1_CACHE_SHIFT=6
+CONFIG_ARM_DMA_MEM_BUFFERABLE=y
+# CONFIG_DEBUG_RODATA is not set
+CONFIG_MULTI_IRQ_HANDLER=y
+# CONFIG_ARM_ERRATA_430973 is not set
+# CONFIG_ARM_ERRATA_720789 is not set
+# CONFIG_ARM_ERRATA_754322 is not set
+# CONFIG_ARM_ERRATA_775420 is not set
+# CONFIG_ARM_ERRATA_773022 is not set
+# CONFIG_ARM_ERRATA_818325_852422 is not set
+# CONFIG_ARM_ERRATA_821420 is not set
+# CONFIG_ARM_ERRATA_825619 is not set
+# CONFIG_ARM_ERRATA_852421 is not set
+# CONFIG_ARM_ERRATA_852423 is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS_GENERIC is not set
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_HAVE_SMP=y
+# CONFIG_SMP is not set
+CONFIG_HAVE_ARM_ARCH_TIMER=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_3G_OPT is not set
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_ARM_PSCI is not set
+CONFIG_ARCH_NR_GPIO=0
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ_FIXED=0
+CONFIG_HZ_100=y
+# CONFIG_HZ_200 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_500 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
+# CONFIG_SCHED_HRTICK is not set
+# CONFIG_THUMB2_KERNEL is not set
+CONFIG_ARM_PATCH_IDIV=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_HAVE_ARCH_PFN_VALID=y
+# CONFIG_HIGHMEM is not set
+# CONFIG_CPU_SW_DOMAIN_PAN is not set
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+# CONFIG_ARM_MODULE_PLTS is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_NO_BOOTMEM=y
+# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_COMPACTION=y
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NEED_PER_CPU_KM=y
+# CONFIG_CLEANCACHE is not set
+# CONFIG_CMA is not set
+# CONFIG_ZPOOL is not set
+# CONFIG_ZBUD is not set
+# CONFIG_ZSMALLOC is not set
+CONFIG_GENERIC_EARLY_IOREMAP=y
+# CONFIG_IDLE_PAGE_TRACKING is not set
+CONFIG_FRAME_VECTOR=y
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+# CONFIG_SECCOMP is not set
+CONFIG_SWIOTLB=y
+CONFIG_IOMMU_HELPER=y
+# CONFIG_PARAVIRT is not set
+# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set
+# CONFIG_XEN is not set
+
+#
+# Boot options
+#
+CONFIG_USE_OF=y
+CONFIG_ATAGS=y
+# CONFIG_DEPRECATED_PARAM_STRUCT is not set
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER=y
+# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set
+CONFIG_CMDLINE=""
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_AUTO_ZRELADDR=y
+# CONFIG_EFI is not set
+
+#
+# CPU Power Management
+#
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# CPU Idle
+#
+# CONFIG_CPU_IDLE is not set
+# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+# CONFIG_KERNEL_MODE_NEON is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_ELFCORE=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
+CONFIG_BINFMT_SCRIPT=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_COREDUMP=y
+
+#
+# Power management options
+#
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_PM_SLEEP=y
+# CONFIG_PM_AUTOSLEEP is not set
+# CONFIG_PM_WAKELOCKS is not set
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_APM_EMULATION is not set
+CONFIG_PM_CLK=y
+# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_CPU_PM=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARM_CPU_SUSPEND=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_DIAG is not set
+CONFIG_UNIX=y
+# CONFIG_UNIX_DIAG is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_ALGO=y
+CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+# CONFIG_IP_FIB_TRIE_STATS is not set
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
+# CONFIG_NET_IP_TUNNEL is not set
+CONFIG_IP_MROUTE=y
+# CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_NET_UDP_TUNNEL is not set
+# CONFIG_NET_FOU is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_INET_UDP_DIAG is not set
+# CONFIG_INET_DIAG_DESTROY is not set
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BIC=m
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+# CONFIG_TCP_CONG_HSTCP is not set
+# CONFIG_TCP_CONG_HYBLA is not set
+# CONFIG_TCP_CONG_VEGAS is not set
+# CONFIG_TCP_CONG_NV is not set
+# CONFIG_TCP_CONG_SCALABLE is not set
+# CONFIG_TCP_CONG_LP is not set
+# CONFIG_TCP_CONG_VENO is not set
+# CONFIG_TCP_CONG_YEAH is not set
+# CONFIG_TCP_CONG_ILLINOIS is not set
+# CONFIG_TCP_CONG_DCTCP is not set
+# CONFIG_TCP_CONG_CDG is not set
+# CONFIG_TCP_CONG_BBR is not set
+CONFIG_DEFAULT_CUBIC=y
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NET_PTP_CLASSIFY is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP is not set
+# CONFIG_BRIDGE is not set
+CONFIG_HAVE_NET_DSA=y
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+CONFIG_DNS_RESOLVER=y
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+# CONFIG_VSOCKETS is not set
+# CONFIG_NETLINK_DIAG is not set
+# CONFIG_MPLS is not set
+# CONFIG_HSR is not set
+# CONFIG_NET_SWITCHDEV is not set
+# CONFIG_NET_L3_MASTER_DEV is not set
+# CONFIG_NET_NCSI is not set
+# CONFIG_SOCK_CGROUP_DATA is not set
+# CONFIG_CGROUP_NET_PRIO is not set
+# CONFIG_CGROUP_NET_CLASSID is not set
+CONFIG_NET_RX_BUSY_POLL=y
+CONFIG_BQL=y
+# CONFIG_BPF_JIT is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_AF_KCM is not set
+# CONFIG_STREAM_PARSER is not set
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_CFG80211=m
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+CONFIG_CFG80211_DEFAULT_PS=y
+# CONFIG_CFG80211_INTERNAL_REGDB is not set
+CONFIG_CFG80211_CRDA_SUPPORT=y
+CONFIG_CFG80211_WEXT=y
+# CONFIG_LIB80211 is not set
+CONFIG_MAC80211=m
+CONFIG_MAC80211_HAS_RC=y
+CONFIG_MAC80211_RC_MINSTREL=y
+CONFIG_MAC80211_RC_MINSTREL_HT=y
+# CONFIG_MAC80211_RC_MINSTREL_VHT is not set
+CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y
+CONFIG_MAC80211_RC_DEFAULT="minstrel_ht"
+CONFIG_MAC80211_MESH=y
+# CONFIG_MAC80211_MESSAGE_TRACING is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+CONFIG_MAC80211_STA_HASH_MAX_SIZE=0
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+# CONFIG_LWTUNNEL is not set
+# CONFIG_DST_CACHE is not set
+# CONFIG_NET_DEVLINK is not set
+CONFIG_MAY_USE_DEVLINK=y
+CONFIG_HAVE_CBPF_JIT=y
+
+#
+# Device Drivers
+#
+CONFIG_ARM_AMBA=y
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set
+CONFIG_ALLOW_DEV_COREDUMP=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+CONFIG_REGMAP=y
+CONFIG_REGMAP_I2C=y
+CONFIG_REGMAP_SPI=y
+CONFIG_REGMAP_MMIO=y
+CONFIG_DMA_SHARED_BUFFER=y
+# CONFIG_FENCE_TRACE is not set
+
+#
+# Bus devices
+#
+# CONFIG_BRCMSTB_GISB_ARB is not set
+# CONFIG_VEXPRESS_CONFIG is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+CONFIG_MTD_OF_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
+# CONFIG_MTD_OOPS is not set
+# CONFIG_MTD_PARTITIONED_MASTER is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SST25L is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOCG3 is not set
+CONFIG_MTD_NAND_ECC=y
+# CONFIG_MTD_NAND_ECC_SMC is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_ECC_BCH is not set
+# CONFIG_MTD_SM_COMMON is not set
+# CONFIG_MTD_NAND_DENALI_DT is not set
+# CONFIG_MTD_NAND_GPIO is not set
+# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_DOCG4 is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_BRCMNAND is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_NAND_HISI504 is not set
+# CONFIG_MTD_NAND_MTK is not set
+CONFIG_MTD_SPI_NAND_GOKE=y
+# CONFIG_GOKE_NAND_ECC_STATUS_REPORT is not set
+# CONFIG_GOKE_NAND_FS_MAY_NO_YAFFS2 is not set
+CONFIG_MTD_SPI_NAND_FMC100=y
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR & LPDDR2 PCM memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_LPDDR2_NVM is not set
+CONFIG_MTD_SPI_NOR=y
+# CONFIG_MTD_MT81xx_NOR is not set
+# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
+# CONFIG_SPI_CADENCE_QUADSPI is not set
+CONFIG_SPI_GOKE_SFC=y
+# CONFIG_CLOSE_SPI_8PIN_4IO is not set
+CONFIG_GOKE_SPI_BLOCK_PROTECT=y
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_LIMIT=20
+# CONFIG_MTD_UBI_FASTMAP is not set
+# CONFIG_MTD_UBI_GLUEBI is not set
+# CONFIG_MTD_UBI_BLOCK is not set
+CONFIG_DTC=y
+CONFIG_OF=y
+# CONFIG_OF_UNITTEST is not set
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_NET=y
+CONFIG_OF_MDIO=y
+CONFIG_OF_RESERVED_MEM=y
+# CONFIG_OF_OVERLAY is not set
+CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_NULL_BLK is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_DRBD is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=65536
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MG_DISK is not set
+# CONFIG_BLK_DEV_RBD is not set
+# CONFIG_NVME_TARGET is not set
+
+#
+# Misc devices
+#
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_DUMMY_IRQ is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_APDS9802ALS is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_ISL29020 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_BH1770 is not set
+# CONFIG_SENSORS_APDS990X is not set
+# CONFIG_HMC6352 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_TI_DAC7512 is not set
+# CONFIG_USB_SWITCH_FSA9480 is not set
+# CONFIG_LATTICE_ECP3_CONFIG is not set
+# CONFIG_SRAM is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_EEPROM_93XX46 is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+# CONFIG_SENSORS_LIS3_SPI is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
+
+#
+# Altera FPGA firmware download module
+#
+# CONFIG_ALTERA_STAPL is not set
+
+#
+# Intel MIC Bus Driver
+#
+
+#
+# SCIF Bus Driver
+#
+
+#
+# VOP Bus Driver
+#
+
+#
+# Intel MIC Host Driver
+#
+
+#
+# Intel MIC Card Driver
+#
+
+#
+# SCIF Driver
+#
+
+#
+# Intel MIC Coprocessor State Management (COSM) Drivers
+#
+
+#
+# VOP Driver
+#
+# CONFIG_ECHO is not set
+# CONFIG_CXL_BASE is not set
+# CONFIG_CXL_AFU_DRIVER_OPS is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+CONFIG_SCSI_NETLINK=y
+# CONFIG_SCSI_MQ_DEFAULT is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+CONFIG_SCSI_FC_ATTRS=y
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_ISCSI_BOOT_SYSFS is not set
+# CONFIG_SCSI_UFSHCD is not set
+# CONFIG_LIBFC is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_TARGET_CORE is not set
+CONFIG_NETDEVICES=y
+CONFIG_NET_CORE=y
+# CONFIG_BONDING is not set
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_NET_TEAM is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_VXLAN is not set
+# CONFIG_MACSEC is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_TUN is not set
+# CONFIG_TUN_VNET_CROSS_LE is not set
+# CONFIG_VETH is not set
+# CONFIG_NLMON is not set
+
+#
+# CAIF transport drivers
+#
+
+#
+# Distributed Switch Architecture drivers
+#
+CONFIG_ETHERNET=y
+# CONFIG_ALTERA_TSE is not set
+# CONFIG_NET_VENDOR_AMAZON is not set
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_AURORA is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_DM9000 is not set
+# CONFIG_DNET is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_HISILICON is not set
+CONFIG_NET_VENDOR_GOKE=y
+CONFIG_GOKE_FEMAC=y
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+CONFIG_NET_VENDOR_MICROCHIP=y
+# CONFIG_ENC28J60 is not set
+# CONFIG_ENCX24J600 is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
+# CONFIG_ETHOC is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_PHYLIB=y
+CONFIG_SWPHY=y
+
+#
+# MDIO bus device drivers
+#
+# CONFIG_MDIO_BCM_UNIMAC is not set
+# CONFIG_MDIO_BITBANG is not set
+# CONFIG_MDIO_BUS_MUX_GPIO is not set
+# CONFIG_MDIO_BUS_MUX_MMIOREG is not set
+CONFIG_MDIO_GOKE_FEMAC=y
+# CONFIG_MDIO_HISI_FEMAC is not set
+
+#
+# MII PHY device drivers
+#
+# CONFIG_AMD_PHY is not set
+# CONFIG_AQUANTIA_PHY is not set
+# CONFIG_AT803X_PHY is not set
+# CONFIG_BCM7XXX_PHY is not set
+# CONFIG_BCM87XX_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_DP83848_PHY is not set
+# CONFIG_DP83867_PHY is not set
+CONFIG_FIXED_PHY=y
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_INTEL_XWAY_PHY is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_MICREL_PHY is not set
+# CONFIG_MICROCHIP_PHY is not set
+# CONFIG_MICROSEMI_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_TERANETICS_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_XILINX_GMII2RGMII is not set
+# CONFIG_MICREL_KS8995MA is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_USB_NET_DRIVERS is not set
+# CONFIG_WLAN is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_ISDN is not set
+# CONFIG_NVM is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+# CONFIG_INPUT_MATRIXKMAP is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ADP5588 is not set
+# CONFIG_KEYBOARD_ADP5589 is not set
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_QT1070 is not set
+# CONFIG_KEYBOARD_QT2160 is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_KEYBOARD_GPIO_POLLED is not set
+# CONFIG_KEYBOARD_TCA6416 is not set
+# CONFIG_KEYBOARD_TCA8418 is not set
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_LM8333 is not set
+# CONFIG_KEYBOARD_MAX7359 is not set
+# CONFIG_KEYBOARD_MCS is not set
+# CONFIG_KEYBOARD_MPR121 is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_SAMSUNG is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_OMAP4 is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_CAP11XX is not set
+# CONFIG_KEYBOARD_BCM is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_BYD=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_CYPRESS=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_SENTELIC is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+CONFIG_MOUSE_PS2_FOCALTECH=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_CYAPA is not set
+# CONFIG_MOUSE_ELAN_I2C is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+# CONFIG_MOUSE_SYNAPTICS_I2C is not set
+# CONFIG_MOUSE_SYNAPTICS_USB is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_AD714X is not set
+# CONFIG_INPUT_ATMEL_CAPTOUCH is not set
+# CONFIG_INPUT_BMA150 is not set
+# CONFIG_INPUT_E3X0_BUTTON is not set
+# CONFIG_INPUT_MMA8450 is not set
+# CONFIG_INPUT_MPU3050 is not set
+# CONFIG_INPUT_GP2A is not set
+# CONFIG_INPUT_GPIO_BEEPER is not set
+# CONFIG_INPUT_GPIO_TILT_POLLED is not set
+# CONFIG_INPUT_GPIO_DECODER is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_KXTJ9 is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
+CONFIG_INPUT_UINPUT=y
+# CONFIG_INPUT_PCF8574 is not set
+# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
+# CONFIG_INPUT_ADXL34X is not set
+# CONFIG_INPUT_CMA3000 is not set
+# CONFIG_INPUT_DRV260X_HAPTICS is not set
+# CONFIG_INPUT_DRV2665_HAPTICS is not set
+# CONFIG_INPUT_DRV2667_HAPTICS is not set
+# CONFIG_RMI4_CORE is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_AMBAKMI is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_ALTERA_PS2 is not set
+# CONFIG_SERIO_PS2MULT is not set
+# CONFIG_SERIO_ARC_PS2 is not set
+# CONFIG_SERIO_APBPS2 is not set
+# CONFIG_USERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_TTY=y
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_VT_CONSOLE_SLEEP=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVMEM=y
+# CONFIG_DEVKMEM is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_EARLYCON=y
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_AMBA_PL010 is not set
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set
+# CONFIG_SERIAL_MAX3100 is not set
+# CONFIG_SERIAL_MAX310X is not set
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_SCCNXP is not set
+# CONFIG_SERIAL_SC16IS7XX is not set
+# CONFIG_SERIAL_BCM63XX is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_IFX6X60 is not set
+# CONFIG_SERIAL_XILINX_PS_UART is not set
+# CONFIG_SERIAL_ARC is not set
+# CONFIG_SERIAL_FSL_LPUART is not set
+# CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set
+# CONFIG_SERIAL_ST_ASC is not set
+# CONFIG_SERIAL_STM32 is not set
+# CONFIG_HVC_DCC is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_XILLYBUS is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MUX=y
+
+#
+# Multiplexer I2C Chip support
+#
+# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set
+# CONFIG_I2C_MUX_GPIO is not set
+# CONFIG_I2C_MUX_PCA9541 is not set
+# CONFIG_I2C_MUX_PCA954x is not set
+# CONFIG_I2C_MUX_PINCTRL is not set
+# CONFIG_I2C_MUX_REG is not set
+# CONFIG_I2C_DEMUX_PINCTRL is not set
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_CBUS_GPIO is not set
+# CONFIG_I2C_DESIGNWARE_PLATFORM is not set
+# CONFIG_I2C_EMEV2 is not set
+# CONFIG_I2C_GPIO is not set
+CONFIG_I2C_GOKE=y
+# CONFIG_I2C_NOMADIK is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_PXA_PCI is not set
+# CONFIG_I2C_RK3X is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_DIOLAN_U2C is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_ROBOTFUZZ_OSIF is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+CONFIG_DMA_MSG_MIN_LEN=5
+CONFIG_DMA_MSG_MAX_LEN=4090
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_SLAVE is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_ALTERA is not set
+# CONFIG_SPI_AXI_SPI_ENGINE is not set
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_CADENCE is not set
+# CONFIG_SPI_DESIGNWARE is not set
+# CONFIG_SPI_GPIO is not set
+# CONFIG_SPI_FSL_SPI is not set
+# CONFIG_SPI_OC_TINY is not set
+CONFIG_SPI_PL022=y
+# CONFIG_SPI_PXA2XX_PCI is not set
+# CONFIG_SPI_ROCKCHIP is not set
+# CONFIG_SPI_SC18IS602 is not set
+# CONFIG_SPI_XCOMM is not set
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_ZYNQMP_GQSPI is not set
+
+#
+# SPI Protocol Masters
+#
+CONFIG_SPI_SPIDEV=y
+# CONFIG_SPI_LOOPBACK_TEST is not set
+# CONFIG_SPI_TLE62X0 is not set
+# CONFIG_SPMI is not set
+# CONFIG_HSI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+# CONFIG_PTP_1588_CLOCK is not set
+
+#
+# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
+#
+CONFIG_PINCTRL=y
+
+#
+# Pin controllers
+#
+CONFIG_PINMUX=y
+CONFIG_PINCONF=y
+CONFIG_GENERIC_PINCONF=y
+# CONFIG_DEBUG_PINCTRL is not set
+# CONFIG_PINCTRL_AMD is not set
+CONFIG_PINCTRL_SINGLE=y
+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
+CONFIG_GPIOLIB=y
+CONFIG_OF_GPIO=y
+CONFIG_GPIOLIB_IRQCHIP=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO drivers
+#
+# CONFIG_GPIO_74XX_MMIO is not set
+# CONFIG_GPIO_ALTERA is not set
+# CONFIG_GPIO_DWAPB is not set
+# CONFIG_GPIO_EM is not set
+# CONFIG_GPIO_GENERIC_PLATFORM is not set
+# CONFIG_GPIO_GRGPIO is not set
+# CONFIG_GPIO_MOCKUP is not set
+# CONFIG_GPIO_MPC8XXX is not set
+CONFIG_GPIO_PL061=y
+# CONFIG_GPIO_SYSCON is not set
+# CONFIG_GPIO_XILINX is not set
+# CONFIG_GPIO_ZEVIO is not set
+# CONFIG_GPIO_ZX is not set
+
+#
+# I2C GPIO expanders
+#
+# CONFIG_GPIO_ADP5588 is not set
+# CONFIG_GPIO_ADNP is not set
+# CONFIG_GPIO_MAX7300 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_SX150X is not set
+# CONFIG_GPIO_TPIC2810 is not set
+# CONFIG_GPIO_TS4900 is not set
+
+#
+# MFD GPIO expanders
+#
+# CONFIG_HTC_EGPIO is not set
+
+#
+# SPI GPIO expanders
+#
+# CONFIG_GPIO_74X164 is not set
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MC33880 is not set
+# CONFIG_GPIO_PISOSR is not set
+
+#
+# SPI or I2C GPIO expanders
+#
+# CONFIG_GPIO_MCP23S08 is not set
+
+#
+# USB GPIO expanders
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_AVS is not set
+CONFIG_POWER_RESET=y
+# CONFIG_POWER_RESET_BRCMKONA is not set
+# CONFIG_POWER_RESET_BRCMSTB is not set
+CONFIG_POWER_RESET_GOKE=y
+# CONFIG_POWER_RESET_GPIO is not set
+# CONFIG_POWER_RESET_GPIO_RESTART is not set
+# CONFIG_POWER_RESET_LTC2952 is not set
+# CONFIG_POWER_RESET_RESTART is not set
+# CONFIG_POWER_RESET_VERSATILE is not set
+# CONFIG_POWER_RESET_SYSCON is not set
+# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set
+# CONFIG_SYSCON_REBOOT_MODE is not set
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_TEST_POWER is not set
+# CONFIG_BATTERY_DS2780 is not set
+# CONFIG_BATTERY_DS2781 is not set
+# CONFIG_BATTERY_DS2782 is not set
+# CONFIG_BATTERY_SBS is not set
+# CONFIG_BATTERY_BQ27XXX is not set
+# CONFIG_BATTERY_MAX17040 is not set
+# CONFIG_BATTERY_MAX17042 is not set
+# CONFIG_CHARGER_MAX8903 is not set
+# CONFIG_CHARGER_LP8727 is not set
+# CONFIG_CHARGER_GPIO is not set
+# CONFIG_CHARGER_BQ2415X is not set
+# CONFIG_CHARGER_BQ24190 is not set
+# CONFIG_CHARGER_BQ24257 is not set
+# CONFIG_CHARGER_BQ24735 is not set
+# CONFIG_CHARGER_BQ25890 is not set
+# CONFIG_CHARGER_SMB347 is not set
+# CONFIG_BATTERY_GAUGE_LTC2941 is not set
+# CONFIG_CHARGER_RT9455 is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+CONFIG_MFD_CORE=y
+# CONFIG_MFD_ACT8945A is not set
+# CONFIG_MFD_AS3711 is not set
+# CONFIG_MFD_AS3722 is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_AAT2870_CORE is not set
+# CONFIG_MFD_ATMEL_FLEXCOM is not set
+# CONFIG_MFD_ATMEL_HLCDC is not set
+# CONFIG_MFD_BCM590XX is not set
+# CONFIG_MFD_AXP20X_I2C is not set
+# CONFIG_MFD_CROS_EC is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_DA9052_SPI is not set
+# CONFIG_MFD_DA9052_I2C is not set
+# CONFIG_MFD_DA9055 is not set
+# CONFIG_MFD_DA9062 is not set
+# CONFIG_MFD_DA9063 is not set
+# CONFIG_MFD_DA9150 is not set
+# CONFIG_MFD_DLN2 is not set
+# CONFIG_MFD_EXYNOS_LPASS is not set
+# CONFIG_MFD_MC13XXX_SPI is not set
+# CONFIG_MFD_MC13XXX_I2C is not set
+# CONFIG_MFD_HI6421_PMIC is not set
+CONFIG_MFD_GOKE_FMC=y
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_HTC_I2CPLD is not set
+# CONFIG_INTEL_SOC_PMIC is not set
+# CONFIG_MFD_KEMPLD is not set
+# CONFIG_MFD_88PM800 is not set
+# CONFIG_MFD_88PM805 is not set
+# CONFIG_MFD_88PM860X is not set
+# CONFIG_MFD_MAX14577 is not set
+# CONFIG_MFD_MAX77620 is not set
+# CONFIG_MFD_MAX77686 is not set
+# CONFIG_MFD_MAX77693 is not set
+# CONFIG_MFD_MAX77843 is not set
+# CONFIG_MFD_MAX8907 is not set
+# CONFIG_MFD_MAX8925 is not set
+# CONFIG_MFD_MAX8997 is not set
+# CONFIG_MFD_MAX8998 is not set
+# CONFIG_MFD_MT6397 is not set
+# CONFIG_MFD_MENF21BMC is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_MFD_VIPERBOARD is not set
+# CONFIG_MFD_RETU is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_PM8921_CORE is not set
+# CONFIG_MFD_RT5033 is not set
+# CONFIG_MFD_RTSX_USB is not set
+# CONFIG_MFD_RC5T583 is not set
+# CONFIG_MFD_RK808 is not set
+# CONFIG_MFD_RN5T618 is not set
+# CONFIG_MFD_SEC_CORE is not set
+# CONFIG_MFD_SI476X_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_SKY81452 is not set
+# CONFIG_MFD_SMSC is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_MFD_STMPE is not set
+CONFIG_MFD_SYSCON=y
+# CONFIG_MFD_TI_AM335X_TSCADC is not set
+# CONFIG_MFD_LP3943 is not set
+# CONFIG_MFD_LP8788 is not set
+# CONFIG_MFD_PALMAS is not set
+# CONFIG_TPS6105X is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TPS6507X is not set
+# CONFIG_MFD_TPS65086 is not set
+# CONFIG_MFD_TPS65090 is not set
+# CONFIG_MFD_TPS65217 is not set
+# CONFIG_MFD_TI_LP873X is not set
+# CONFIG_MFD_TPS65218 is not set
+# CONFIG_MFD_TPS6586X is not set
+# CONFIG_MFD_TPS65910 is not set
+# CONFIG_MFD_TPS65912_I2C is not set
+# CONFIG_MFD_TPS65912_SPI is not set
+# CONFIG_MFD_TPS80031 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_TWL6040_CORE is not set
+# CONFIG_MFD_WL1273_CORE is not set
+# CONFIG_MFD_LM3533 is not set
+# CONFIG_MFD_TC3589X is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_MFD_ARIZONA_I2C is not set
+# CONFIG_MFD_ARIZONA_SPI is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X_I2C is not set
+# CONFIG_MFD_WM831X_SPI is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8994 is not set
+# CONFIG_REGULATOR is not set
+CONFIG_MEDIA_SUPPORT=y
+
+#
+# Multimedia core support
+#
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set
+# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set
+# CONFIG_MEDIA_RADIO_SUPPORT is not set
+# CONFIG_MEDIA_SDR_SUPPORT is not set
+# CONFIG_MEDIA_RC_SUPPORT is not set
+# CONFIG_MEDIA_CONTROLLER is not set
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L2=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEOBUF2_CORE=y
+CONFIG_VIDEOBUF2_MEMOPS=y
+CONFIG_VIDEOBUF2_VMALLOC=y
+# CONFIG_TTPCI_EEPROM is not set
+
+#
+# Media drivers
+#
+CONFIG_MEDIA_USB_SUPPORT=y
+
+#
+# Webcam devices
+#
+CONFIG_USB_VIDEO_CLASS=y
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+CONFIG_USB_GSPCA=m
+# CONFIG_USB_M5602 is not set
+# CONFIG_USB_STV06XX is not set
+# CONFIG_USB_GL860 is not set
+# CONFIG_USB_GSPCA_BENQ is not set
+# CONFIG_USB_GSPCA_CONEX is not set
+# CONFIG_USB_GSPCA_CPIA1 is not set
+# CONFIG_USB_GSPCA_DTCS033 is not set
+# CONFIG_USB_GSPCA_ETOMS is not set
+# CONFIG_USB_GSPCA_FINEPIX is not set
+# CONFIG_USB_GSPCA_JEILINJ is not set
+# CONFIG_USB_GSPCA_JL2005BCD is not set
+# CONFIG_USB_GSPCA_KINECT is not set
+# CONFIG_USB_GSPCA_KONICA is not set
+# CONFIG_USB_GSPCA_MARS is not set
+# CONFIG_USB_GSPCA_MR97310A is not set
+# CONFIG_USB_GSPCA_NW80X is not set
+# CONFIG_USB_GSPCA_OV519 is not set
+# CONFIG_USB_GSPCA_OV534 is not set
+# CONFIG_USB_GSPCA_OV534_9 is not set
+# CONFIG_USB_GSPCA_PAC207 is not set
+# CONFIG_USB_GSPCA_PAC7302 is not set
+# CONFIG_USB_GSPCA_PAC7311 is not set
+# CONFIG_USB_GSPCA_SE401 is not set
+# CONFIG_USB_GSPCA_SN9C2028 is not set
+# CONFIG_USB_GSPCA_SN9C20X is not set
+# CONFIG_USB_GSPCA_SONIXB is not set
+# CONFIG_USB_GSPCA_SONIXJ is not set
+# CONFIG_USB_GSPCA_SPCA500 is not set
+# CONFIG_USB_GSPCA_SPCA501 is not set
+# CONFIG_USB_GSPCA_SPCA505 is not set
+# CONFIG_USB_GSPCA_SPCA506 is not set
+# CONFIG_USB_GSPCA_SPCA508 is not set
+# CONFIG_USB_GSPCA_SPCA561 is not set
+# CONFIG_USB_GSPCA_SPCA1528 is not set
+# CONFIG_USB_GSPCA_SQ905 is not set
+# CONFIG_USB_GSPCA_SQ905C is not set
+# CONFIG_USB_GSPCA_SQ930X is not set
+# CONFIG_USB_GSPCA_STK014 is not set
+# CONFIG_USB_GSPCA_STK1135 is not set
+# CONFIG_USB_GSPCA_STV0680 is not set
+# CONFIG_USB_GSPCA_SUNPLUS is not set
+# CONFIG_USB_GSPCA_T613 is not set
+# CONFIG_USB_GSPCA_TOPRO is not set
+# CONFIG_USB_GSPCA_TOUPTEK is not set
+# CONFIG_USB_GSPCA_TV8532 is not set
+# CONFIG_USB_GSPCA_VC032X is not set
+# CONFIG_USB_GSPCA_VICAM is not set
+# CONFIG_USB_GSPCA_XIRLINK_CIT is not set
+# CONFIG_USB_GSPCA_ZC3XX is not set
+# CONFIG_USB_PWC is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_USB_ZR364XX is not set
+# CONFIG_USB_STKWEBCAM is not set
+# CONFIG_USB_S2255 is not set
+
+#
+# Webcam, TV (analog/digital) USB devices
+#
+# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_V4L_PLATFORM_DRIVERS is not set
+# CONFIG_V4L_MEM2MEM_DRIVERS is not set
+# CONFIG_V4L_TEST_DRIVERS is not set
+
+#
+# Supported MMC/SDIO adapters
+#
+# CONFIG_CYPRESS_FIRMWARE is not set
+
+#
+# Media ancillary drivers (tuners, sensors, i2c, spi, frontends)
+#
+CONFIG_MEDIA_SUBDRV_AUTOSELECT=y
+
+#
+# Audio decoders, processors and mixers
+#
+
+#
+# RDS decoders
+#
+
+#
+# Video decoders
+#
+
+#
+# Video and audio decoders
+#
+
+#
+# Video encoders
+#
+
+#
+# Camera sensor devices
+#
+
+#
+# Flash devices
+#
+
+#
+# Video improvement chips
+#
+
+#
+# Audio/Video compression chips
+#
+
+#
+# Miscellaneous helper chips
+#
+
+#
+# Sensors used on soc_camera driver
+#
+
+#
+# Tools to develop new frontends
+#
+# CONFIG_DVB_DUMMY_FE is not set
+
+#
+# Graphics support
+#
+# CONFIG_IMX_IPUV3_CORE is not set
+# CONFIG_DRM is not set
+
+#
+# ACP (Audio CoProcessor) Configuration
+#
+
+#
+# Frame buffer Devices
+#
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB_CMDLINE=y
+CONFIG_FB_NOTIFY=y
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_ARMCLCD is not set
+# CONFIG_FB_OPENCORES is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_SMSCUFX is not set
+# CONFIG_FB_UDL is not set
+# CONFIG_FB_IBM_GXT4500 is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_FB_AUO_K190X is not set
+# CONFIG_FB_SIMPLE is not set
+# CONFIG_FB_SSD1307 is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+# CONFIG_LOGO is not set
+# CONFIG_SOUND is not set
+
+#
+# HID support
+#
+CONFIG_HID=y
+# CONFIG_HID_BATTERY_STRENGTH is not set
+# CONFIG_HIDRAW is not set
+# CONFIG_UHID is not set
+CONFIG_HID_GENERIC=y
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_ACRUX is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_APPLEIR is not set
+# CONFIG_HID_AUREAL is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_BETOP_FF is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_CMEDIA is not set
+# CONFIG_HID_CP2112 is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EMS_FF is not set
+# CONFIG_HID_ELECOM is not set
+# CONFIG_HID_ELO is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_GEMBIRD is not set
+# CONFIG_HID_GFRM is not set
+# CONFIG_HID_HOLTEK is not set
+# CONFIG_HID_KEYTOUCH is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_UCLOGIC is not set
+# CONFIG_HID_WALTOP is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_ICADE is not set
+# CONFIG_HID_TWINHAN is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LCPOWER is not set
+# CONFIG_HID_LENOVO is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MAGICMOUSE is not set
+CONFIG_HID_MICROSOFT=y
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_MULTITOUCH is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_ORTEK is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PENMOUNT is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_PICOLCD is not set
+# CONFIG_HID_PLANTRONICS is not set
+# CONFIG_HID_PRIMAX is not set
+# CONFIG_HID_ROCCAT is not set
+# CONFIG_HID_SAITEK is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SPEEDLINK is not set
+# CONFIG_HID_STEELSERIES is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_RMI is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TIVO is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_WACOM is not set
+# CONFIG_HID_XINMO is not set
+# CONFIG_HID_ZEROPLUS is not set
+# CONFIG_HID_ZYDACRON is not set
+# CONFIG_HID_SENSOR_HUB is not set
+# CONFIG_HID_ALPS is not set
+
+#
+# USB HID support
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# I2C HID support
+#
+# CONFIG_I2C_HID is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_COMMON=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB=y
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEFAULT_PERSIST=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_PLATFORM=y
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+# CONFIG_USB_FOTG210_HCD is not set
+# CONFIG_USB_MAX3421_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HCD_TEST_MODE is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_REALTEK is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_STORAGE_ENE_UB6250 is not set
+# CONFIG_USB_UAS is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USBIP_CORE is not set
+# CONFIG_USB_MUSB_HDRC is not set
+CONFIG_USB_DWC3=y
+# CONFIG_USB_DWC3_HOST is not set
+# CONFIG_USB_DWC3_GADGET is not set
+CONFIG_USB_DWC3_DUAL_ROLE=y
+
+#
+# Platform Glue Driver Support
+#
+CONFIG_USB_DWC3_OF_SIMPLE=y
+# CONFIG_USB_DWC2 is not set
+# CONFIG_USB_CHIPIDEA is not set
+# CONFIG_USB_ISP1760 is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_EHSET_TEST_FIXTURE is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_YUREX is not set
+# CONFIG_USB_EZUSB_FX2 is not set
+# CONFIG_USB_HSIC_USB3503 is not set
+# CONFIG_USB_HSIC_USB4604 is not set
+# CONFIG_USB_LINK_LAYER_TEST is not set
+
+#
+# USB Physical Layer drivers
+#
+# CONFIG_USB_PHY is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_USB_ISP1301 is not set
+# CONFIG_USB_ULPI is not set
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2
+
+#
+# USB Peripheral Controller
+#
+# CONFIG_USB_FUSB300 is not set
+# CONFIG_USB_FOTG210_UDC is not set
+# CONFIG_USB_GR_UDC is not set
+# CONFIG_USB_R8A66597 is not set
+# CONFIG_USB_PXA27X is not set
+# CONFIG_USB_MV_UDC is not set
+# CONFIG_USB_MV_U3D is not set
+# CONFIG_USB_M66592 is not set
+# CONFIG_USB_BDC_UDC is not set
+# CONFIG_USB_NET2272 is not set
+# CONFIG_USB_GADGET_XILINX is not set
+# CONFIG_USB_DUMMY_HCD is not set
+CONFIG_USB_LIBCOMPOSITE=m
+CONFIG_USB_F_ACM=m
+CONFIG_USB_U_SERIAL=m
+CONFIG_USB_U_ETHER=m
+CONFIG_USB_F_ECM=m
+CONFIG_USB_F_RNDIS=m
+CONFIG_USB_F_MASS_STORAGE=m
+CONFIG_USB_CONFIGFS=m
+# CONFIG_USB_CONFIGFS_SERIAL is not set
+CONFIG_USB_CONFIGFS_ACM=y
+# CONFIG_USB_CONFIGFS_OBEX is not set
+# CONFIG_USB_CONFIGFS_NCM is not set
+CONFIG_USB_CONFIGFS_ECM=y
+# CONFIG_USB_CONFIGFS_ECM_SUBSET is not set
+CONFIG_USB_CONFIGFS_RNDIS=y
+# CONFIG_USB_CONFIGFS_EEM is not set
+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
+# CONFIG_USB_CONFIGFS_F_LB_SS is not set
+# CONFIG_USB_CONFIGFS_F_FS is not set
+# CONFIG_USB_CONFIGFS_F_HID is not set
+# CONFIG_USB_CONFIGFS_F_UVC is not set
+# CONFIG_USB_CONFIGFS_F_PRINTER is not set
+# CONFIG_USB_ULPI_BUS is not set
+# CONFIG_UWB is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_PWRSEQ_EMMC=y
+CONFIG_PWRSEQ_SIMPLE=y
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_MINORS=8
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_ARMMMCI is not set
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+# CONFIG_MMC_SDHCI_OF_ARASAN is not set
+# CONFIG_MMC_SDHCI_OF_AT91 is not set
+CONFIG_MMC_SDHCI_GOKE=y
+# CONFIG_MMC_SDHCI_F_SDH30 is not set
+# CONFIG_MMC_SPI is not set
+# CONFIG_MMC_DW is not set
+# CONFIG_MMC_VUB300 is not set
+# CONFIG_MMC_USHC is not set
+# CONFIG_MMC_USDHI6ROL0 is not set
+# CONFIG_MMC_MTK is not set
+# CONFIG_MMC_CQ_HCI is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_EDAC_ATOMIC_SCRUB=y
+CONFIG_EDAC_SUPPORT=y
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+CONFIG_RTC_SYSTOHC=y
+CONFIG_RTC_SYSTOHC_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_ABB5ZES3 is not set
+# CONFIG_RTC_DRV_ABX80X is not set
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_HYM8563 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_ISL12022 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8523 is not set
+# CONFIG_RTC_DRV_PCF85063 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_BQ32K is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8010 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+# CONFIG_RTC_DRV_EM3027 is not set
+# CONFIG_RTC_DRV_RV8803 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T93 is not set
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1302 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1343 is not set
+# CONFIG_RTC_DRV_DS1347 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6916 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RX4581 is not set
+# CONFIG_RTC_DRV_RX6110 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
+# CONFIG_RTC_DRV_MCP795 is not set
+CONFIG_RTC_I2C_AND_SPI=y
+
+#
+# SPI and I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS3232 is not set
+# CONFIG_RTC_DRV_PCF2127 is not set
+# CONFIG_RTC_DRV_RV3029C2 is not set
+
+#
+# Platform RTC drivers
+#
+CONFIG_RTC_DRV_GOKE=y
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1685_FAMILY is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_DS2404 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+# CONFIG_RTC_DRV_ZYNQMP is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_PL030 is not set
+# CONFIG_RTC_DRV_PL031 is not set
+# CONFIG_RTC_DRV_SNVS is not set
+
+#
+# HID Sensor RTC drivers
+#
+# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set
+# CONFIG_DMADEVICES is not set
+
+#
+# DMABUF options
+#
+# CONFIG_SYNC_FILE is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+# CONFIG_VIRT_DRIVERS is not set
+
+#
+# Virtio drivers
+#
+# CONFIG_VIRTIO_MMIO is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_STAGING is not set
+# CONFIG_GOLDFISH is not set
+# CONFIG_CHROME_PLATFORMS is not set
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_COMMON_CLK=y
+
+#
+# Common Clock Framework
+#
+# CONFIG_COMMON_CLK_SI5351 is not set
+# CONFIG_COMMON_CLK_SI514 is not set
+# CONFIG_COMMON_CLK_SI570 is not set
+# CONFIG_COMMON_CLK_CDCE706 is not set
+# CONFIG_COMMON_CLK_CDCE925 is not set
+# CONFIG_COMMON_CLK_CS2000_CP is not set
+# CONFIG_CLK_QORIQ is not set
+# CONFIG_COMMON_CLK_NXP is not set
+# CONFIG_COMMON_CLK_PXA is not set
+# CONFIG_COMMON_CLK_PIC32 is not set
+CONFIG_COMMON_CLK_GK7605V100=y
+CONFIG_RESET_GOKE=y
+
+#
+# Hardware Spinlock drivers
+#
+
+#
+# Clock Source drivers
+#
+CONFIG_CLKSRC_OF=y
+CONFIG_CLKSRC_PROBE=y
+CONFIG_CLKSRC_MMIO=y
+CONFIG_ARM_ARCH_TIMER=y
+CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y
+# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS is not set
+CONFIG_ARM_TIMER_SP804=y
+# CONFIG_ATMEL_PIT is not set
+# CONFIG_SH_TIMER_CMT is not set
+# CONFIG_SH_TIMER_MTU2 is not set
+# CONFIG_SH_TIMER_TMU is not set
+# CONFIG_EM_TIMER_STI is not set
+# CONFIG_MAILBOX is not set
+# CONFIG_IOMMU_SUPPORT is not set
+
+#
+# Remoteproc drivers
+#
+# CONFIG_STE_MODEM_RPROC is not set
+
+#
+# Rpmsg drivers
+#
+
+#
+# SOC (System On Chip) specific Drivers
+#
+
+#
+# Broadcom SoC drivers
+#
+# CONFIG_SOC_BRCMSTB is not set
+# CONFIG_SUNXI_SRAM is not set
+# CONFIG_SOC_TI is not set
+# CONFIG_PM_DEVFREQ is not set
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
+# CONFIG_IIO is not set
+# CONFIG_PWM is not set
+CONFIG_IRQCHIP=y
+CONFIG_ARM_GIC=y
+CONFIG_ARM_GIC_MAX_NR=1
+# CONFIG_IPACK_BUS is not set
+CONFIG_RESET_CONTROLLER=y
+# CONFIG_RESET_ATH79 is not set
+# CONFIG_RESET_BERLIN is not set
+# CONFIG_RESET_LPC18XX is not set
+# CONFIG_RESET_MESON is not set
+# CONFIG_RESET_PISTACHIO is not set
+# CONFIG_RESET_SOCFPGA is not set
+# CONFIG_RESET_STM32 is not set
+# CONFIG_RESET_SUNXI is not set
+# CONFIG_TI_SYSCON_RESET is not set
+# CONFIG_RESET_ZYNQ is not set
+# CONFIG_FMC is not set
+
+#
+# PHY Subsystem
+#
+CONFIG_GENERIC_PHY=y
+# CONFIG_PHY_PXA_28NM_HSIC is not set
+# CONFIG_PHY_PXA_28NM_USB2 is not set
+# CONFIG_BCM_KONA_USB2_PHY is not set
+CONFIG_PHY_GOKE_USBP2=y
+# CONFIG_USB_MODE_OPTION is not set
+# CONFIG_POWERCAP is not set
+# CONFIG_MCB is not set
+
+#
+# Performance monitor support
+#
+# CONFIG_RAS is not set
+
+#
+# Android
+#
+# CONFIG_ANDROID is not set
+# CONFIG_NVMEM is not set
+# CONFIG_STM is not set
+# CONFIG_INTEL_TH is not set
+
+#
+# FPGA Configuration Support
+#
+# CONFIG_FPGA is not set
+
+#
+# goke driver support
+#
+
+#
+# Firmware Drivers
+#
+# CONFIG_FIRMWARE_MEMMAP is not set
+# CONFIG_FW_CFG_SYSFS is not set
+CONFIG_HAVE_ARM_SMCCC=y
+
+#
+# File systems
+#
+CONFIG_DCACHE_WORD_ACCESS=y
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_USE_FOR_EXT2=y
+# CONFIG_EXT4_FS_POSIX_ACL is not set
+# CONFIG_EXT4_FS_SECURITY is not set
+# CONFIG_EXT4_ENCRYPTION is not set
+# CONFIG_EXT4_DEBUG is not set
+CONFIG_JBD2=y
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+# CONFIG_F2FS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_EXPORTFS=y
+# CONFIG_EXPORTFS_BLOCK_OPS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_MANDATORY_FILE_LOCKING=y
+# CONFIG_FS_ENCRYPTION is not set
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_QUOTACTL is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+# CONFIG_OVERLAY_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_FAT_DEFAULT_UTF8 is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_PROC_CHILDREN is not set
+CONFIG_KERNFS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_TMPFS_XATTR=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=y
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ORANGEFS_FS is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_YAFFS_FS=y
+CONFIG_YAFFS_YAFFS1=y
+# CONFIG_YAFFS_9BYTE_TAGS is not set
+# CONFIG_YAFFS_DOES_ECC is not set
+CONFIG_YAFFS_YAFFS2=y
+CONFIG_YAFFS_AUTO_YAFFS2=y
+# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set
+# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
+# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set
+# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set
+# CONFIG_YAFFS_DISABLE_BACKGROUND is not set
+# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set
+CONFIG_YAFFS_XATTR=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+# CONFIG_JFFS2_LZMA is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_UBIFS_FS=y
+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_ATIME_SUPPORT is not set
+# CONFIG_LOGFS is not set
+CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX6FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_PSTORE is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V2=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+# CONFIG_NFS_SWAP is not set
+# CONFIG_NFS_V4_1 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFS_USE_LEGACY_DNS is not set
+CONFIG_NFS_USE_KERNEL_DNS=y
+# CONFIG_NFSD is not set
+CONFIG_GRACE_PERIOD=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_ACL_SUPPORT=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_DEBUG is not set
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=y
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+# CONFIG_NLS_MAC_ROMAN is not set
+# CONFIG_NLS_MAC_CELTIC is not set
+# CONFIG_NLS_MAC_CENTEURO is not set
+# CONFIG_NLS_MAC_CROATIAN is not set
+# CONFIG_NLS_MAC_CYRILLIC is not set
+# CONFIG_NLS_MAC_GAELIC is not set
+# CONFIG_NLS_MAC_GREEK is not set
+# CONFIG_NLS_MAC_ICELAND is not set
+# CONFIG_NLS_MAC_INUIT is not set
+# CONFIG_NLS_MAC_ROMANIAN is not set
+# CONFIG_NLS_MAC_TURKISH is not set
+CONFIG_NLS_UTF8=y
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+
+#
+# printk and dmesg options
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
+# CONFIG_BOOT_PRINTK_DELAY is not set
+
+#
+# Compile-time checks and compiler options
+#
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_READABLE_ASM is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_PAGE_OWNER is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_SECTION_MISMATCH_WARN_ONLY=y
+CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_DEBUG_KERNEL=y
+
+#
+# Memory Debugging
+#
+# CONFIG_PAGE_EXTENSION is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_PAGE_POISONING is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_SHIRQ is not set
+
+#
+# Debug Lockups and Hangs
+#
+# CONFIG_LOCKUP_DETECTOR is not set
+# CONFIG_DETECT_HUNG_TASK is not set
+# CONFIG_WQ_WATCHDOG is not set
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+CONFIG_PANIC_TIMEOUT=0
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHED_INFO is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_SCHED_STACK_END_CHECK is not set
+# CONFIG_DEBUG_TIMEKEEPING is not set
+# CONFIG_TIMER_STATS is not set
+
+#
+# Lock Debugging (spinlocks, mutexes, etc...)
+#
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_ATOMIC_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_LOCK_TORTURE_TEST is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_PI_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+
+#
+# RCU Debugging
+#
+# CONFIG_PROVE_RCU is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_TORTURE_TEST is not set
+# CONFIG_RCU_PERF_TEST is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_TRACE is not set
+# CONFIG_RCU_EQS_DEBUG is not set
+# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_NOTIFIER_ERROR_INJECTION is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+
+#
+# Runtime Testing
+#
+# CONFIG_TEST_LIST_SORT is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_RBTREE_TEST is not set
+# CONFIG_INTERVAL_TREE_TEST is not set
+# CONFIG_PERCPU_TEST is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_TEST_HEXDUMP is not set
+# CONFIG_TEST_STRING_HELPERS is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_TEST_PRINTF is not set
+# CONFIG_TEST_BITMAP is not set
+# CONFIG_TEST_UUID is not set
+# CONFIG_TEST_RHASHTABLE is not set
+# CONFIG_TEST_HASH is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_TEST_LKM is not set
+# CONFIG_TEST_USER_COPY is not set
+# CONFIG_TEST_BPF is not set
+# CONFIG_TEST_FIRMWARE is not set
+# CONFIG_TEST_UDELAY is not set
+# CONFIG_MEMTEST is not set
+# CONFIG_TEST_STATIC_KEYS is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set
+# CONFIG_UBSAN is not set
+CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
+CONFIG_STRICT_DEVMEM=y
+# CONFIG_IO_STRICT_DEVMEM is not set
+# CONFIG_ARM_PTDUMP is not set
+# CONFIG_ARM_UNWIND is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_LL is not set
+CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
+# CONFIG_DEBUG_UART_8250 is not set
+CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
+# CONFIG_PID_IN_CONTEXTIDR is not set
+# CONFIG_DEBUG_SET_MODULE_RONX is not set
+# CONFIG_CORESIGHT is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_PERSISTENT_KEYRINGS is not set
+# CONFIG_ENCRYPTED_KEYS is not set
+# CONFIG_KEY_DH_OPERATIONS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y
+CONFIG_HAVE_ARCH_HARDENED_USERCOPY=y
+# CONFIG_HARDENED_USERCOPY is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_RNG_DEFAULT=m
+CONFIG_CRYPTO_AKCIPHER2=y
+CONFIG_CRYPTO_KPP2=y
+# CONFIG_CRYPTO_RSA is not set
+# CONFIG_CRYPTO_DH is not set
+# CONFIG_CRYPTO_ECDH is not set
+CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_USER is not set
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_NULL2=y
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_MCRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+# CONFIG_CRYPTO_CHACHA20POLY1305 is not set
+CONFIG_CRYPTO_SEQIV=m
+CONFIG_CRYPTO_ECHAINIV=m
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+CONFIG_CRYPTO_CTR=m
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+# CONFIG_CRYPTO_KEYWRAP is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_CMAC is not set
+CONFIG_CRYPTO_HMAC=m
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_CRC32 is not set
+CONFIG_CRYPTO_CRCT10DIF=y
+CONFIG_CRYPTO_GHASH=m
+# CONFIG_CRYPTO_POLY1305 is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=y
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_SHA3 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_CHACHA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_LZO=y
+# CONFIG_CRYPTO_842 is not set
+# CONFIG_CRYPTO_LZ4 is not set
+# CONFIG_CRYPTO_LZ4HC is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_DRBG_MENU=m
+CONFIG_CRYPTO_DRBG_HMAC=y
+# CONFIG_CRYPTO_DRBG_HASH is not set
+# CONFIG_CRYPTO_DRBG_CTR is not set
+CONFIG_CRYPTO_DRBG=m
+CONFIG_CRYPTO_JITTERENTROPY=m
+# CONFIG_CRYPTO_USER_API_HASH is not set
+# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
+# CONFIG_CRYPTO_USER_API_RNG is not set
+# CONFIG_CRYPTO_USER_API_AEAD is not set
+# CONFIG_CRYPTO_HW is not set
+# CONFIG_ASYMMETRIC_KEY_TYPE is not set
+
+#
+# Certificates for signature checking
+#
+# CONFIG_ARM_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_HAVE_ARCH_BITREVERSE=y
+CONFIG_RATIONAL=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_NET_UTILS=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IO=y
+CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=y
+# CONFIG_CRC8 is not set
+# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set
+# CONFIG_RANDOM32_SELFTEST is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_LZ4_DECOMPRESS=y
+CONFIG_XZ_DEC=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_BCJ=y
+# CONFIG_XZ_DEC_TEST is not set
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_LZ4=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_ASSOCIATIVE_ARRAY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_HAS_DMA=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
+# CONFIG_IRQ_POLL is not set
+CONFIG_LIBFDT=y
+CONFIG_OID_REGISTRY=y
+# CONFIG_SG_SPLIT is not set
+CONFIG_SG_POOL=y
+CONFIG_ARCH_HAS_SG_CHAIN=y
+CONFIG_SBITMAP=y
+# CONFIG_VIRTUALIZATION is not set
diff -urN linux-4.9.37/arch/arm/configs/gk7605v100_full_defconfig linux-4.9.y/arch/arm/configs/gk7605v100_full_defconfig
--- linux-4.9.37/arch/arm/configs/gk7605v100_full_defconfig 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/arch/arm/configs/gk7605v100_full_defconfig 2021-06-07 13:01:32.000000000 +0300
@@ -0,0 +1,2975 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/arm 4.9.37 Kernel Configuration
+#
+CONFIG_ARM=y
+CONFIG_ARM_HAS_SG_CHAIN=y
+CONFIG_MIGHT_HAVE_PCI=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_ARM_PATCH_PHYS_VIRT=y
+CONFIG_GENERIC_BUG=y
+CONFIG_PGTABLE_LEVELS=2
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_IRQ_WORK=y
+CONFIG_BUILDTIME_EXTABLE_SORT=y
+
+#
+# General setup
+#
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+# CONFIG_COMPILE_TEST is not set
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_HAVE_KERNEL_LZ4=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_XZ is not set
+# CONFIG_KERNEL_LZO is not set
+# CONFIG_KERNEL_LZ4 is not set
+CONFIG_DEFAULT_HOSTNAME="(none)"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_CROSS_MEMORY_ATTACH=y
+CONFIG_FHANDLE=y
+CONFIG_USELIB=y
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_ARCH_AUDITSYSCALL=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_IRQ_DOMAIN_HIERARCHY=y
+CONFIG_HANDLE_DOMAIN_IRQ=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_ARCH_CLOCKSOURCE_DATA=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+
+#
+# Timers subsystem
+#
+CONFIG_HZ_PERIODIC=y
+# CONFIG_NO_HZ_IDLE is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set
+# CONFIG_IRQ_TIME_ACCOUNTING is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TINY_RCU=y
+# CONFIG_RCU_EXPERT is not set
+CONFIG_SRCU=y
+# CONFIG_TASKS_RCU is not set
+# CONFIG_RCU_STALL_COMMON is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_RCU_EXPEDITE_BOOT is not set
+# CONFIG_BUILD_BIN2C is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_NMI_LOG_BUF_SHIFT=13
+CONFIG_GENERIC_SCHED_CLOCK=y
+CONFIG_CGROUPS=y
+# CONFIG_MEMCG is not set
+# CONFIG_BLK_CGROUP is not set
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUP_PIDS is not set
+CONFIG_CGROUP_FREEZER=y
+# CONFIG_CPUSETS is not set
+# CONFIG_CGROUP_DEVICE is not set
+# CONFIG_CGROUP_CPUACCT is not set
+# CONFIG_CGROUP_DEBUG is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+CONFIG_NAMESPACES=y
+CONFIG_UTS_NS=y
+CONFIG_IPC_NS=y
+# CONFIG_USER_NS is not set
+CONFIG_PID_NS=y
+CONFIG_NET_NS=y
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_RD_XZ is not set
+# CONFIG_RD_LZO is not set
+CONFIG_RD_LZ4=y
+CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_HAVE_UID16=y
+CONFIG_BPF=y
+# CONFIG_EXPERT is not set
+CONFIG_UID16=y
+CONFIG_MULTIUSER=y
+# CONFIG_SGETMASK_SYSCALL is not set
+CONFIG_SYSFS_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set
+CONFIG_KALLSYMS_BASE_RELATIVE=y
+CONFIG_PRINTK=y
+CONFIG_PRINTK_NMI=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+# CONFIG_BPF_SYSCALL is not set
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_ADVISE_SYSCALLS=y
+# CONFIG_USERFAULTFD is not set
+CONFIG_MEMBARRIER=y
+# CONFIG_EMBEDDED is not set
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLAB_FREELIST_RANDOM is not set
+# CONFIG_SYSTEM_DATA_VERIFICATION is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+# CONFIG_JUMP_LABEL is not set
+# CONFIG_UPROBES is not set
+# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_ARCH_USE_BUILTIN_BSWAP=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_NMI=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_IDLE_POLL_SETUP=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_HAVE_GCC_PLUGINS=y
+# CONFIG_GCC_PLUGINS is not set
+CONFIG_HAVE_CC_STACKPROTECTOR=y
+CONFIG_CC_STACKPROTECTOR=y
+# CONFIG_CC_STACKPROTECTOR_NONE is not set
+# CONFIG_CC_STACKPROTECTOR_REGULAR is not set
+CONFIG_CC_STACKPROTECTOR_STRONG=y
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_MODULES_USE_ELF_REL=y
+CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_HAVE_ARCH_MMAP_RND_BITS=y
+CONFIG_HAVE_EXIT_THREAD=y
+CONFIG_ARCH_MMAP_RND_BITS_MIN=8
+CONFIG_ARCH_MMAP_RND_BITS_MAX=16
+CONFIG_ARCH_MMAP_RND_BITS=8
+# CONFIG_HAVE_ARCH_HASH is not set
+# CONFIG_ISA_BUS_API is not set
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_OLD_SIGSUSPEND3=y
+CONFIG_OLD_SIGACTION=y
+# CONFIG_CPU_NO_EFFICIENT_FFS is not set
+# CONFIG_HAVE_ARCH_VMAP_STACK is not set
+
+#
+# GCOV-based kernel profiling
+#
+CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_MODULE_SIG is not set
+# CONFIG_MODULE_COMPRESS is not set
+# CONFIG_TRIM_UNUSED_KSYMS is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+CONFIG_BLK_DEV_BSG=y
+# CONFIG_BLK_DEV_BSGLIB is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+CONFIG_BLK_CMDLINE_PARSER=y
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_AIX_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_CMDLINE_PARTITION=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+CONFIG_INLINE_READ_UNLOCK=y
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+CONFIG_INLINE_WRITE_UNLOCK=y
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+CONFIG_MMU=y
+CONFIG_ARCH_MULTIPLATFORM=y
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_LPC32XX is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C24XX is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP1 is not set
+
+#
+# Multiple platform selection
+#
+
+#
+# CPU Core family selection
+#
+# CONFIG_ARCH_MULTI_V6 is not set
+CONFIG_ARCH_MULTI_V7=y
+CONFIG_ARCH_MULTI_V6_V7=y
+# CONFIG_ARCH_MULTI_CPU_AUTO is not set
+# CONFIG_ARCH_VIRT is not set
+# CONFIG_ARCH_MVEBU is not set
+# CONFIG_ARCH_ALPINE is not set
+# CONFIG_ARCH_ARTPEC is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_BCM is not set
+# CONFIG_ARCH_BERLIN is not set
+# CONFIG_ARCH_DIGICOLOR is not set
+# CONFIG_ARCH_HIGHBANK is not set
+# CONFIG_ARCH_HISI is not set
+CONFIG_ARCH_GOKE=y
+
+#
+# Goke platform type
+#
+# CONFIG_ARCH_GK7205V200 is not set
+# CONFIG_ARCH_GK7205V300 is not set
+# CONFIG_ARCH_GK7202V300 is not set
+CONFIG_ARCH_GK7605V100=y
+# CONFIG_GOKE_MC is not set
+CONFIG_BSP_ZRELADDR=0x40008000
+CONFIG_BSP_PARAMS_PHYS=0x00000100
+CONFIG_BSP_INITRD_PHYS=0x00800000
+# CONFIG_ARCH_KEYSTONE is not set
+# CONFIG_ARCH_MESON is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_MEDIATEK is not set
+
+#
+# TI OMAP/AM/DM/DRA Family
+#
+# CONFIG_ARCH_OMAP3 is not set
+# CONFIG_ARCH_OMAP4 is not set
+# CONFIG_SOC_OMAP5 is not set
+# CONFIG_SOC_AM33XX is not set
+# CONFIG_SOC_AM43XX is not set
+# CONFIG_SOC_DRA7XX is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_QCOM is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_ROCKCHIP is not set
+# CONFIG_ARCH_SOCFPGA is not set
+# CONFIG_PLAT_SPEAR is not set
+# CONFIG_ARCH_STI is not set
+# CONFIG_ARCH_S5PV210 is not set
+# CONFIG_ARCH_EXYNOS is not set
+# CONFIG_ARCH_RENESAS is not set
+# CONFIG_ARCH_SUNXI is not set
+# CONFIG_ARCH_SIRF is not set
+# CONFIG_ARCH_TANGO is not set
+# CONFIG_ARCH_TEGRA is not set
+# CONFIG_ARCH_UNIPHIER is not set
+# CONFIG_ARCH_U8500 is not set
+# CONFIG_ARCH_VEXPRESS is not set
+# CONFIG_ARCH_WM8850 is not set
+# CONFIG_ARCH_ZX is not set
+# CONFIG_ARCH_ZYNQ is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_V7=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_LPAE is not set
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+CONFIG_ARM_THUMB=y
+# CONFIG_ARM_THUMBEE is not set
+CONFIG_ARM_VIRT_EXT=y
+# CONFIG_SWP_EMULATE is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_KUSER_HELPERS=y
+CONFIG_VDSO=y
+CONFIG_MIGHT_HAVE_CACHE_L2X0=y
+# CONFIG_CACHE_L2X0 is not set
+CONFIG_ARM_L1_CACHE_SHIFT_6=y
+CONFIG_ARM_L1_CACHE_SHIFT=6
+CONFIG_ARM_DMA_MEM_BUFFERABLE=y
+# CONFIG_DEBUG_RODATA is not set
+CONFIG_MULTI_IRQ_HANDLER=y
+# CONFIG_ARM_ERRATA_430973 is not set
+# CONFIG_ARM_ERRATA_720789 is not set
+# CONFIG_ARM_ERRATA_754322 is not set
+# CONFIG_ARM_ERRATA_775420 is not set
+# CONFIG_ARM_ERRATA_773022 is not set
+# CONFIG_ARM_ERRATA_818325_852422 is not set
+# CONFIG_ARM_ERRATA_821420 is not set
+# CONFIG_ARM_ERRATA_825619 is not set
+# CONFIG_ARM_ERRATA_852421 is not set
+# CONFIG_ARM_ERRATA_852423 is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS_GENERIC is not set
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_HAVE_SMP=y
+# CONFIG_SMP is not set
+CONFIG_HAVE_ARM_ARCH_TIMER=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_3G_OPT is not set
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_ARM_PSCI is not set
+CONFIG_ARCH_NR_GPIO=0
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ_FIXED=0
+CONFIG_HZ_100=y
+# CONFIG_HZ_200 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_500 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
+# CONFIG_SCHED_HRTICK is not set
+# CONFIG_THUMB2_KERNEL is not set
+CONFIG_ARM_PATCH_IDIV=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_HAVE_ARCH_PFN_VALID=y
+# CONFIG_HIGHMEM is not set
+# CONFIG_CPU_SW_DOMAIN_PAN is not set
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+# CONFIG_ARM_MODULE_PLTS is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_NO_BOOTMEM=y
+# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_COMPACTION=y
+CONFIG_MIGRATION=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NEED_PER_CPU_KM=y
+# CONFIG_CLEANCACHE is not set
+# CONFIG_CMA is not set
+# CONFIG_ZPOOL is not set
+# CONFIG_ZBUD is not set
+# CONFIG_ZSMALLOC is not set
+CONFIG_GENERIC_EARLY_IOREMAP=y
+# CONFIG_IDLE_PAGE_TRACKING is not set
+CONFIG_FRAME_VECTOR=y
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+# CONFIG_SECCOMP is not set
+CONFIG_SWIOTLB=y
+CONFIG_IOMMU_HELPER=y
+# CONFIG_PARAVIRT is not set
+# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set
+# CONFIG_XEN is not set
+
+#
+# Boot options
+#
+CONFIG_USE_OF=y
+CONFIG_ATAGS=y
+# CONFIG_DEPRECATED_PARAM_STRUCT is not set
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER=y
+# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND is not set
+CONFIG_CMDLINE=""
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_AUTO_ZRELADDR=y
+# CONFIG_EFI is not set
+
+#
+# CPU Power Management
+#
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# CPU Idle
+#
+# CONFIG_CPU_IDLE is not set
+# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+# CONFIG_KERNEL_MODE_NEON is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_ELFCORE=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
+CONFIG_BINFMT_SCRIPT=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_COREDUMP=y
+
+#
+# Power management options
+#
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_PM_SLEEP=y
+# CONFIG_PM_AUTOSLEEP is not set
+# CONFIG_PM_WAKELOCKS is not set
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_APM_EMULATION is not set
+CONFIG_PM_CLK=y
+# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_CPU_PM=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARM_CPU_SUSPEND=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_DIAG is not set
+CONFIG_UNIX=y
+# CONFIG_UNIX_DIAG is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_ALGO=y
+CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+# CONFIG_IP_FIB_TRIE_STATS is not set
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
+# CONFIG_NET_IP_TUNNEL is not set
+CONFIG_IP_MROUTE=y
+# CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_NET_UDP_TUNNEL is not set
+# CONFIG_NET_FOU is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_INET_UDP_DIAG is not set
+# CONFIG_INET_DIAG_DESTROY is not set
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BIC=m
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+# CONFIG_TCP_CONG_HSTCP is not set
+# CONFIG_TCP_CONG_HYBLA is not set
+# CONFIG_TCP_CONG_VEGAS is not set
+# CONFIG_TCP_CONG_NV is not set
+# CONFIG_TCP_CONG_SCALABLE is not set
+# CONFIG_TCP_CONG_LP is not set
+# CONFIG_TCP_CONG_VENO is not set
+# CONFIG_TCP_CONG_YEAH is not set
+# CONFIG_TCP_CONG_ILLINOIS is not set
+# CONFIG_TCP_CONG_DCTCP is not set
+# CONFIG_TCP_CONG_CDG is not set
+# CONFIG_TCP_CONG_BBR is not set
+CONFIG_DEFAULT_CUBIC=y
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_TCP_MD5SIG=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NET_PTP_CLASSIFY is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP is not set
+# CONFIG_BRIDGE is not set
+CONFIG_HAVE_NET_DSA=y
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+CONFIG_DNS_RESOLVER=y
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+# CONFIG_VSOCKETS is not set
+# CONFIG_NETLINK_DIAG is not set
+# CONFIG_MPLS is not set
+# CONFIG_HSR is not set
+# CONFIG_NET_SWITCHDEV is not set
+# CONFIG_NET_L3_MASTER_DEV is not set
+# CONFIG_NET_NCSI is not set
+# CONFIG_SOCK_CGROUP_DATA is not set
+# CONFIG_CGROUP_NET_PRIO is not set
+# CONFIG_CGROUP_NET_CLASSID is not set
+CONFIG_NET_RX_BUSY_POLL=y
+CONFIG_BQL=y
+# CONFIG_BPF_JIT is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_AF_KCM is not set
+# CONFIG_STREAM_PARSER is not set
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_CFG80211=m
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+CONFIG_CFG80211_DEFAULT_PS=y
+# CONFIG_CFG80211_INTERNAL_REGDB is not set
+CONFIG_CFG80211_CRDA_SUPPORT=y
+CONFIG_CFG80211_WEXT=y
+# CONFIG_LIB80211 is not set
+CONFIG_MAC80211=m
+CONFIG_MAC80211_HAS_RC=y
+CONFIG_MAC80211_RC_MINSTREL=y
+CONFIG_MAC80211_RC_MINSTREL_HT=y
+# CONFIG_MAC80211_RC_MINSTREL_VHT is not set
+CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y
+CONFIG_MAC80211_RC_DEFAULT="minstrel_ht"
+CONFIG_MAC80211_MESH=y
+# CONFIG_MAC80211_MESSAGE_TRACING is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+CONFIG_MAC80211_STA_HASH_MAX_SIZE=0
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+# CONFIG_LWTUNNEL is not set
+# CONFIG_DST_CACHE is not set
+# CONFIG_NET_DEVLINK is not set
+CONFIG_MAY_USE_DEVLINK=y
+CONFIG_HAVE_CBPF_JIT=y
+
+#
+# Device Drivers
+#
+CONFIG_ARM_AMBA=y
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_STANDALONE=y
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set
+CONFIG_ALLOW_DEV_COREDUMP=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+CONFIG_REGMAP=y
+CONFIG_REGMAP_I2C=y
+CONFIG_REGMAP_SPI=y
+CONFIG_REGMAP_MMIO=y
+CONFIG_DMA_SHARED_BUFFER=y
+# CONFIG_FENCE_TRACE is not set
+
+#
+# Bus devices
+#
+# CONFIG_BRCMSTB_GISB_ARB is not set
+# CONFIG_VEXPRESS_CONFIG is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+CONFIG_MTD_OF_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
+# CONFIG_MTD_OOPS is not set
+# CONFIG_MTD_PARTITIONED_MASTER is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SST25L is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOCG3 is not set
+CONFIG_MTD_NAND_ECC=y
+# CONFIG_MTD_NAND_ECC_SMC is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_ECC_BCH is not set
+# CONFIG_MTD_SM_COMMON is not set
+# CONFIG_MTD_NAND_DENALI_DT is not set
+# CONFIG_MTD_NAND_GPIO is not set
+# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_DOCG4 is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_BRCMNAND is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_NAND_HISI504 is not set
+# CONFIG_MTD_NAND_MTK is not set
+CONFIG_MTD_SPI_NAND_GOKE=y
+# CONFIG_GOKE_NAND_ECC_STATUS_REPORT is not set
+# CONFIG_GOKE_NAND_FS_MAY_NO_YAFFS2 is not set
+CONFIG_MTD_SPI_NAND_FMC100=y
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR & LPDDR2 PCM memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+# CONFIG_MTD_LPDDR2_NVM is not set
+CONFIG_MTD_SPI_NOR=y
+# CONFIG_MTD_MT81xx_NOR is not set
+# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
+# CONFIG_SPI_CADENCE_QUADSPI is not set
+CONFIG_SPI_GOKE_SFC=y
+# CONFIG_CLOSE_SPI_8PIN_4IO is not set
+CONFIG_GOKE_SPI_BLOCK_PROTECT=y
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_LIMIT=20
+# CONFIG_MTD_UBI_FASTMAP is not set
+# CONFIG_MTD_UBI_GLUEBI is not set
+# CONFIG_MTD_UBI_BLOCK is not set
+CONFIG_DTC=y
+CONFIG_OF=y
+# CONFIG_OF_UNITTEST is not set
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_NET=y
+CONFIG_OF_MDIO=y
+CONFIG_OF_RESERVED_MEM=y
+# CONFIG_OF_OVERLAY is not set
+CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_NULL_BLK is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_DRBD is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=65536
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MG_DISK is not set
+# CONFIG_BLK_DEV_RBD is not set
+# CONFIG_NVME_TARGET is not set
+
+#
+# Misc devices
+#
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_DUMMY_IRQ is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_APDS9802ALS is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_ISL29020 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_BH1770 is not set
+# CONFIG_SENSORS_APDS990X is not set
+# CONFIG_HMC6352 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_TI_DAC7512 is not set
+# CONFIG_USB_SWITCH_FSA9480 is not set
+# CONFIG_LATTICE_ECP3_CONFIG is not set
+# CONFIG_SRAM is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_EEPROM_93XX46 is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+# CONFIG_SENSORS_LIS3_SPI is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
+
+#
+# Altera FPGA firmware download module
+#
+# CONFIG_ALTERA_STAPL is not set
+
+#
+# Intel MIC Bus Driver
+#
+
+#
+# SCIF Bus Driver
+#
+
+#
+# VOP Bus Driver
+#
+
+#
+# Intel MIC Host Driver
+#
+
+#
+# Intel MIC Card Driver
+#
+
+#
+# SCIF Driver
+#
+
+#
+# Intel MIC Coprocessor State Management (COSM) Drivers
+#
+
+#
+# VOP Driver
+#
+# CONFIG_ECHO is not set
+# CONFIG_CXL_BASE is not set
+# CONFIG_CXL_AFU_DRIVER_OPS is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+CONFIG_SCSI_NETLINK=y
+# CONFIG_SCSI_MQ_DEFAULT is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+CONFIG_SCSI_FC_ATTRS=y
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_ISCSI_BOOT_SYSFS is not set
+# CONFIG_SCSI_UFSHCD is not set
+# CONFIG_LIBFC is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_TARGET_CORE is not set
+CONFIG_NETDEVICES=y
+CONFIG_NET_CORE=y
+# CONFIG_BONDING is not set
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_NET_TEAM is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_VXLAN is not set
+# CONFIG_MACSEC is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_TUN is not set
+# CONFIG_TUN_VNET_CROSS_LE is not set
+# CONFIG_VETH is not set
+# CONFIG_NLMON is not set
+
+#
+# CAIF transport drivers
+#
+
+#
+# Distributed Switch Architecture drivers
+#
+CONFIG_ETHERNET=y
+# CONFIG_ALTERA_TSE is not set
+# CONFIG_NET_VENDOR_AMAZON is not set
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_AURORA is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_DM9000 is not set
+# CONFIG_DNET is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_HISILICON is not set
+CONFIG_NET_VENDOR_GOKE=y
+CONFIG_GOKE_FEMAC=y
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+CONFIG_NET_VENDOR_MICROCHIP=y
+# CONFIG_ENC28J60 is not set
+# CONFIG_ENCX24J600 is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
+# CONFIG_ETHOC is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_PHYLIB=y
+CONFIG_SWPHY=y
+
+#
+# MDIO bus device drivers
+#
+# CONFIG_MDIO_BCM_UNIMAC is not set
+# CONFIG_MDIO_BITBANG is not set
+# CONFIG_MDIO_BUS_MUX_GPIO is not set
+# CONFIG_MDIO_BUS_MUX_MMIOREG is not set
+CONFIG_MDIO_GOKE_FEMAC=y
+# CONFIG_MDIO_HISI_FEMAC is not set
+
+#
+# MII PHY device drivers
+#
+# CONFIG_AMD_PHY is not set
+# CONFIG_AQUANTIA_PHY is not set
+# CONFIG_AT803X_PHY is not set
+# CONFIG_BCM7XXX_PHY is not set
+# CONFIG_BCM87XX_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_DP83848_PHY is not set
+# CONFIG_DP83867_PHY is not set
+CONFIG_FIXED_PHY=y
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_INTEL_XWAY_PHY is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_MICREL_PHY is not set
+# CONFIG_MICROCHIP_PHY is not set
+# CONFIG_MICROSEMI_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_TERANETICS_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_XILINX_GMII2RGMII is not set
+# CONFIG_MICREL_KS8995MA is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_USB_NET_DRIVERS is not set
+# CONFIG_WLAN is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_ISDN is not set
+# CONFIG_NVM is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+# CONFIG_INPUT_MATRIXKMAP is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ADP5588 is not set
+# CONFIG_KEYBOARD_ADP5589 is not set
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_QT1070 is not set
+# CONFIG_KEYBOARD_QT2160 is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_KEYBOARD_GPIO_POLLED is not set
+# CONFIG_KEYBOARD_TCA6416 is not set
+# CONFIG_KEYBOARD_TCA8418 is not set
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_LM8333 is not set
+# CONFIG_KEYBOARD_MAX7359 is not set
+# CONFIG_KEYBOARD_MCS is not set
+# CONFIG_KEYBOARD_MPR121 is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_SAMSUNG is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_OMAP4 is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_CAP11XX is not set
+# CONFIG_KEYBOARD_BCM is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_BYD=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_CYPRESS=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_SENTELIC is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+CONFIG_MOUSE_PS2_FOCALTECH=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_CYAPA is not set
+# CONFIG_MOUSE_ELAN_I2C is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+# CONFIG_MOUSE_SYNAPTICS_I2C is not set
+# CONFIG_MOUSE_SYNAPTICS_USB is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_AD714X is not set
+# CONFIG_INPUT_ATMEL_CAPTOUCH is not set
+# CONFIG_INPUT_BMA150 is not set
+# CONFIG_INPUT_E3X0_BUTTON is not set
+# CONFIG_INPUT_MMA8450 is not set
+# CONFIG_INPUT_MPU3050 is not set
+# CONFIG_INPUT_GP2A is not set
+# CONFIG_INPUT_GPIO_BEEPER is not set
+# CONFIG_INPUT_GPIO_TILT_POLLED is not set
+# CONFIG_INPUT_GPIO_DECODER is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_KXTJ9 is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
+CONFIG_INPUT_UINPUT=y
+# CONFIG_INPUT_PCF8574 is not set
+# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
+# CONFIG_INPUT_ADXL34X is not set
+# CONFIG_INPUT_CMA3000 is not set
+# CONFIG_INPUT_DRV260X_HAPTICS is not set
+# CONFIG_INPUT_DRV2665_HAPTICS is not set
+# CONFIG_INPUT_DRV2667_HAPTICS is not set
+# CONFIG_RMI4_CORE is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_AMBAKMI is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_ALTERA_PS2 is not set
+# CONFIG_SERIO_PS2MULT is not set
+# CONFIG_SERIO_ARC_PS2 is not set
+# CONFIG_SERIO_APBPS2 is not set
+# CONFIG_USERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_TTY=y
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_VT_CONSOLE_SLEEP=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVMEM=y
+# CONFIG_DEVKMEM is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_EARLYCON=y
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_AMBA_PL010 is not set
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set
+# CONFIG_SERIAL_MAX3100 is not set
+# CONFIG_SERIAL_MAX310X is not set
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_SCCNXP is not set
+# CONFIG_SERIAL_SC16IS7XX is not set
+# CONFIG_SERIAL_BCM63XX is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_IFX6X60 is not set
+# CONFIG_SERIAL_XILINX_PS_UART is not set
+# CONFIG_SERIAL_ARC is not set
+# CONFIG_SERIAL_FSL_LPUART is not set
+# CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set
+# CONFIG_SERIAL_ST_ASC is not set
+# CONFIG_SERIAL_STM32 is not set
+# CONFIG_HVC_DCC is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_XILLYBUS is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MUX=y
+
+#
+# Multiplexer I2C Chip support
+#
+# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set
+# CONFIG_I2C_MUX_GPIO is not set
+# CONFIG_I2C_MUX_PCA9541 is not set
+# CONFIG_I2C_MUX_PCA954x is not set
+# CONFIG_I2C_MUX_PINCTRL is not set
+# CONFIG_I2C_MUX_REG is not set
+# CONFIG_I2C_DEMUX_PINCTRL is not set
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_CBUS_GPIO is not set
+# CONFIG_I2C_DESIGNWARE_PLATFORM is not set
+# CONFIG_I2C_EMEV2 is not set
+# CONFIG_I2C_GPIO is not set
+CONFIG_I2C_GOKE=y
+# CONFIG_I2C_NOMADIK is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_PXA_PCI is not set
+# CONFIG_I2C_RK3X is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_DIOLAN_U2C is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_ROBOTFUZZ_OSIF is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+CONFIG_DMA_MSG_MIN_LEN=5
+CONFIG_DMA_MSG_MAX_LEN=4090
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_SLAVE is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_ALTERA is not set
+# CONFIG_SPI_AXI_SPI_ENGINE is not set
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_CADENCE is not set
+# CONFIG_SPI_DESIGNWARE is not set
+# CONFIG_SPI_GPIO is not set
+# CONFIG_SPI_FSL_SPI is not set
+# CONFIG_SPI_OC_TINY is not set
+CONFIG_SPI_PL022=y
+# CONFIG_SPI_PXA2XX_PCI is not set
+# CONFIG_SPI_ROCKCHIP is not set
+# CONFIG_SPI_SC18IS602 is not set
+# CONFIG_SPI_XCOMM is not set
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_ZYNQMP_GQSPI is not set
+
+#
+# SPI Protocol Masters
+#
+CONFIG_SPI_SPIDEV=y
+# CONFIG_SPI_LOOPBACK_TEST is not set
+# CONFIG_SPI_TLE62X0 is not set
+# CONFIG_SPMI is not set
+# CONFIG_HSI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+# CONFIG_PTP_1588_CLOCK is not set
+
+#
+# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
+#
+CONFIG_PINCTRL=y
+
+#
+# Pin controllers
+#
+CONFIG_PINMUX=y
+CONFIG_PINCONF=y
+CONFIG_GENERIC_PINCONF=y
+# CONFIG_DEBUG_PINCTRL is not set
+# CONFIG_PINCTRL_AMD is not set
+CONFIG_PINCTRL_SINGLE=y
+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
+CONFIG_GPIOLIB=y
+CONFIG_OF_GPIO=y
+CONFIG_GPIOLIB_IRQCHIP=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO drivers
+#
+# CONFIG_GPIO_74XX_MMIO is not set
+# CONFIG_GPIO_ALTERA is not set
+# CONFIG_GPIO_DWAPB is not set
+# CONFIG_GPIO_EM is not set
+# CONFIG_GPIO_GENERIC_PLATFORM is not set
+# CONFIG_GPIO_GRGPIO is not set
+# CONFIG_GPIO_MOCKUP is not set
+# CONFIG_GPIO_MPC8XXX is not set
+CONFIG_GPIO_PL061=y
+# CONFIG_GPIO_SYSCON is not set
+# CONFIG_GPIO_XILINX is not set
+# CONFIG_GPIO_ZEVIO is not set
+# CONFIG_GPIO_ZX is not set
+
+#
+# I2C GPIO expanders
+#
+# CONFIG_GPIO_ADP5588 is not set
+# CONFIG_GPIO_ADNP is not set
+# CONFIG_GPIO_MAX7300 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_SX150X is not set
+# CONFIG_GPIO_TPIC2810 is not set
+# CONFIG_GPIO_TS4900 is not set
+
+#
+# MFD GPIO expanders
+#
+# CONFIG_HTC_EGPIO is not set
+
+#
+# SPI GPIO expanders
+#
+# CONFIG_GPIO_74X164 is not set
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MC33880 is not set
+# CONFIG_GPIO_PISOSR is not set
+
+#
+# SPI or I2C GPIO expanders
+#
+# CONFIG_GPIO_MCP23S08 is not set
+
+#
+# USB GPIO expanders
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_AVS is not set
+CONFIG_POWER_RESET=y
+# CONFIG_POWER_RESET_BRCMKONA is not set
+# CONFIG_POWER_RESET_BRCMSTB is not set
+CONFIG_POWER_RESET_GOKE=y
+# CONFIG_POWER_RESET_GPIO is not set
+# CONFIG_POWER_RESET_GPIO_RESTART is not set
+# CONFIG_POWER_RESET_LTC2952 is not set
+# CONFIG_POWER_RESET_RESTART is not set
+# CONFIG_POWER_RESET_VERSATILE is not set
+# CONFIG_POWER_RESET_SYSCON is not set
+# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set
+# CONFIG_SYSCON_REBOOT_MODE is not set
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_TEST_POWER is not set
+# CONFIG_BATTERY_DS2780 is not set
+# CONFIG_BATTERY_DS2781 is not set
+# CONFIG_BATTERY_DS2782 is not set
+# CONFIG_BATTERY_SBS is not set
+# CONFIG_BATTERY_BQ27XXX is not set
+# CONFIG_BATTERY_MAX17040 is not set
+# CONFIG_BATTERY_MAX17042 is not set
+# CONFIG_CHARGER_MAX8903 is not set
+# CONFIG_CHARGER_LP8727 is not set
+# CONFIG_CHARGER_GPIO is not set
+# CONFIG_CHARGER_BQ2415X is not set
+# CONFIG_CHARGER_BQ24190 is not set
+# CONFIG_CHARGER_BQ24257 is not set
+# CONFIG_CHARGER_BQ24735 is not set
+# CONFIG_CHARGER_BQ25890 is not set
+# CONFIG_CHARGER_SMB347 is not set
+# CONFIG_BATTERY_GAUGE_LTC2941 is not set
+# CONFIG_CHARGER_RT9455 is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+CONFIG_MFD_CORE=y
+# CONFIG_MFD_ACT8945A is not set
+# CONFIG_MFD_AS3711 is not set
+# CONFIG_MFD_AS3722 is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_AAT2870_CORE is not set
+# CONFIG_MFD_ATMEL_FLEXCOM is not set
+# CONFIG_MFD_ATMEL_HLCDC is not set
+# CONFIG_MFD_BCM590XX is not set
+# CONFIG_MFD_AXP20X_I2C is not set
+# CONFIG_MFD_CROS_EC is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_DA9052_SPI is not set
+# CONFIG_MFD_DA9052_I2C is not set
+# CONFIG_MFD_DA9055 is not set
+# CONFIG_MFD_DA9062 is not set
+# CONFIG_MFD_DA9063 is not set
+# CONFIG_MFD_DA9150 is not set
+# CONFIG_MFD_DLN2 is not set
+# CONFIG_MFD_EXYNOS_LPASS is not set
+# CONFIG_MFD_MC13XXX_SPI is not set
+# CONFIG_MFD_MC13XXX_I2C is not set
+# CONFIG_MFD_HI6421_PMIC is not set
+CONFIG_MFD_GOKE_FMC=y
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_HTC_I2CPLD is not set
+# CONFIG_INTEL_SOC_PMIC is not set
+# CONFIG_MFD_KEMPLD is not set
+# CONFIG_MFD_88PM800 is not set
+# CONFIG_MFD_88PM805 is not set
+# CONFIG_MFD_88PM860X is not set
+# CONFIG_MFD_MAX14577 is not set
+# CONFIG_MFD_MAX77620 is not set
+# CONFIG_MFD_MAX77686 is not set
+# CONFIG_MFD_MAX77693 is not set
+# CONFIG_MFD_MAX77843 is not set
+# CONFIG_MFD_MAX8907 is not set
+# CONFIG_MFD_MAX8925 is not set
+# CONFIG_MFD_MAX8997 is not set
+# CONFIG_MFD_MAX8998 is not set
+# CONFIG_MFD_MT6397 is not set
+# CONFIG_MFD_MENF21BMC is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_MFD_VIPERBOARD is not set
+# CONFIG_MFD_RETU is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_PM8921_CORE is not set
+# CONFIG_MFD_RT5033 is not set
+# CONFIG_MFD_RTSX_USB is not set
+# CONFIG_MFD_RC5T583 is not set
+# CONFIG_MFD_RK808 is not set
+# CONFIG_MFD_RN5T618 is not set
+# CONFIG_MFD_SEC_CORE is not set
+# CONFIG_MFD_SI476X_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_SKY81452 is not set
+# CONFIG_MFD_SMSC is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_MFD_STMPE is not set
+CONFIG_MFD_SYSCON=y
+# CONFIG_MFD_TI_AM335X_TSCADC is not set
+# CONFIG_MFD_LP3943 is not set
+# CONFIG_MFD_LP8788 is not set
+# CONFIG_MFD_PALMAS is not set
+# CONFIG_TPS6105X is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TPS6507X is not set
+# CONFIG_MFD_TPS65086 is not set
+# CONFIG_MFD_TPS65090 is not set
+# CONFIG_MFD_TPS65217 is not set
+# CONFIG_MFD_TI_LP873X is not set
+# CONFIG_MFD_TPS65218 is not set
+# CONFIG_MFD_TPS6586X is not set
+# CONFIG_MFD_TPS65910 is not set
+# CONFIG_MFD_TPS65912_I2C is not set
+# CONFIG_MFD_TPS65912_SPI is not set
+# CONFIG_MFD_TPS80031 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_TWL6040_CORE is not set
+# CONFIG_MFD_WL1273_CORE is not set
+# CONFIG_MFD_LM3533 is not set
+# CONFIG_MFD_TC3589X is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_MFD_ARIZONA_I2C is not set
+# CONFIG_MFD_ARIZONA_SPI is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X_I2C is not set
+# CONFIG_MFD_WM831X_SPI is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8994 is not set
+# CONFIG_REGULATOR is not set
+CONFIG_MEDIA_SUPPORT=y
+
+#
+# Multimedia core support
+#
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set
+# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set
+# CONFIG_MEDIA_RADIO_SUPPORT is not set
+# CONFIG_MEDIA_SDR_SUPPORT is not set
+# CONFIG_MEDIA_RC_SUPPORT is not set
+# CONFIG_MEDIA_CONTROLLER is not set
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L2=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEOBUF2_CORE=y
+CONFIG_VIDEOBUF2_MEMOPS=y
+CONFIG_VIDEOBUF2_VMALLOC=y
+# CONFIG_TTPCI_EEPROM is not set
+
+#
+# Media drivers
+#
+CONFIG_MEDIA_USB_SUPPORT=y
+
+#
+# Webcam devices
+#
+CONFIG_USB_VIDEO_CLASS=y
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+CONFIG_USB_GSPCA=m
+# CONFIG_USB_M5602 is not set
+# CONFIG_USB_STV06XX is not set
+# CONFIG_USB_GL860 is not set
+# CONFIG_USB_GSPCA_BENQ is not set
+# CONFIG_USB_GSPCA_CONEX is not set
+# CONFIG_USB_GSPCA_CPIA1 is not set
+# CONFIG_USB_GSPCA_DTCS033 is not set
+# CONFIG_USB_GSPCA_ETOMS is not set
+# CONFIG_USB_GSPCA_FINEPIX is not set
+# CONFIG_USB_GSPCA_JEILINJ is not set
+# CONFIG_USB_GSPCA_JL2005BCD is not set
+# CONFIG_USB_GSPCA_KINECT is not set
+# CONFIG_USB_GSPCA_KONICA is not set
+# CONFIG_USB_GSPCA_MARS is not set
+# CONFIG_USB_GSPCA_MR97310A is not set
+# CONFIG_USB_GSPCA_NW80X is not set
+# CONFIG_USB_GSPCA_OV519 is not set
+# CONFIG_USB_GSPCA_OV534 is not set
+# CONFIG_USB_GSPCA_OV534_9 is not set
+# CONFIG_USB_GSPCA_PAC207 is not set
+# CONFIG_USB_GSPCA_PAC7302 is not set
+# CONFIG_USB_GSPCA_PAC7311 is not set
+# CONFIG_USB_GSPCA_SE401 is not set
+# CONFIG_USB_GSPCA_SN9C2028 is not set
+# CONFIG_USB_GSPCA_SN9C20X is not set
+# CONFIG_USB_GSPCA_SONIXB is not set
+# CONFIG_USB_GSPCA_SONIXJ is not set
+# CONFIG_USB_GSPCA_SPCA500 is not set
+# CONFIG_USB_GSPCA_SPCA501 is not set
+# CONFIG_USB_GSPCA_SPCA505 is not set
+# CONFIG_USB_GSPCA_SPCA506 is not set
+# CONFIG_USB_GSPCA_SPCA508 is not set
+# CONFIG_USB_GSPCA_SPCA561 is not set
+# CONFIG_USB_GSPCA_SPCA1528 is not set
+# CONFIG_USB_GSPCA_SQ905 is not set
+# CONFIG_USB_GSPCA_SQ905C is not set
+# CONFIG_USB_GSPCA_SQ930X is not set
+# CONFIG_USB_GSPCA_STK014 is not set
+# CONFIG_USB_GSPCA_STK1135 is not set
+# CONFIG_USB_GSPCA_STV0680 is not set
+# CONFIG_USB_GSPCA_SUNPLUS is not set
+# CONFIG_USB_GSPCA_T613 is not set
+# CONFIG_USB_GSPCA_TOPRO is not set
+# CONFIG_USB_GSPCA_TOUPTEK is not set
+# CONFIG_USB_GSPCA_TV8532 is not set
+# CONFIG_USB_GSPCA_VC032X is not set
+# CONFIG_USB_GSPCA_VICAM is not set
+# CONFIG_USB_GSPCA_XIRLINK_CIT is not set
+# CONFIG_USB_GSPCA_ZC3XX is not set
+# CONFIG_USB_PWC is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_USB_ZR364XX is not set
+# CONFIG_USB_STKWEBCAM is not set
+# CONFIG_USB_S2255 is not set
+
+#
+# Webcam, TV (analog/digital) USB devices
+#
+# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_V4L_PLATFORM_DRIVERS is not set
+# CONFIG_V4L_MEM2MEM_DRIVERS is not set
+# CONFIG_V4L_TEST_DRIVERS is not set
+
+#
+# Supported MMC/SDIO adapters
+#
+# CONFIG_CYPRESS_FIRMWARE is not set
+
+#
+# Media ancillary drivers (tuners, sensors, i2c, spi, frontends)
+#
+CONFIG_MEDIA_SUBDRV_AUTOSELECT=y
+
+#
+# Audio decoders, processors and mixers
+#
+
+#
+# RDS decoders
+#
+
+#
+# Video decoders
+#
+
+#
+# Video and audio decoders
+#
+
+#
+# Video encoders
+#
+
+#
+# Camera sensor devices
+#
+
+#
+# Flash devices
+#
+
+#
+# Video improvement chips
+#
+
+#
+# Audio/Video compression chips
+#
+
+#
+# Miscellaneous helper chips
+#
+
+#
+# Sensors used on soc_camera driver
+#
+
+#
+# Tools to develop new frontends
+#
+# CONFIG_DVB_DUMMY_FE is not set
+
+#
+# Graphics support
+#
+# CONFIG_IMX_IPUV3_CORE is not set
+# CONFIG_DRM is not set
+
+#
+# ACP (Audio CoProcessor) Configuration
+#
+
+#
+# Frame buffer Devices
+#
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+CONFIG_FB_CMDLINE=y
+CONFIG_FB_NOTIFY=y
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_ARMCLCD is not set
+# CONFIG_FB_OPENCORES is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_SMSCUFX is not set
+# CONFIG_FB_UDL is not set
+# CONFIG_FB_IBM_GXT4500 is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_FB_AUO_K190X is not set
+# CONFIG_FB_SIMPLE is not set
+# CONFIG_FB_SSD1307 is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+# CONFIG_LOGO is not set
+# CONFIG_SOUND is not set
+
+#
+# HID support
+#
+CONFIG_HID=y
+# CONFIG_HID_BATTERY_STRENGTH is not set
+# CONFIG_HIDRAW is not set
+# CONFIG_UHID is not set
+CONFIG_HID_GENERIC=y
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_ACRUX is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_APPLEIR is not set
+# CONFIG_HID_AUREAL is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_BETOP_FF is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_CMEDIA is not set
+# CONFIG_HID_CP2112 is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EMS_FF is not set
+# CONFIG_HID_ELECOM is not set
+# CONFIG_HID_ELO is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_GEMBIRD is not set
+# CONFIG_HID_GFRM is not set
+# CONFIG_HID_HOLTEK is not set
+# CONFIG_HID_KEYTOUCH is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_UCLOGIC is not set
+# CONFIG_HID_WALTOP is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_ICADE is not set
+# CONFIG_HID_TWINHAN is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LCPOWER is not set
+# CONFIG_HID_LENOVO is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MAGICMOUSE is not set
+CONFIG_HID_MICROSOFT=y
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_MULTITOUCH is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_ORTEK is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PENMOUNT is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_PICOLCD is not set
+# CONFIG_HID_PLANTRONICS is not set
+# CONFIG_HID_PRIMAX is not set
+# CONFIG_HID_ROCCAT is not set
+# CONFIG_HID_SAITEK is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SPEEDLINK is not set
+# CONFIG_HID_STEELSERIES is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_RMI is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TIVO is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_WACOM is not set
+# CONFIG_HID_XINMO is not set
+# CONFIG_HID_ZEROPLUS is not set
+# CONFIG_HID_ZYDACRON is not set
+# CONFIG_HID_SENSOR_HUB is not set
+# CONFIG_HID_ALPS is not set
+
+#
+# USB HID support
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# I2C HID support
+#
+# CONFIG_I2C_HID is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_COMMON=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB=y
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEFAULT_PERSIST=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_PLATFORM=y
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+# CONFIG_USB_FOTG210_HCD is not set
+# CONFIG_USB_MAX3421_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HCD_TEST_MODE is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_REALTEK is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_STORAGE_ENE_UB6250 is not set
+# CONFIG_USB_UAS is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USBIP_CORE is not set
+# CONFIG_USB_MUSB_HDRC is not set
+CONFIG_USB_DWC3=y
+# CONFIG_USB_DWC3_HOST is not set
+# CONFIG_USB_DWC3_GADGET is not set
+CONFIG_USB_DWC3_DUAL_ROLE=y
+
+#
+# Platform Glue Driver Support
+#
+CONFIG_USB_DWC3_OF_SIMPLE=y
+# CONFIG_USB_DWC2 is not set
+# CONFIG_USB_CHIPIDEA is not set
+# CONFIG_USB_ISP1760 is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_EHSET_TEST_FIXTURE is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_YUREX is not set
+# CONFIG_USB_EZUSB_FX2 is not set
+# CONFIG_USB_HSIC_USB3503 is not set
+# CONFIG_USB_HSIC_USB4604 is not set
+# CONFIG_USB_LINK_LAYER_TEST is not set
+
+#
+# USB Physical Layer drivers
+#
+# CONFIG_USB_PHY is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_USB_ISP1301 is not set
+# CONFIG_USB_ULPI is not set
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2
+
+#
+# USB Peripheral Controller
+#
+# CONFIG_USB_FUSB300 is not set
+# CONFIG_USB_FOTG210_UDC is not set
+# CONFIG_USB_GR_UDC is not set
+# CONFIG_USB_R8A66597 is not set
+# CONFIG_USB_PXA27X is not set
+# CONFIG_USB_MV_UDC is not set
+# CONFIG_USB_MV_U3D is not set
+# CONFIG_USB_M66592 is not set
+# CONFIG_USB_BDC_UDC is not set
+# CONFIG_USB_NET2272 is not set
+# CONFIG_USB_GADGET_XILINX is not set
+# CONFIG_USB_DUMMY_HCD is not set
+CONFIG_USB_LIBCOMPOSITE=m
+CONFIG_USB_F_ACM=m
+CONFIG_USB_U_SERIAL=m
+CONFIG_USB_U_ETHER=m
+CONFIG_USB_F_ECM=m
+CONFIG_USB_F_RNDIS=m
+CONFIG_USB_F_MASS_STORAGE=m
+CONFIG_USB_CONFIGFS=m
+# CONFIG_USB_CONFIGFS_SERIAL is not set
+CONFIG_USB_CONFIGFS_ACM=y
+# CONFIG_USB_CONFIGFS_OBEX is not set
+# CONFIG_USB_CONFIGFS_NCM is not set
+CONFIG_USB_CONFIGFS_ECM=y
+# CONFIG_USB_CONFIGFS_ECM_SUBSET is not set
+CONFIG_USB_CONFIGFS_RNDIS=y
+# CONFIG_USB_CONFIGFS_EEM is not set
+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
+# CONFIG_USB_CONFIGFS_F_LB_SS is not set
+# CONFIG_USB_CONFIGFS_F_FS is not set
+# CONFIG_USB_CONFIGFS_F_HID is not set
+# CONFIG_USB_CONFIGFS_F_UVC is not set
+# CONFIG_USB_CONFIGFS_F_PRINTER is not set
+# CONFIG_USB_ULPI_BUS is not set
+# CONFIG_UWB is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_PWRSEQ_EMMC=y
+CONFIG_PWRSEQ_SIMPLE=y
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_MINORS=8
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_ARMMMCI is not set
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+# CONFIG_MMC_SDHCI_OF_ARASAN is not set
+# CONFIG_MMC_SDHCI_OF_AT91 is not set
+CONFIG_MMC_SDHCI_GOKE=y
+# CONFIG_MMC_SDHCI_F_SDH30 is not set
+# CONFIG_MMC_SPI is not set
+# CONFIG_MMC_DW is not set
+# CONFIG_MMC_VUB300 is not set
+# CONFIG_MMC_USHC is not set
+# CONFIG_MMC_USDHI6ROL0 is not set
+# CONFIG_MMC_MTK is not set
+# CONFIG_MMC_CQ_HCI is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_EDAC_ATOMIC_SCRUB=y
+CONFIG_EDAC_SUPPORT=y
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+CONFIG_RTC_SYSTOHC=y
+CONFIG_RTC_SYSTOHC_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_ABB5ZES3 is not set
+# CONFIG_RTC_DRV_ABX80X is not set
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_HYM8563 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_ISL12022 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8523 is not set
+# CONFIG_RTC_DRV_PCF85063 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_BQ32K is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8010 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+# CONFIG_RTC_DRV_EM3027 is not set
+# CONFIG_RTC_DRV_RV8803 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T93 is not set
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1302 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1343 is not set
+# CONFIG_RTC_DRV_DS1347 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6916 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RX4581 is not set
+# CONFIG_RTC_DRV_RX6110 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
+# CONFIG_RTC_DRV_MCP795 is not set
+CONFIG_RTC_I2C_AND_SPI=y
+
+#
+# SPI and I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS3232 is not set
+# CONFIG_RTC_DRV_PCF2127 is not set
+# CONFIG_RTC_DRV_RV3029C2 is not set
+
+#
+# Platform RTC drivers
+#
+CONFIG_RTC_DRV_GOKE=y
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1685_FAMILY is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_DS2404 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+# CONFIG_RTC_DRV_ZYNQMP is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_PL030 is not set
+# CONFIG_RTC_DRV_PL031 is not set
+# CONFIG_RTC_DRV_SNVS is not set
+
+#
+# HID Sensor RTC drivers
+#
+# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set
+# CONFIG_DMADEVICES is not set
+
+#
+# DMABUF options
+#
+# CONFIG_SYNC_FILE is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+# CONFIG_VIRT_DRIVERS is not set
+
+#
+# Virtio drivers
+#
+# CONFIG_VIRTIO_MMIO is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_STAGING is not set
+# CONFIG_GOLDFISH is not set
+# CONFIG_CHROME_PLATFORMS is not set
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_HAVE_CLK_PREPARE=y
+CONFIG_COMMON_CLK=y
+
+#
+# Common Clock Framework
+#
+# CONFIG_COMMON_CLK_SI5351 is not set
+# CONFIG_COMMON_CLK_SI514 is not set
+# CONFIG_COMMON_CLK_SI570 is not set
+# CONFIG_COMMON_CLK_CDCE706 is not set
+# CONFIG_COMMON_CLK_CDCE925 is not set
+# CONFIG_COMMON_CLK_CS2000_CP is not set
+# CONFIG_CLK_QORIQ is not set
+# CONFIG_COMMON_CLK_NXP is not set
+# CONFIG_COMMON_CLK_PXA is not set
+# CONFIG_COMMON_CLK_PIC32 is not set
+CONFIG_COMMON_CLK_GK7605V100=y
+CONFIG_RESET_GOKE=y
+
+#
+# Hardware Spinlock drivers
+#
+
+#
+# Clock Source drivers
+#
+CONFIG_CLKSRC_OF=y
+CONFIG_CLKSRC_PROBE=y
+CONFIG_CLKSRC_MMIO=y
+CONFIG_ARM_ARCH_TIMER=y
+CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y
+# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS is not set
+CONFIG_ARM_TIMER_SP804=y
+# CONFIG_ATMEL_PIT is not set
+# CONFIG_SH_TIMER_CMT is not set
+# CONFIG_SH_TIMER_MTU2 is not set
+# CONFIG_SH_TIMER_TMU is not set
+# CONFIG_EM_TIMER_STI is not set
+# CONFIG_MAILBOX is not set
+# CONFIG_IOMMU_SUPPORT is not set
+
+#
+# Remoteproc drivers
+#
+# CONFIG_STE_MODEM_RPROC is not set
+
+#
+# Rpmsg drivers
+#
+
+#
+# SOC (System On Chip) specific Drivers
+#
+
+#
+# Broadcom SoC drivers
+#
+# CONFIG_SOC_BRCMSTB is not set
+# CONFIG_SUNXI_SRAM is not set
+# CONFIG_SOC_TI is not set
+# CONFIG_PM_DEVFREQ is not set
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
+# CONFIG_IIO is not set
+# CONFIG_PWM is not set
+CONFIG_IRQCHIP=y
+CONFIG_ARM_GIC=y
+CONFIG_ARM_GIC_MAX_NR=1
+# CONFIG_IPACK_BUS is not set
+CONFIG_RESET_CONTROLLER=y
+# CONFIG_RESET_ATH79 is not set
+# CONFIG_RESET_BERLIN is not set
+# CONFIG_RESET_LPC18XX is not set
+# CONFIG_RESET_MESON is not set
+# CONFIG_RESET_PISTACHIO is not set
+# CONFIG_RESET_SOCFPGA is not set
+# CONFIG_RESET_STM32 is not set
+# CONFIG_RESET_SUNXI is not set
+# CONFIG_TI_SYSCON_RESET is not set
+# CONFIG_RESET_ZYNQ is not set
+# CONFIG_FMC is not set
+
+#
+# PHY Subsystem
+#
+CONFIG_GENERIC_PHY=y
+# CONFIG_PHY_PXA_28NM_HSIC is not set
+# CONFIG_PHY_PXA_28NM_USB2 is not set
+# CONFIG_BCM_KONA_USB2_PHY is not set
+CONFIG_PHY_GOKE_USBP2=y
+# CONFIG_USB_MODE_OPTION is not set
+# CONFIG_POWERCAP is not set
+# CONFIG_MCB is not set
+
+#
+# Performance monitor support
+#
+# CONFIG_RAS is not set
+
+#
+# Android
+#
+# CONFIG_ANDROID is not set
+# CONFIG_NVMEM is not set
+# CONFIG_STM is not set
+# CONFIG_INTEL_TH is not set
+
+#
+# FPGA Configuration Support
+#
+# CONFIG_FPGA is not set
+
+#
+# goke driver support
+#
+
+#
+# Firmware Drivers
+#
+# CONFIG_FIRMWARE_MEMMAP is not set
+# CONFIG_FW_CFG_SYSFS is not set
+CONFIG_HAVE_ARM_SMCCC=y
+
+#
+# File systems
+#
+CONFIG_DCACHE_WORD_ACCESS=y
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_USE_FOR_EXT2=y
+# CONFIG_EXT4_FS_POSIX_ACL is not set
+# CONFIG_EXT4_FS_SECURITY is not set
+# CONFIG_EXT4_ENCRYPTION is not set
+# CONFIG_EXT4_DEBUG is not set
+CONFIG_JBD2=y
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+# CONFIG_F2FS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_EXPORTFS=y
+# CONFIG_EXPORTFS_BLOCK_OPS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_MANDATORY_FILE_LOCKING=y
+# CONFIG_FS_ENCRYPTION is not set
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_QUOTACTL is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+# CONFIG_OVERLAY_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_FAT_DEFAULT_UTF8 is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_PROC_CHILDREN is not set
+CONFIG_KERNFS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_TMPFS_XATTR=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=y
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ORANGEFS_FS is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_YAFFS_FS=y
+CONFIG_YAFFS_YAFFS1=y
+# CONFIG_YAFFS_9BYTE_TAGS is not set
+# CONFIG_YAFFS_DOES_ECC is not set
+CONFIG_YAFFS_YAFFS2=y
+CONFIG_YAFFS_AUTO_YAFFS2=y
+# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set
+# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
+# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set
+# CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING is not set
+# CONFIG_YAFFS_DISABLE_BACKGROUND is not set
+# CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING is not set
+CONFIG_YAFFS_XATTR=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+# CONFIG_JFFS2_LZMA is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_UBIFS_FS=y
+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_ATIME_SUPPORT is not set
+# CONFIG_LOGFS is not set
+CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX6FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_PSTORE is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V2=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+# CONFIG_NFS_SWAP is not set
+# CONFIG_NFS_V4_1 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFS_USE_LEGACY_DNS is not set
+CONFIG_NFS_USE_KERNEL_DNS=y
+# CONFIG_NFSD is not set
+CONFIG_GRACE_PERIOD=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_ACL_SUPPORT=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_DEBUG is not set
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=y
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+# CONFIG_NLS_MAC_ROMAN is not set
+# CONFIG_NLS_MAC_CELTIC is not set
+# CONFIG_NLS_MAC_CENTEURO is not set
+# CONFIG_NLS_MAC_CROATIAN is not set
+# CONFIG_NLS_MAC_CYRILLIC is not set
+# CONFIG_NLS_MAC_GAELIC is not set
+# CONFIG_NLS_MAC_GREEK is not set
+# CONFIG_NLS_MAC_ICELAND is not set
+# CONFIG_NLS_MAC_INUIT is not set
+# CONFIG_NLS_MAC_ROMANIAN is not set
+# CONFIG_NLS_MAC_TURKISH is not set
+CONFIG_NLS_UTF8=y
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+
+#
+# printk and dmesg options
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
+# CONFIG_BOOT_PRINTK_DELAY is not set
+
+#
+# Compile-time checks and compiler options
+#
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_READABLE_ASM is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_PAGE_OWNER is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_SECTION_MISMATCH_WARN_ONLY=y
+CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_DEBUG_KERNEL=y
+
+#
+# Memory Debugging
+#
+# CONFIG_PAGE_EXTENSION is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_PAGE_POISONING is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_SHIRQ is not set
+
+#
+# Debug Lockups and Hangs
+#
+# CONFIG_LOCKUP_DETECTOR is not set
+# CONFIG_DETECT_HUNG_TASK is not set
+# CONFIG_WQ_WATCHDOG is not set
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+CONFIG_PANIC_TIMEOUT=0
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHED_INFO is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_SCHED_STACK_END_CHECK is not set
+# CONFIG_DEBUG_TIMEKEEPING is not set
+# CONFIG_TIMER_STATS is not set
+
+#
+# Lock Debugging (spinlocks, mutexes, etc...)
+#
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_ATOMIC_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_LOCK_TORTURE_TEST is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_PI_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+
+#
+# RCU Debugging
+#
+# CONFIG_PROVE_RCU is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_TORTURE_TEST is not set
+# CONFIG_RCU_PERF_TEST is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_TRACE is not set
+# CONFIG_RCU_EQS_DEBUG is not set
+# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_NOTIFIER_ERROR_INJECTION is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+
+#
+# Runtime Testing
+#
+# CONFIG_TEST_LIST_SORT is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_RBTREE_TEST is not set
+# CONFIG_INTERVAL_TREE_TEST is not set
+# CONFIG_PERCPU_TEST is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_TEST_HEXDUMP is not set
+# CONFIG_TEST_STRING_HELPERS is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_TEST_PRINTF is not set
+# CONFIG_TEST_BITMAP is not set
+# CONFIG_TEST_UUID is not set
+# CONFIG_TEST_RHASHTABLE is not set
+# CONFIG_TEST_HASH is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_TEST_LKM is not set
+# CONFIG_TEST_USER_COPY is not set
+# CONFIG_TEST_BPF is not set
+# CONFIG_TEST_FIRMWARE is not set
+# CONFIG_TEST_UDELAY is not set
+# CONFIG_MEMTEST is not set
+# CONFIG_TEST_STATIC_KEYS is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set
+# CONFIG_UBSAN is not set
+CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
+CONFIG_STRICT_DEVMEM=y
+# CONFIG_IO_STRICT_DEVMEM is not set
+# CONFIG_ARM_PTDUMP is not set
+# CONFIG_ARM_UNWIND is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_LL is not set
+CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
+# CONFIG_DEBUG_UART_8250 is not set
+CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
+# CONFIG_PID_IN_CONTEXTIDR is not set
+# CONFIG_DEBUG_SET_MODULE_RONX is not set
+# CONFIG_CORESIGHT is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_PERSISTENT_KEYRINGS is not set
+# CONFIG_ENCRYPTED_KEYS is not set
+# CONFIG_KEY_DH_OPERATIONS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y
+CONFIG_HAVE_ARCH_HARDENED_USERCOPY=y
+# CONFIG_HARDENED_USERCOPY is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_RNG_DEFAULT=m
+CONFIG_CRYPTO_AKCIPHER2=y
+CONFIG_CRYPTO_KPP2=y
+# CONFIG_CRYPTO_RSA is not set
+# CONFIG_CRYPTO_DH is not set
+# CONFIG_CRYPTO_ECDH is not set
+CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_USER is not set
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_NULL2=y
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_MCRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+# CONFIG_CRYPTO_CHACHA20POLY1305 is not set
+CONFIG_CRYPTO_SEQIV=m
+CONFIG_CRYPTO_ECHAINIV=m
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+CONFIG_CRYPTO_CTR=m
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+# CONFIG_CRYPTO_KEYWRAP is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_CMAC is not set
+CONFIG_CRYPTO_HMAC=m
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_CRC32 is not set
+CONFIG_CRYPTO_CRCT10DIF=y
+CONFIG_CRYPTO_GHASH=m
+# CONFIG_CRYPTO_POLY1305 is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=y
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_SHA3 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_CHACHA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_LZO=y
+# CONFIG_CRYPTO_842 is not set
+# CONFIG_CRYPTO_LZ4 is not set
+# CONFIG_CRYPTO_LZ4HC is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_DRBG_MENU=m
+CONFIG_CRYPTO_DRBG_HMAC=y
+# CONFIG_CRYPTO_DRBG_HASH is not set
+# CONFIG_CRYPTO_DRBG_CTR is not set
+CONFIG_CRYPTO_DRBG=m
+CONFIG_CRYPTO_JITTERENTROPY=m
+# CONFIG_CRYPTO_USER_API_HASH is not set
+# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
+# CONFIG_CRYPTO_USER_API_RNG is not set
+# CONFIG_CRYPTO_USER_API_AEAD is not set
+# CONFIG_CRYPTO_HW is not set
+# CONFIG_ASYMMETRIC_KEY_TYPE is not set
+
+#
+# Certificates for signature checking
+#
+# CONFIG_ARM_CRYPTO is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_HAVE_ARCH_BITREVERSE=y
+CONFIG_RATIONAL=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_NET_UTILS=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IO=y
+CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=y
+# CONFIG_CRC8 is not set
+# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set
+# CONFIG_RANDOM32_SELFTEST is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_LZ4_DECOMPRESS=y
+CONFIG_XZ_DEC=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_BCJ=y
+# CONFIG_XZ_DEC_TEST is not set
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_LZ4=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_ASSOCIATIVE_ARRAY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_HAS_DMA=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
+# CONFIG_IRQ_POLL is not set
+CONFIG_LIBFDT=y
+CONFIG_OID_REGISTRY=y
+# CONFIG_SG_SPLIT is not set
+CONFIG_SG_POOL=y
+CONFIG_ARCH_HAS_SG_CHAIN=y
+CONFIG_SBITMAP=y
+# CONFIG_VIRTUALIZATION is not set
diff -urN linux-4.9.37/arch/arm/crypto/.gitignore linux-4.9.y/arch/arm/crypto/.gitignore
--- linux-4.9.37/arch/arm/crypto/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/arm/crypto/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,3 +0,0 @@
-aesbs-core.S
-sha256-core.S
-sha512-core.S
diff -urN linux-4.9.37/arch/arm/Kconfig linux-4.9.y/arch/arm/Kconfig
--- linux-4.9.37/arch/arm/Kconfig 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/arm/Kconfig 2021-06-07 13:01:32.000000000 +0300
@@ -330,7 +330,7 @@
depends on MMU
select ARM_HAS_SG_CHAIN
select ARM_PATCH_PHYS_VIRT
- select AUTO_ZRELADDR
+ #select AUTO_ZRELADDR
select CLKSRC_OF
select COMMON_CLK
select GENERIC_CLOCKEVENTS
@@ -747,6 +747,8 @@
source "arch/arm/mach-hisi/Kconfig"
+source "arch/arm/mach-goke/Kconfig"
+
source "arch/arm/mach-integrator/Kconfig"
source "arch/arm/mach-iop32x/Kconfig"
diff -urN linux-4.9.37/arch/arm/Kconfig.debug linux-4.9.y/arch/arm/Kconfig.debug
--- linux-4.9.37/arch/arm/Kconfig.debug 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/arm/Kconfig.debug 2021-06-07 13:01:32.000000000 +0300
@@ -287,6 +287,38 @@
Say Y here if you want kernel low-level debugging support
on HI3620 UART.
+ config DEBUG_GK7205V200_UART
+ bool "Goke GK7205V200 Debug UART"
+ depends on ARCH_GK7205V200
+ select DEBUG_UART_PL01X
+ help
+ Say Y here if you want kernel low-level debugging support
+ on GK7205V200 UART.
+
+ config DEBUG_GK7205V300_UART
+ bool "Goke GK7205V300 Debug UART"
+ depends on ARCH_GK7205V300
+ select DEBUG_UART_PL01X
+ help
+ Say Y here if you want kernel low-level debugging support
+ on GK7205V300 UART.
+
+ config DEBUG_GK7202V300_UART
+ bool "Goke GK7202V300 Debug UART"
+ depends on ARCH_GK7202V300
+ select DEBUG_UART_PL01X
+ help
+ Say Y here if you want kernel low-level debugging support
+ on GK7202V300 UART.
+
+ config DEBUG_GK7605V100_UART
+ bool "Goke GK7605V100 Debug UART"
+ depends on ARCH_GK7605V100
+ select DEBUG_UART_PL01X
+ help
+ Say Y here if you want kernel low-level debugging support
+ on GK7605V100 UART.
+
config DEBUG_HIGHBANK_UART
bool "Kernel low-level debugging messages via Highbank UART"
depends on ARCH_HIGHBANK
@@ -1530,6 +1562,9 @@
default 0xf991e000 if DEBUG_QCOM_UARTDM
default 0xfc00c000 if DEBUG_AT91_SAMA5D4_USART3
default 0xfcb00000 if DEBUG_HI3620_UART
+ default 0x12040000 if DEBUG_GK7205V200_UART
+ default 0x12040000 if DEBUG_GK7205V300_UART
+ default 0x12040000 if DEBUG_GK7202V300_UART
default 0xfd883000 if DEBUG_ALPINE_UART0
default 0xfe800000 if ARCH_IOP32X
default 0xff690000 if DEBUG_RK32_UART2
@@ -1619,6 +1654,9 @@
default 0xfe300000 if DEBUG_BCM_KONA_UART
default 0xfe800000 if ARCH_IOP32X
default 0xfeb00000 if DEBUG_HI3620_UART || DEBUG_HIX5HD2_UART
+ default 0xfe440000 if DEBUG_GK7205V200_UART
+ default 0xfe440000 if DEBUG_GK7205V300_UART
+ default 0xfe440000 if DEBUG_GK7202V300_UART
default 0xfeb24000 if DEBUG_RK3X_UART0
default 0xfeb26000 if DEBUG_RK3X_UART1
default 0xfeb30c00 if DEBUG_KEYSTONE_UART0
diff -urN linux-4.9.37/arch/arm/kernel/.gitignore linux-4.9.y/arch/arm/kernel/.gitignore
--- linux-4.9.37/arch/arm/kernel/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/arm/kernel/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-vmlinux.lds
diff -urN linux-4.9.37/arch/arm/kvm/handle_exit.c linux-4.9.y/arch/arm/kvm/handle_exit.c
--- linux-4.9.37/arch/arm/kvm/handle_exit.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/arm/kvm/handle_exit.c 2021-06-07 13:01:32.000000000 +0300
@@ -21,7 +21,7 @@
#include <asm/kvm_emulate.h>
#include <asm/kvm_coproc.h>
#include <asm/kvm_mmu.h>
-#include <asm/kvm_psci.h>
+#include <kvm/arm_psci.h>
#include <trace/events/kvm.h>
#include "trace.h"
diff -urN linux-4.9.37/arch/arm/mach-goke/include/mach/io.h linux-4.9.y/arch/arm/mach-goke/include/mach/io.h
--- linux-4.9.37/arch/arm/mach-goke/include/mach/io.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/arch/arm/mach-goke/include/mach/io.h 2021-06-07 13:01:32.000000000 +0300
@@ -0,0 +1,6 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+#endif
diff -urN linux-4.9.37/arch/arm/mach-goke/include/mach/platform.h linux-4.9.y/arch/arm/mach-goke/include/mach/platform.h
--- linux-4.9.37/arch/arm/mach-goke/include/mach/platform.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/arch/arm/mach-goke/include/mach/platform.h 2021-06-07 13:01:32.000000000 +0300
@@ -0,0 +1,6 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+#ifndef __GOKE_PLATFORM_H__
+#define __GOKE_PLATFORM_H__
+#endif /* End of __GOKE_PLATFORM_H__ */
diff -urN linux-4.9.37/arch/arm/mach-goke/Kconfig linux-4.9.y/arch/arm/mach-goke/Kconfig
--- linux-4.9.37/arch/arm/mach-goke/Kconfig 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/arch/arm/mach-goke/Kconfig 2021-06-07 13:01:32.000000000 +0300
@@ -0,0 +1,71 @@
+config ARCH_GOKE
+ bool "Goke SoC Support"
+ select ARM_AMBA
+ select ARM_GIC if ARCH_MULTI_V7
+ select ARM_VIC if ARCH_MULTI_V5
+ select ARM_TIMER_SP804
+ select POWER_RESET
+ select POWER_RESET_GOKE
+ select POWER_SUPPLY
+
+if ARCH_GOKE
+
+menu "Goke platform type"
+
+config ARCH_GK7205V200
+ bool "Goke GK7205V200 Cortex-A7 family"
+ depends on ARCH_MULTI_V7
+ select HAVE_ARM_ARCH_TIMER
+ select PINCTRL
+ select POWER_RESET_GOKE
+ help
+ Support for Goke GK7205V200 Soc family.
+
+config ARCH_GK7205V300
+ bool "Goke GK7205V300 Cortex-A7 family"
+ depends on ARCH_MULTI_V7
+ select HAVE_ARM_ARCH_TIMER
+ select PINCTRL
+ select POWER_RESET_GOKE
+ help
+ Support for Goke GK7205V300 Soc family.
+
+config ARCH_GK7202V300
+ bool "Goke GK7202V300 Cortex-A7 family"
+ depends on ARCH_MULTI_V7
+ select HAVE_ARM_ARCH_TIMER
+ select PINCTRL
+ select POWER_RESET_GOKE
+ help
+ Support for Goke GK7202V300 Soc family.
+
+config ARCH_GK7605V100
+ bool "Goke GK7605V100 Cortex-A7 family"
+ depends on ARCH_MULTI_V7
+ select HAVE_ARM_ARCH_TIMER
+ select PINCTRL
+ select POWER_RESET_GOKE
+ help
+ Support for Goke GK7605V100 Soc family.
+
+config GOKE_MC
+ bool "Goke mc platform solution"
+ default n
+ help
+ support for Goke mc platform solution
+
+config BSP_ZRELADDR
+ hex 'zreladdr'
+ default "0x40008000" if ARCH_GK7205V200 || ARCH_GK7205V300 || ARCH_GK7202V300 || ARCH_GK7605V100
+
+config BSP_PARAMS_PHYS
+ hex 'params_phys'
+ default "0x00000100"
+
+config BSP_INITRD_PHYS
+ hex 'initrd_phys'
+ default "0x00800000"
+
+endmenu
+
+endif
diff -urN linux-4.9.37/arch/arm/mach-goke/mach-common.h linux-4.9.y/arch/arm/mach-goke/mach-common.h
--- linux-4.9.37/arch/arm/mach-goke/mach-common.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/arch/arm/mach-goke/mach-common.h 2021-06-07 13:01:32.000000000 +0300
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+#ifndef __SMP_COMMON_H
+#define __SMP_COMMON_H
+
+#ifdef CONFIG_SMP
+void bsp_set_cpu(unsigned int cpu, bool enable);
+void __init bsp_smp_prepare_cpus(unsigned int max_cpus);
+int bsp_boot_secondary(unsigned int cpu, struct task_struct *idle);
+#endif /* CONFIG_SMP */
+#endif /* __SMP_COMMON_H */
diff -urN linux-4.9.37/arch/arm/mach-goke/mach-gk7202v300.c linux-4.9.y/arch/arm/mach-goke/mach-gk7202v300.c
--- linux-4.9.37/arch/arm/mach-goke/mach-gk7202v300.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/arch/arm/mach-goke/mach-gk7202v300.c 2021-06-07 13:01:32.000000000 +0300
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#include <linux/of_address.h>
+#include <asm/smp_scu.h>
+
+#include "mach-common.h"
+
+#ifdef CONFIG_SMP
+
+#define REG_CPU_SRST_CRG 0x78
+#define CPU1_SRST_REQ BIT(2)
+#define DBG1_SRST_REQ BIT(4)
+
+void bsp_set_cpu(unsigned int cpu, bool enable)
+{
+ struct device_node *np = NULL;
+ unsigned int regval;
+ void __iomem *crg_base;
+
+ np = of_find_compatible_node(NULL, NULL, "goke,gk7202v300-clock");
+ if (!np) {
+ pr_err("failed to find goke clock node\n");
+ return;
+ }
+
+ crg_base = of_iomap(np, 0);
+ if (!crg_base) {
+ pr_err("failed to map address\n");
+ return;
+ }
+
+ if (enable) {
+ /* clear the slave cpu reset */
+ regval = readl(crg_base + REG_CPU_SRST_CRG);
+ regval &= ~CPU1_SRST_REQ;
+ writel(regval, (crg_base + REG_CPU_SRST_CRG));
+ } else {
+ regval = readl(crg_base + REG_CPU_SRST_CRG);
+ regval |= (DBG1_SRST_REQ | CPU1_SRST_REQ);
+ writel(regval, (crg_base + REG_CPU_SRST_CRG));
+ }
+}
+
+static const struct smp_operations bsp_smp_ops __initconst = {
+ .smp_prepare_cpus = bsp_smp_prepare_cpus,
+ .smp_boot_secondary = bsp_boot_secondary,
+};
+
+CPU_METHOD_OF_DECLARE(gk7202v300_smp, "goke,gk7202v300-smp", &bsp_smp_ops);
+#endif /* CONFIG_SMP */
diff -urN linux-4.9.37/arch/arm/mach-goke/mach-gk7205v200.c linux-4.9.y/arch/arm/mach-goke/mach-gk7205v200.c
--- linux-4.9.37/arch/arm/mach-goke/mach-gk7205v200.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/arch/arm/mach-goke/mach-gk7205v200.c 2021-06-07 13:01:32.000000000 +0300
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#include <linux/of_address.h>
+#include <asm/smp_scu.h>
+
+#include "mach-common.h"
+
+#ifdef CONFIG_SMP
+
+#define REG_CPU_SRST_CRG 0x78
+#define CPU1_SRST_REQ BIT(2)
+#define DBG1_SRST_REQ BIT(4)
+
+void bsp_set_cpu(unsigned int cpu, bool enable)
+{
+ struct device_node *np = NULL;
+ unsigned int regval;
+ void __iomem *crg_base;
+
+ np = of_find_compatible_node(NULL, NULL, "goke,gk7205v200-clock");
+ if (!np) {
+ pr_err("failed to find goke clock node\n");
+ return;
+ }
+
+ crg_base = of_iomap(np, 0);
+ if (!crg_base) {
+ pr_err("failed to map address\n");
+ return;
+ }
+
+ if (enable) {
+ /* clear the slave cpu reset */
+ regval = readl(crg_base + REG_CPU_SRST_CRG);
+ regval &= ~CPU1_SRST_REQ;
+ writel(regval, (crg_base + REG_CPU_SRST_CRG));
+ } else {
+ regval = readl(crg_base + REG_CPU_SRST_CRG);
+ regval |= (DBG1_SRST_REQ | CPU1_SRST_REQ);
+ writel(regval, (crg_base + REG_CPU_SRST_CRG));
+ }
+}
+
+static const struct smp_operations bsp_smp_ops __initconst = {
+ .smp_prepare_cpus = bsp_smp_prepare_cpus,
+ .smp_boot_secondary = bsp_boot_secondary,
+};
+
+CPU_METHOD_OF_DECLARE(gk7205v200_smp, "goke,gk7205v200-smp", &bsp_smp_ops);
+#endif /* CONFIG_SMP */
diff -urN linux-4.9.37/arch/arm/mach-goke/mach-gk7205v300.c linux-4.9.y/arch/arm/mach-goke/mach-gk7205v300.c
--- linux-4.9.37/arch/arm/mach-goke/mach-gk7205v300.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/arch/arm/mach-goke/mach-gk7205v300.c 2021-06-07 13:01:32.000000000 +0300
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#include <linux/of_address.h>
+#include <asm/smp_scu.h>
+
+#include "mach-common.h"
+
+#ifdef CONFIG_SMP
+
+#define REG_CPU_SRST_CRG 0x78
+#define CPU1_SRST_REQ BIT(2)
+#define DBG1_SRST_REQ BIT(4)
+
+void bsp_set_cpu(unsigned int cpu, bool enable)
+{
+ struct device_node *np = NULL;
+ unsigned int regval;
+ void __iomem *crg_base;
+
+ np = of_find_compatible_node(NULL, NULL, "goke,gk7205v300-clock");
+ if (!np) {
+ pr_err("failed to find goke clock node\n");
+ return;
+ }
+
+ crg_base = of_iomap(np, 0);
+ if (!crg_base) {
+ pr_err("failed to map address\n");
+ return;
+ }
+
+ if (enable) {
+ /* clear the slave cpu reset */
+ regval = readl(crg_base + REG_CPU_SRST_CRG);
+ regval &= ~CPU1_SRST_REQ;
+ writel(regval, (crg_base + REG_CPU_SRST_CRG));
+ } else {
+ regval = readl(crg_base + REG_CPU_SRST_CRG);
+ regval |= (DBG1_SRST_REQ | CPU1_SRST_REQ);
+ writel(regval, (crg_base + REG_CPU_SRST_CRG));
+ }
+}
+
+static const struct smp_operations bsp_smp_ops __initconst = {
+ .smp_prepare_cpus = bsp_smp_prepare_cpus,
+ .smp_boot_secondary = bsp_boot_secondary,
+};
+
+CPU_METHOD_OF_DECLARE(gk7205v300_smp, "goke,gk7205v300-smp", &bsp_smp_ops);
+#endif /* CONFIG_SMP */
diff -urN linux-4.9.37/arch/arm/mach-goke/mach-gk7605v100.c linux-4.9.y/arch/arm/mach-goke/mach-gk7605v100.c
--- linux-4.9.37/arch/arm/mach-goke/mach-gk7605v100.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/arch/arm/mach-goke/mach-gk7605v100.c 2021-06-07 13:01:32.000000000 +0300
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#include <linux/of_address.h>
+#include <asm/smp_scu.h>
+
+#include "mach-common.h"
+
+#ifdef CONFIG_SMP
+
+#define REG_CPU_SRST_CRG 0x78
+#define CPU1_SRST_REQ BIT(2)
+#define DBG1_SRST_REQ BIT(4)
+
+void bsp_set_cpu(unsigned int cpu, bool enable)
+{
+ struct device_node *np = NULL;
+ unsigned int regval;
+ void __iomem *crg_base;
+
+ np = of_find_compatible_node(NULL, NULL, "goke,gk7605v100-clock");
+ if (!np) {
+ pr_err("failed to find goke clock node\n");
+ return;
+ }
+
+ crg_base = of_iomap(np, 0);
+ if (!crg_base) {
+ pr_err("failed to map address\n");
+ return;
+ }
+
+ if (enable) {
+ /* clear the slave cpu reset */
+ regval = readl(crg_base + REG_CPU_SRST_CRG);
+ regval &= ~CPU1_SRST_REQ;
+ writel(regval, (crg_base + REG_CPU_SRST_CRG));
+ } else {
+ regval = readl(crg_base + REG_CPU_SRST_CRG);
+ regval |= (DBG1_SRST_REQ | CPU1_SRST_REQ);
+ writel(regval, (crg_base + REG_CPU_SRST_CRG));
+ }
+}
+
+static const struct smp_operations bsp_smp_ops __initconst = {
+ .smp_prepare_cpus = bsp_smp_prepare_cpus,
+ .smp_boot_secondary = bsp_boot_secondary,
+};
+
+CPU_METHOD_OF_DECLARE(gk7605v100_smp, "goke,gk7605v100-smp", &bsp_smp_ops);
+#endif /* CONFIG_SMP */
diff -urN linux-4.9.37/arch/arm/mach-goke/Makefile linux-4.9.y/arch/arm/mach-goke/Makefile
--- linux-4.9.37/arch/arm/mach-goke/Makefile 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/arch/arm/mach-goke/Makefile 2021-06-07 13:01:32.000000000 +0300
@@ -0,0 +1,8 @@
+#
+# Makefile for Goke processors family
+#
+
+obj-$(CONFIG_ARCH_GK7205V200) += mach-gk7205v200.o
+obj-$(CONFIG_ARCH_GK7205V300) += mach-gk7205v300.o
+obj-$(CONFIG_ARCH_GK7202V300) += mach-gk7202v300.o
+obj-$(CONFIG_ARCH_GK7605V100) += mach-gk7605v100.o
diff -urN linux-4.9.37/arch/arm/mach-goke/Makefile.boot linux-4.9.y/arch/arm/mach-goke/Makefile.boot
--- linux-4.9.37/arch/arm/mach-goke/Makefile.boot 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/arch/arm/mach-goke/Makefile.boot 2021-06-07 13:01:32.000000000 +0300
@@ -0,0 +1,3 @@
+zreladdr-$(CONFIG_ARCH_GOKE) := $(CONFIG_BSP_ZRELADDR)
+params_phys-$(CONFIG_ARCH_GOKE) := $(CONFIG_BSP_PARAMS_PHYS)
+initrd_phys-$(CONFIG_ARCH_GOKE) := $(CONFIG_BSP_INITRD_PHYS)
diff -urN linux-4.9.37/arch/arm/Makefile linux-4.9.y/arch/arm/Makefile
--- linux-4.9.37/arch/arm/Makefile 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/arm/Makefile 2021-06-07 13:01:32.000000000 +0300
@@ -170,6 +170,7 @@
machine-$(CONFIG_ARCH_GEMINI) += gemini
machine-$(CONFIG_ARCH_HIGHBANK) += highbank
machine-$(CONFIG_ARCH_HISI) += hisi
+machine-$(CONFIG_ARCH_GOKE) += goke
machine-$(CONFIG_ARCH_INTEGRATOR) += integrator
machine-$(CONFIG_ARCH_IOP13XX) += iop13xx
machine-$(CONFIG_ARCH_IOP32X) += iop32x
@@ -268,6 +269,10 @@
endif
endif
+ifeq ($(CONFIG_ARCH_GOKE),y)
+KBUILD_CPPFLAGS += $(patsubst %,-I%include,$(machdirs) $(platdirs))
+endif
+
export TEXT_OFFSET GZFLAGS MMUEXT
# Do we have FASTFPE?
diff -urN linux-4.9.37/arch/arm/mm/dma-mapping.c linux-4.9.y/arch/arm/mm/dma-mapping.c
--- linux-4.9.37/arch/arm/mm/dma-mapping.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/arm/mm/dma-mapping.c 2021-06-07 13:01:32.000000000 +0300
@@ -275,7 +275,7 @@
return mask;
}
-static void __dma_clear_buffer(struct page *page, size_t size, int coherent_flag)
+void __dma_clear_buffer(struct page *page, size_t size, int coherent_flag)
{
/*
* Ensure that the allocated pages are zeroed, and that any data
@@ -304,6 +304,7 @@
}
}
}
+EXPORT_SYMBOL(__dma_clear_buffer);
/*
* Allocate a DMA buffer for 'dev' of size 'size' using the
@@ -528,6 +529,12 @@
flush_tlb_kernel_range(start, end);
}
+void bsp_flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+ flush_tlb_kernel_range(start, end);
+}
+EXPORT_SYMBOL(bsp_flush_tlb_kernel_range);
+
static void *__alloc_remap_buffer(struct device *dev, size_t size, gfp_t gfp,
pgprot_t prot, struct page **ret_page,
const void *caller, bool want_vaddr)
@@ -2397,3 +2404,10 @@
{
arm_teardown_iommu_dma_ops(dev);
}
+
+void bsp_dmac_map_area(const void *kaddr, size_t size,
+ enum dma_data_direction dir)
+{
+ dmac_map_area(kaddr, size, dir);
+}
+EXPORT_SYMBOL(bsp_dmac_map_area);
diff -urN linux-4.9.37/arch/arm/mm/init.c linux-4.9.y/arch/arm/mm/init.c
--- linux-4.9.37/arch/arm/mm/init.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/arm/mm/init.c 2021-06-07 13:01:32.000000000 +0300
@@ -268,6 +268,12 @@
/* reserve any platform specific memblock areas */
if (mdesc->reserve)
mdesc->reserve();
+#if defined CONFIG_CMA && defined CONFIG_ARCH_GOKE
+ else {
+ extern int goke_declare_heap_memory(void);
+ goke_declare_heap_memory();
+ }
+#endif
early_init_fdt_reserve_self();
early_init_fdt_scan_reserved_mem();
diff -urN linux-4.9.37/arch/arm/vdso/.gitignore linux-4.9.y/arch/arm/vdso/.gitignore
--- linux-4.9.37/arch/arm/vdso/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/arm/vdso/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,3 +0,0 @@
-vdso.lds
-vdso.so.raw
-vdsomunge
diff -urN linux-4.9.37/arch/arm/vdso/vgettimeofday.c linux-4.9.y/arch/arm/vdso/vgettimeofday.c
--- linux-4.9.37/arch/arm/vdso/vgettimeofday.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/arm/vdso/vgettimeofday.c 2021-06-07 13:01:32.000000000 +0300
@@ -115,7 +115,7 @@
return 0;
}
-#ifdef CONFIG_ARM_ARCH_TIMER
+#if defined (CONFIG_ARM_ARCH_TIMER) && defined(CONFIG_ARM_ARCH_TIMER_VCT_ACCESS)
static notrace u64 get_ns(struct vdso_data *vdata)
{
diff -urN linux-4.9.37/arch/arm64/boot/dts/.gitignore linux-4.9.y/arch/arm64/boot/dts/.gitignore
--- linux-4.9.37/arch/arm64/boot/dts/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/arm64/boot/dts/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-*.dtb
diff -urN linux-4.9.37/arch/arm64/boot/.gitignore linux-4.9.y/arch/arm64/boot/.gitignore
--- linux-4.9.37/arch/arm64/boot/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/arm64/boot/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,2 +0,0 @@
-Image
-Image.gz
diff -urN linux-4.9.37/arch/arm64/kernel/.gitignore linux-4.9.y/arch/arm64/kernel/.gitignore
--- linux-4.9.37/arch/arm64/kernel/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/arm64/kernel/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-vmlinux.lds
diff -urN linux-4.9.37/arch/arm64/kernel/vdso/.gitignore linux-4.9.y/arch/arm64/kernel/vdso/.gitignore
--- linux-4.9.37/arch/arm64/kernel/vdso/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/arm64/kernel/vdso/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,2 +0,0 @@
-vdso.lds
-vdso-offsets.h
diff -urN linux-4.9.37/arch/avr32/boot/images/.gitignore linux-4.9.y/arch/avr32/boot/images/.gitignore
--- linux-4.9.37/arch/avr32/boot/images/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/avr32/boot/images/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,4 +0,0 @@
-uImage
-uImage.srec
-vmlinux.cso
-sfdwarf.log
diff -urN linux-4.9.37/arch/avr32/kernel/.gitignore linux-4.9.y/arch/avr32/kernel/.gitignore
--- linux-4.9.37/arch/avr32/kernel/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/avr32/kernel/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-vmlinux.lds
diff -urN linux-4.9.37/arch/blackfin/boot/.gitignore linux-4.9.y/arch/blackfin/boot/.gitignore
--- linux-4.9.37/arch/blackfin/boot/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/blackfin/boot/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,3 +0,0 @@
-vmImage*
-vmlinux*
-uImage*
diff -urN linux-4.9.37/arch/blackfin/kernel/.gitignore linux-4.9.y/arch/blackfin/kernel/.gitignore
--- linux-4.9.37/arch/blackfin/kernel/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/blackfin/kernel/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-vmlinux.lds
diff -urN linux-4.9.37/arch/cris/boot/.gitignore linux-4.9.y/arch/cris/boot/.gitignore
--- linux-4.9.37/arch/cris/boot/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/cris/boot/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,2 +0,0 @@
-Image
-zImage
diff -urN linux-4.9.37/arch/.gitignore linux-4.9.y/arch/.gitignore
--- linux-4.9.37/arch/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,2 +0,0 @@
-i386
-x86_64
diff -urN linux-4.9.37/arch/ia64/kernel/.gitignore linux-4.9.y/arch/ia64/kernel/.gitignore
--- linux-4.9.37/arch/ia64/kernel/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/ia64/kernel/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,2 +0,0 @@
-gate.lds
-vmlinux.lds
diff -urN linux-4.9.37/arch/m32r/kernel/.gitignore linux-4.9.y/arch/m32r/kernel/.gitignore
--- linux-4.9.37/arch/m32r/kernel/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/m32r/kernel/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-vmlinux.lds
diff -urN linux-4.9.37/arch/m68k/kernel/.gitignore linux-4.9.y/arch/m68k/kernel/.gitignore
--- linux-4.9.37/arch/m68k/kernel/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/m68k/kernel/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-vmlinux.lds
diff -urN linux-4.9.37/arch/metag/boot/.gitignore linux-4.9.y/arch/metag/boot/.gitignore
--- linux-4.9.37/arch/metag/boot/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/metag/boot/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,4 +0,0 @@
-vmlinux*
-uImage*
-ramdisk.*
-*.dtb*
diff -urN linux-4.9.37/arch/metag/kernel/.gitignore linux-4.9.y/arch/metag/kernel/.gitignore
--- linux-4.9.37/arch/metag/kernel/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/metag/kernel/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-vmlinux.lds
diff -urN linux-4.9.37/arch/microblaze/boot/.gitignore linux-4.9.y/arch/microblaze/boot/.gitignore
--- linux-4.9.37/arch/microblaze/boot/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/microblaze/boot/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,3 +0,0 @@
-*.dtb
-linux.bin*
-simpleImage.*
diff -urN linux-4.9.37/arch/microblaze/kernel/.gitignore linux-4.9.y/arch/microblaze/kernel/.gitignore
--- linux-4.9.37/arch/microblaze/kernel/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/microblaze/kernel/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-vmlinux.lds
diff -urN linux-4.9.37/arch/mips/boot/.gitignore linux-4.9.y/arch/mips/boot/.gitignore
--- linux-4.9.37/arch/mips/boot/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/mips/boot/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,8 +0,0 @@
-mkboot
-elf2ecoff
-vmlinux.*
-zImage
-zImage.tmp
-calc_vmlinuz_load_addr
-uImage
-*.dtb
diff -urN linux-4.9.37/arch/mips/boot/tools/.gitignore linux-4.9.y/arch/mips/boot/tools/.gitignore
--- linux-4.9.37/arch/mips/boot/tools/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/mips/boot/tools/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-relocs
diff -urN linux-4.9.37/arch/mips/kernel/.gitignore linux-4.9.y/arch/mips/kernel/.gitignore
--- linux-4.9.37/arch/mips/kernel/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/mips/kernel/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-vmlinux.lds
diff -urN linux-4.9.37/arch/mips/vdso/.gitignore linux-4.9.y/arch/mips/vdso/.gitignore
--- linux-4.9.37/arch/mips/vdso/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/mips/vdso/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,4 +0,0 @@
-*.so*
-vdso-*image.c
-genvdso
-vdso*.lds
diff -urN linux-4.9.37/arch/mn10300/boot/.gitignore linux-4.9.y/arch/mn10300/boot/.gitignore
--- linux-4.9.37/arch/mn10300/boot/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/mn10300/boot/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-zImage
diff -urN linux-4.9.37/arch/parisc/kernel/.gitignore linux-4.9.y/arch/parisc/kernel/.gitignore
--- linux-4.9.37/arch/parisc/kernel/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/parisc/kernel/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-vmlinux.lds
diff -urN linux-4.9.37/arch/powerpc/boot/.gitignore linux-4.9.y/arch/powerpc/boot/.gitignore
--- linux-4.9.37/arch/powerpc/boot/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/powerpc/boot/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,44 +0,0 @@
-addnote
-empty.c
-hack-coff
-inffast.c
-inffast.h
-inffixed.h
-inflate.c
-inflate.h
-inftrees.c
-inftrees.h
-infutil.c
-infutil.h
-kernel-vmlinux.strip.c
-kernel-vmlinux.strip.gz
-mktree
-uImage
-cuImage.*
-dtbImage.*
-*.dtb
-treeImage.*
-zImage
-zImage.initrd
-zImage.bin.*
-zImage.chrp
-zImage.coff
-zImage.epapr
-zImage.holly
-zImage.*lds
-zImage.miboot
-zImage.pmac
-zImage.pseries
-zconf.h
-zlib.h
-zutil.h
-fdt.c
-fdt.h
-fdt_ro.c
-fdt_rw.c
-fdt_strerror.c
-fdt_sw.c
-fdt_wip.c
-libfdt.h
-libfdt_internal.h
-
diff -urN linux-4.9.37/arch/powerpc/kernel/.gitignore linux-4.9.y/arch/powerpc/kernel/.gitignore
--- linux-4.9.37/arch/powerpc/kernel/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/powerpc/kernel/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-vmlinux.lds
diff -urN linux-4.9.37/arch/powerpc/kernel/vdso32/.gitignore linux-4.9.y/arch/powerpc/kernel/vdso32/.gitignore
--- linux-4.9.37/arch/powerpc/kernel/vdso32/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/powerpc/kernel/vdso32/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,2 +0,0 @@
-vdso32.lds
-vdso32.so.dbg
diff -urN linux-4.9.37/arch/powerpc/kernel/vdso64/.gitignore linux-4.9.y/arch/powerpc/kernel/vdso64/.gitignore
--- linux-4.9.37/arch/powerpc/kernel/vdso64/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/powerpc/kernel/vdso64/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,2 +0,0 @@
-vdso64.lds
-vdso64.so.dbg
diff -urN linux-4.9.37/arch/powerpc/platforms/cell/spufs/.gitignore linux-4.9.y/arch/powerpc/platforms/cell/spufs/.gitignore
--- linux-4.9.37/arch/powerpc/platforms/cell/spufs/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/powerpc/platforms/cell/spufs/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,2 +0,0 @@
-spu_save_dump.h
-spu_restore_dump.h
diff -urN linux-4.9.37/arch/s390/boot/compressed/.gitignore linux-4.9.y/arch/s390/boot/compressed/.gitignore
--- linux-4.9.37/arch/s390/boot/compressed/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/s390/boot/compressed/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,3 +0,0 @@
-sizes.h
-vmlinux
-vmlinux.lds
diff -urN linux-4.9.37/arch/s390/boot/.gitignore linux-4.9.y/arch/s390/boot/.gitignore
--- linux-4.9.37/arch/s390/boot/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/s390/boot/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,2 +0,0 @@
-image
-bzImage
diff -urN linux-4.9.37/arch/s390/kernel/.gitignore linux-4.9.y/arch/s390/kernel/.gitignore
--- linux-4.9.37/arch/s390/kernel/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/s390/kernel/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-vmlinux.lds
diff -urN linux-4.9.37/arch/s390/kernel/vdso32/.gitignore linux-4.9.y/arch/s390/kernel/vdso32/.gitignore
--- linux-4.9.37/arch/s390/kernel/vdso32/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/s390/kernel/vdso32/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-vdso32.lds
diff -urN linux-4.9.37/arch/s390/kernel/vdso64/.gitignore linux-4.9.y/arch/s390/kernel/vdso64/.gitignore
--- linux-4.9.37/arch/s390/kernel/vdso64/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/s390/kernel/vdso64/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-vdso64.lds
diff -urN linux-4.9.37/arch/s390/tools/.gitignore linux-4.9.y/arch/s390/tools/.gitignore
--- linux-4.9.37/arch/s390/tools/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/s390/tools/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-gen_facilities
diff -urN linux-4.9.37/arch/sh/boot/compressed/.gitignore linux-4.9.y/arch/sh/boot/compressed/.gitignore
--- linux-4.9.37/arch/sh/boot/compressed/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/sh/boot/compressed/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-vmlinux.bin.*
diff -urN linux-4.9.37/arch/sh/boot/compressed/vmlinux.scr linux-4.9.y/arch/sh/boot/compressed/vmlinux.scr
--- linux-4.9.37/arch/sh/boot/compressed/vmlinux.scr 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/sh/boot/compressed/vmlinux.scr 1970-01-01 03:00:00.000000000 +0300
@@ -1,10 +0,0 @@
-SECTIONS
-{
- .rodata..compressed : {
- input_len = .;
- LONG(input_data_end - input_data) input_data = .;
- *(.data)
- output_len = . - 4;
- input_data_end = .;
- }
-}
diff -urN linux-4.9.37/arch/sh/boot/.gitignore linux-4.9.y/arch/sh/boot/.gitignore
--- linux-4.9.37/arch/sh/boot/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/sh/boot/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,3 +0,0 @@
-zImage
-vmlinux*
-uImage*
diff -urN linux-4.9.37/arch/sh/boot/romimage/vmlinux.scr linux-4.9.y/arch/sh/boot/romimage/vmlinux.scr
--- linux-4.9.37/arch/sh/boot/romimage/vmlinux.scr 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/sh/boot/romimage/vmlinux.scr 1970-01-01 03:00:00.000000000 +0300
@@ -1,8 +0,0 @@
-SECTIONS
-{
- .text : {
- zero_page_pos = .;
- *(.data)
- end_data = .;
- }
-}
diff -urN linux-4.9.37/arch/sh/kernel/.gitignore linux-4.9.y/arch/sh/kernel/.gitignore
--- linux-4.9.37/arch/sh/kernel/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/sh/kernel/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-vmlinux.lds
diff -urN linux-4.9.37/arch/sh/kernel/vsyscall/.gitignore linux-4.9.y/arch/sh/kernel/vsyscall/.gitignore
--- linux-4.9.37/arch/sh/kernel/vsyscall/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/sh/kernel/vsyscall/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-vsyscall.lds
diff -urN linux-4.9.37/arch/sparc/boot/.gitignore linux-4.9.y/arch/sparc/boot/.gitignore
--- linux-4.9.37/arch/sparc/boot/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/sparc/boot/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,8 +0,0 @@
-btfix.S
-btfixupprep
-image
-zImage
-tftpboot.img
-vmlinux.aout
-piggyback
-
diff -urN linux-4.9.37/arch/sparc/kernel/.gitignore linux-4.9.y/arch/sparc/kernel/.gitignore
--- linux-4.9.37/arch/sparc/kernel/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/sparc/kernel/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-vmlinux.lds
diff -urN linux-4.9.37/arch/um/.gitignore linux-4.9.y/arch/um/.gitignore
--- linux-4.9.37/arch/um/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/um/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,3 +0,0 @@
-kernel/config.c
-kernel/config.tmp
-kernel/vmlinux.lds
diff -urN linux-4.9.37/arch/unicore32/.gitignore linux-4.9.y/arch/unicore32/.gitignore
--- linux-4.9.37/arch/unicore32/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/unicore32/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,21 +0,0 @@
-#
-# Generated include files
-#
-include/generated
-#
-# Generated ld script file
-#
-kernel/vmlinux.lds
-#
-# Generated images in boot
-#
-boot/Image
-boot/zImage
-boot/uImage
-#
-# Generated files in boot/compressed
-#
-boot/compressed/piggy.S
-boot/compressed/piggy.gzip
-boot/compressed/vmlinux
-boot/compressed/vmlinux.lds
diff -urN linux-4.9.37/arch/x86/boot/compressed/.gitignore linux-4.9.y/arch/x86/boot/compressed/.gitignore
--- linux-4.9.37/arch/x86/boot/compressed/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/x86/boot/compressed/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,6 +0,0 @@
-relocs
-vmlinux.bin.all
-vmlinux.relocs
-vmlinux.lds
-mkpiggy
-piggy.S
diff -urN linux-4.9.37/arch/x86/boot/.gitignore linux-4.9.y/arch/x86/boot/.gitignore
--- linux-4.9.37/arch/x86/boot/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/x86/boot/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,9 +0,0 @@
-bootsect
-bzImage
-cpustr.h
-mkcpustr
-voffset.h
-zoffset.h
-setup
-setup.bin
-setup.elf
diff -urN linux-4.9.37/arch/x86/boot/tools/.gitignore linux-4.9.y/arch/x86/boot/tools/.gitignore
--- linux-4.9.37/arch/x86/boot/tools/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/x86/boot/tools/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-build
diff -urN linux-4.9.37/arch/x86/entry/vdso/.gitignore linux-4.9.y/arch/x86/entry/vdso/.gitignore
--- linux-4.9.37/arch/x86/entry/vdso/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/x86/entry/vdso/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,7 +0,0 @@
-vdso.lds
-vdsox32.lds
-vdso32-syscall-syms.lds
-vdso32-sysenter-syms.lds
-vdso32-int80-syms.lds
-vdso-image-*.c
-vdso2c
diff -urN linux-4.9.37/arch/x86/entry/vdso/vdso32/.gitignore linux-4.9.y/arch/x86/entry/vdso/vdso32/.gitignore
--- linux-4.9.37/arch/x86/entry/vdso/vdso32/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/x86/entry/vdso/vdso32/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-vdso32.lds
diff -urN linux-4.9.37/arch/x86/.gitignore linux-4.9.y/arch/x86/.gitignore
--- linux-4.9.37/arch/x86/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/x86/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,6 +0,0 @@
-boot/compressed/vmlinux
-tools/test_get_len
-tools/insn_sanity
-purgatory/kexec-purgatory.c
-purgatory/purgatory.ro
-
diff -urN linux-4.9.37/arch/x86/kernel/cpu/.gitignore linux-4.9.y/arch/x86/kernel/cpu/.gitignore
--- linux-4.9.37/arch/x86/kernel/cpu/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/x86/kernel/cpu/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-capflags.c
diff -urN linux-4.9.37/arch/x86/kernel/.gitignore linux-4.9.y/arch/x86/kernel/.gitignore
--- linux-4.9.37/arch/x86/kernel/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/x86/kernel/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,3 +0,0 @@
-vsyscall.lds
-vsyscall_32.lds
-vmlinux.lds
diff -urN linux-4.9.37/arch/x86/lib/.gitignore linux-4.9.y/arch/x86/lib/.gitignore
--- linux-4.9.37/arch/x86/lib/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/x86/lib/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-inat-tables.c
diff -urN linux-4.9.37/arch/x86/realmode/rm/.gitignore linux-4.9.y/arch/x86/realmode/rm/.gitignore
--- linux-4.9.37/arch/x86/realmode/rm/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/x86/realmode/rm/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,3 +0,0 @@
-pasyms.h
-realmode.lds
-realmode.relocs
diff -urN linux-4.9.37/arch/x86/tools/.gitignore linux-4.9.y/arch/x86/tools/.gitignore
--- linux-4.9.37/arch/x86/tools/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/x86/tools/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-relocs
diff -urN linux-4.9.37/arch/x86/um/vdso/.gitignore linux-4.9.y/arch/x86/um/vdso/.gitignore
--- linux-4.9.37/arch/x86/um/vdso/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/x86/um/vdso/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,2 +0,0 @@
-vdso-syms.lds
-vdso.lds
diff -urN linux-4.9.37/arch/xtensa/boot/boot-elf/.gitignore linux-4.9.y/arch/xtensa/boot/boot-elf/.gitignore
--- linux-4.9.37/arch/xtensa/boot/boot-elf/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/xtensa/boot/boot-elf/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-boot.lds
diff -urN linux-4.9.37/arch/xtensa/boot/.gitignore linux-4.9.y/arch/xtensa/boot/.gitignore
--- linux-4.9.37/arch/xtensa/boot/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/xtensa/boot/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,3 +0,0 @@
-uImage
-zImage.redboot
-*.dtb
diff -urN linux-4.9.37/arch/xtensa/boot/lib/.gitignore linux-4.9.y/arch/xtensa/boot/lib/.gitignore
--- linux-4.9.37/arch/xtensa/boot/lib/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/xtensa/boot/lib/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,3 +0,0 @@
-inffast.c
-inflate.c
-inftrees.c
diff -urN linux-4.9.37/arch/xtensa/kernel/.gitignore linux-4.9.y/arch/xtensa/kernel/.gitignore
--- linux-4.9.37/arch/xtensa/kernel/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/arch/xtensa/kernel/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-vmlinux.lds
diff -urN linux-4.9.37/certs/.gitignore linux-4.9.y/certs/.gitignore
--- linux-4.9.37/certs/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/certs/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,4 +0,0 @@
-#
-# Generated files
-#
-x509_certificate_list
diff -urN linux-4.9.37/crypto/asymmetric_keys/.gitignore linux-4.9.y/crypto/asymmetric_keys/.gitignore
--- linux-4.9.37/crypto/asymmetric_keys/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/crypto/asymmetric_keys/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-*-asn1.[ch]
diff -urN linux-4.9.37/crypto/.gitignore linux-4.9.y/crypto/.gitignore
--- linux-4.9.37/crypto/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/crypto/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-*-asn1.[ch]
diff -urN linux-4.9.37/Documentation/arm/SH-Mobile/.gitignore linux-4.9.y/Documentation/arm/SH-Mobile/.gitignore
--- linux-4.9.37/Documentation/arm/SH-Mobile/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/Documentation/arm/SH-Mobile/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-vrl4
diff -urN linux-4.9.37/Documentation/DocBook/.gitignore linux-4.9.y/Documentation/DocBook/.gitignore
--- linux-4.9.37/Documentation/DocBook/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/Documentation/DocBook/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,17 +0,0 @@
-*.xml
-*.ps
-*.pdf
-*.html
-*.9.gz
-*.9
-*.aux
-*.dvi
-*.log
-*.out
-*.png
-*.gif
-*.svg
-*.proc
-*.db
-media-indices.tmpl
-media-entities.tmpl
diff -urN linux-4.9.37/Documentation/.gitignore linux-4.9.y/Documentation/.gitignore
--- linux-4.9.37/Documentation/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/Documentation/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,2 +0,0 @@
-output
-*.pyc
diff -urN linux-4.9.37/Documentation/vm/.gitignore linux-4.9.y/Documentation/vm/.gitignore
--- linux-4.9.37/Documentation/vm/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/Documentation/vm/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,2 +0,0 @@
-page-types
-slabinfo
diff -urN linux-4.9.37/drivers/atm/.gitignore linux-4.9.y/drivers/atm/.gitignore
--- linux-4.9.37/drivers/atm/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/atm/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,5 +0,0 @@
-# Ignore generated files
-fore200e_mkfirm
-fore200e_pca_fw.c
-pca200e.bin
-pca200e_ecd.bin2
diff -urN linux-4.9.37/drivers/base/dma-contiguous.c linux-4.9.y/drivers/base/dma-contiguous.c
--- linux-4.9.37/drivers/base/dma-contiguous.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/base/dma-contiguous.c 2021-06-07 13:01:33.000000000 +0300
@@ -195,6 +195,7 @@
return cma_alloc(dev_get_cma_area(dev), count, align);
}
+EXPORT_SYMBOL(dma_alloc_from_contiguous);
/**
* dma_release_from_contiguous() - release allocated pages
@@ -211,6 +212,7 @@
{
return cma_release(dev_get_cma_area(dev), pages, count);
}
+EXPORT_SYMBOL(dma_release_from_contiguous);
/*
* Support for reserved memory regions defined in device tree
diff -urN linux-4.9.37/drivers/char/random.c linux-4.9.y/drivers/char/random.c
--- linux-4.9.37/drivers/char/random.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/char/random.c 2021-06-07 13:01:33.000000000 +0300
@@ -812,7 +812,7 @@
if (crng_init_cnt >= CRNG_INIT_CNT_THRESH) {
crng_init = 1;
wake_up_interruptible(&crng_init_wait);
- pr_notice("random: fast init done\n");
+ printk_once("random: fast init done\n");
}
spin_unlock_irqrestore(&primary_crng.lock, flags);
return 1;
@@ -850,7 +850,7 @@
crng_init = 2;
process_random_ready_list();
wake_up_interruptible(&crng_init_wait);
- pr_notice("random: crng init done\n");
+ printk_once("random: crng init done\n");
}
spin_unlock_irqrestore(&primary_crng.lock, flags);
}
@@ -1744,7 +1744,7 @@
if (!crng_ready() && maxwarn > 0) {
maxwarn--;
- printk(KERN_NOTICE "random: %s: uninitialized urandom read "
+ printk_once(KERN_NOTICE "random: %s: uninitialized urandom read "
"(%zd bytes read)\n",
current->comm, nbytes);
spin_lock_irqsave(&primary_crng.lock, flags);
diff -urN linux-4.9.37/drivers/clk/goke/clk.c linux-4.9.y/drivers/clk/goke/clk.c
--- linux-4.9.37/drivers/clk/goke/clk.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/clk/goke/clk.c 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#include <linux/kernel.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+
+#include "clk.h"
+
+static DEFINE_SPINLOCK(gk_clk_lock);
+
+struct gk_clock_data *gk_clk_init(struct device_node *np,
+ int nr_clks)
+{
+ struct gk_clock_data *clk_data;
+ struct clk **clk_table;
+ void __iomem *base;
+
+ base = of_iomap(np, 0);
+ if (!base) {
+ pr_err("%s: failed to map clock registers\n", __func__);
+ goto err;
+ }
+
+ clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+ if (!clk_data) {
+ pr_err("%s: could not allocate clock data\n", __func__);
+ goto err;
+ }
+ clk_data->base = base;
+
+ clk_table = kzalloc(sizeof(struct clk *) * nr_clks, GFP_KERNEL);
+ if (!clk_table) {
+ pr_err("%s: could not allocate clock lookup table\n", __func__);
+ goto err_data;
+ }
+ clk_data->clk_data.clks = clk_table;
+ clk_data->clk_data.clk_num = nr_clks;
+ of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data->clk_data);
+ return clk_data;
+err_data:
+ kfree(clk_data);
+err:
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(gk_clk_init);
+
+int gk_clk_register_fixed_rate(const struct gk_fixed_rate_clock *clks,
+ int nums, struct gk_clock_data *data)
+{
+ struct clk *clk;
+ int i;
+
+ for (i = 0; i < nums; i++) {
+ clk = clk_register_fixed_rate(NULL, clks[i].name,
+ clks[i].parent_name,
+ clks[i].flags,
+ clks[i].fixed_rate);
+ if (IS_ERR(clk)) {
+ pr_err("%s: failed to register clock %s\n",
+ __func__, clks[i].name);
+ goto err;
+ }
+ data->clk_data.clks[clks[i].id] = clk;
+ }
+
+ return 0;
+
+err:
+ while (i--)
+ clk_unregister_fixed_rate(data->clk_data.clks[clks[i].id]);
+
+ return PTR_ERR(clk);
+}
+EXPORT_SYMBOL_GPL(gk_clk_register_fixed_rate);
+
+int gk_clk_register_fixed_factor(const struct gk_fixed_factor_clock *clks,
+ int nums,
+ struct gk_clock_data *data)
+{
+ struct clk *clk;
+ int i;
+
+ for (i = 0; i < nums; i++) {
+ clk = clk_register_fixed_factor(NULL, clks[i].name,
+ clks[i].parent_name,
+ clks[i].flags, clks[i].mult,
+ clks[i].div);
+ if (IS_ERR(clk)) {
+ pr_err("%s: failed to register clock %s\n",
+ __func__, clks[i].name);
+ goto err;
+ }
+ data->clk_data.clks[clks[i].id] = clk;
+ }
+
+ return 0;
+
+err:
+ while (i--)
+ clk_unregister_fixed_factor(data->clk_data.clks[clks[i].id]);
+
+ return PTR_ERR(clk);
+}
+EXPORT_SYMBOL_GPL(gk_clk_register_fixed_factor);
+
+int gk_clk_register_mux(const struct gk_mux_clock *clks,
+ int nums, struct gk_clock_data *data)
+{
+ struct clk *clk;
+ void __iomem *base = data->base;
+ int i;
+
+ for (i = 0; i < nums; i++) {
+ u32 mask = BIT(clks[i].width) - 1;
+
+ clk = clk_register_mux_table(NULL, clks[i].name,
+ clks[i].parent_names,
+ clks[i].num_parents, clks[i].flags,
+ base + clks[i].offset, clks[i].shift,
+ mask, clks[i].mux_flags,
+ clks[i].table, &gk_clk_lock);
+ if (IS_ERR(clk)) {
+ pr_err("%s: failed to register clock %s\n",
+ __func__, clks[i].name);
+ goto err;
+ }
+
+ if (clks[i].alias)
+ clk_register_clkdev(clk, clks[i].alias, NULL);
+
+ data->clk_data.clks[clks[i].id] = clk;
+ }
+
+ return 0;
+
+err:
+ while (i--)
+ clk_unregister_mux(data->clk_data.clks[clks[i].id]);
+
+ return PTR_ERR(clk);
+}
+EXPORT_SYMBOL_GPL(gk_clk_register_mux);
+
+
+int gk_clk_register_gate(const struct gk_gate_clock *clks,
+ int nums, struct gk_clock_data *data)
+{
+ struct clk *clk;
+ void __iomem *base = data->base;
+ int i;
+
+ for (i = 0; i < nums; i++) {
+ clk = clk_register_gate(NULL, clks[i].name,
+ clks[i].parent_name,
+ clks[i].flags,
+ base + clks[i].offset,
+ clks[i].bit_idx,
+ clks[i].gate_flags,
+ &gk_clk_lock);
+ if (IS_ERR(clk)) {
+ pr_err("%s: failed to register clock %s\n",
+ __func__, clks[i].name);
+ goto err;
+ }
+
+ if (clks[i].alias)
+ clk_register_clkdev(clk, clks[i].alias, NULL);
+
+ data->clk_data.clks[clks[i].id] = clk;
+ }
+
+ return 0;
+
+err:
+ while (i--)
+ clk_unregister_gate(data->clk_data.clks[clks[i].id]);
+
+ return PTR_ERR(clk);
+}
+EXPORT_SYMBOL_GPL(gk_clk_register_gate);
\ В конце файла нет новой строки
diff -urN linux-4.9.37/drivers/clk/goke/clk-gk7202v300.c linux-4.9.y/drivers/clk/goke/clk-gk7202v300.c
--- linux-4.9.37/drivers/clk/goke/clk-gk7202v300.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/clk/goke/clk-gk7202v300.c 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#include <dt-bindings/clock/gk7202v300-clock.h>
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include "clk.h"
+#include "reset.h"
+
+static struct gk_fixed_rate_clock gk7202v300_fixed_rate_clks[] __initdata = {
+ { GK7202V300_FIXED_100K, "100k", NULL, 0, 100000, },
+ { GK7202V300_FIXED_400K, "400k", NULL, 0, 400000, },
+ { GK7202V300_FIXED_3M, "3m", NULL, 0, 3000000, },
+ { GK7202V300_FIXED_6M, "6m", NULL, 0, 6000000, },
+ { GK7202V300_FIXED_12M, "12m", NULL, 0, 12000000, },
+ { GK7202V300_FIXED_24M, "24m", NULL, 0, 24000000, },
+ { GK7202V300_FIXED_25M, "25m", NULL, 0, 25000000, },
+ { GK7202V300_FIXED_50M, "50m", NULL, 0, 50000000, },
+ { GK7202V300_FIXED_83P3M, "83.3m",NULL, 0, 83300000, },
+ { GK7202V300_FIXED_90M, "90m", NULL, 0, 90000000, },
+ { GK7202V300_FIXED_100M, "100m", NULL, 0, 100000000, },
+ { GK7202V300_FIXED_112M, "112m", NULL, 0, 112000000, },
+ { GK7202V300_FIXED_125M, "125m", NULL, 0, 125000000, },
+ { GK7202V300_FIXED_150M, "150m", NULL, 0, 150000000, },
+ { GK7202V300_FIXED_200M, "200m", NULL, 0, 200000000, },
+ { GK7202V300_FIXED_250M, "250m", NULL, 0, 250000000, },
+ { GK7202V300_FIXED_300M, "300m", NULL, 0, 300000000, },
+ { GK7202V300_FIXED_324M, "324m", NULL, 0, 324000000, },
+ { GK7202V300_FIXED_342M, "342m", NULL, 0, 342000000, },
+ { GK7202V300_FIXED_342M, "375m", NULL, 0, 375000000, },
+ { GK7202V300_FIXED_400M, "400m", NULL, 0, 400000000, },
+ { GK7202V300_FIXED_448M, "448m", NULL, 0, 448000000, },
+ { GK7202V300_FIXED_500M, "500m", NULL, 0, 500000000, },
+ { GK7202V300_FIXED_540M, "540m", NULL, 0, 540000000, },
+ { GK7202V300_FIXED_600M, "600m", NULL, 0, 600000000, },
+ { GK7202V300_FIXED_750M, "750m", NULL, 0, 750000000, },
+ { GK7202V300_FIXED_1000M, "1000m",NULL, 0, 1000000000, },
+ { GK7202V300_FIXED_1500M, "1500m",NULL, 0, 1500000000UL, },
+};
+
+static const char *sysaxi_mux_p[] __initconst = {
+ "24m", "200m"
+};
+static const char *sysapb_mux_p[] __initconst = {"24m", "50m"};
+static const char *uart_mux_p[] __initconst = {"24m", "6m"};
+static const char *fmc_mux_p[] __initconst = {"24m", "100m", "150m", "200m", "300m", "360m"};
+static const char *mmc_mux_p[] __initdata = {
+ "100k", "400k", "25m", "50m", "90m", "112m", "150m"
+};
+static const char *eth_mux_p[] __initconst = {"100m", "54m"};
+static const char *usb_mux_p[] __initdata = {"phy", "crg",};
+
+static u32 sysaxi_mux_table[] = {0, 1};
+static u32 sysapb_mux_table[] = {0, 1};
+static u32 uart_mux_table[] = {0, 1};
+static u32 fmc_mux_table[] = {0, 1, 2, 3, 4, 5, 6, 7};
+static u32 mmc_mux_table[] = {0, 1, 2, 3, 4, 5, 6};
+static u32 eth_mux_table[] = {0, 1};
+static u32 usb_mux_table[] = {0, 1};
+
+static struct gk_mux_clock gk7202v300_mux_clks[] __initdata = {
+ {
+ GK7202V300_SYSAXI_CLK, "sysaxi_mux", sysaxi_mux_p,
+ ARRAY_SIZE(sysaxi_mux_p),
+ CLK_SET_RATE_PARENT, 0x80, 6, 1, 0, sysaxi_mux_table,
+ },
+ {
+ GK7202V300_SYSAPB_CLK, "sysapb_mux", sysapb_mux_p,
+ ARRAY_SIZE(sysapb_mux_p),
+ CLK_SET_RATE_PARENT, 0x80, 10, 1, 0, sysapb_mux_table,
+ },
+ {
+ GK7202V300_FMC_MUX, "fmc_mux", fmc_mux_p, ARRAY_SIZE(fmc_mux_p),
+ CLK_SET_RATE_PARENT, 0x144, 2, 3, 0, fmc_mux_table,
+ },
+ {
+ GK7202V300_MMC0_MUX, "mmc0_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
+ CLK_SET_RATE_PARENT, 0x1f4, 24, 3, 0, mmc_mux_table,
+ },
+ {
+ GK7202V300_MMC1_MUX, "mmc1_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
+ CLK_SET_RATE_PARENT, 0x22c, 24, 3, 0, mmc_mux_table,
+ },
+ {
+ GK7202V300_UART_MUX, "uart_mux0", uart_mux_p,
+ ARRAY_SIZE(uart_mux_p),
+ CLK_SET_RATE_PARENT, 0x1bc, 18, 1, 0, uart_mux_table,
+ },
+ {
+ GK7202V300_UART_MUX, "uart_mux1", uart_mux_p,
+ ARRAY_SIZE(uart_mux_p),
+ CLK_SET_RATE_PARENT, 0x1bc, 19, 1, 0, uart_mux_table,
+ },
+ {
+ GK7202V300_UART_MUX, "uart_mux2", uart_mux_p,
+ ARRAY_SIZE(uart_mux_p),
+ CLK_SET_RATE_PARENT, 0x1bc, 20, 1, 0, uart_mux_table,
+ },
+ {
+ GK7202V300_ETH_MUX, "eth_mux", eth_mux_p, ARRAY_SIZE(eth_mux_p),
+ CLK_SET_RATE_PARENT, 0x16c, 7, 1, 0, eth_mux_table,
+ },
+ {
+ GK7202V300_USB2_MUX, "usb2_mux", usb_mux_p, ARRAY_SIZE(usb_mux_p),
+ CLK_SET_RATE_PARENT, 0x140, 13, 0, 0, usb_mux_table
+ },
+};
+
+static struct gk_fixed_factor_clock gk7202v300_fixed_factor_clks[] __initdata = {
+ {
+ GK7202V300_SYSAXI_CLK, "clk_sysaxi", "sysaxi_mux", 1, 4,
+ CLK_SET_RATE_PARENT
+ },
+};
+
+static struct gk_gate_clock gk7202v300_gate_clks[] __initdata = {
+ /* fmc */
+ {
+ GK7202V300_FMC_CLK, "clk_fmc", "fmc_mux",
+ CLK_SET_RATE_PARENT, 0x144, 1, 0,
+ },
+ /* mmc */
+ {
+ GK7202V300_MMC0_CLK, "clk_mmc0", "mmc0_mux",
+ CLK_SET_RATE_PARENT, 0x1f4, 28, 0,
+ },
+ {
+ GK7202V300_MMC1_CLK, "clk_mmc1", "mmc1_mux",
+ CLK_SET_RATE_PARENT, 0x22c, 28, 0,
+ },
+ /* uart */
+ {
+ GK7202V300_UART0_CLK, "clk_uart0", "24m",
+ CLK_SET_RATE_PARENT, 0x1b8, 0, 0,
+ },
+ {
+ GK7202V300_UART1_CLK, "clk_uart1", "24m",
+ CLK_SET_RATE_PARENT, 0x1b8, 1, 0,
+ },
+ {
+ GK7202V300_UART2_CLK, "clk_uart2", "24m",
+ CLK_SET_RATE_PARENT, 0x1b8, 2, 0,
+ },
+ /* spi */
+ {
+ GK7202V300_SPI0_CLK, "clk_spi0", "100m",
+ CLK_SET_RATE_PARENT, 0x1bc, 12, 0,
+ },
+ {
+ GK7202V300_SPI1_CLK, "clk_spi1", "100m",
+ CLK_SET_RATE_PARENT, 0x1bc, 13, 0,
+ },
+ /* i2c */
+ {
+ GK7202V300_I2C0_CLK, "clk_i2c0", "50m",
+ CLK_SET_RATE_PARENT, 0x1b8, 11, 0,
+ },
+ {
+ GK7202V300_I2C1_CLK, "clk_i2c1", "50m",
+ CLK_SET_RATE_PARENT, 0x1b8, 12, 0,
+ },
+ {
+ GK7202V300_I2C2_CLK, "clk_i2c2", "50m",
+ CLK_SET_RATE_PARENT, 0x1b8, 13, 0,
+ },
+ /* ethernet mac */
+ {
+ GK7202V300_ETH0_CLK, "clk_eth0", "eth_mux",
+ CLK_SET_RATE_PARENT, 0x16c, 1, 0,
+ },
+ /* edmac */
+ {
+ GK7202V300_EDMAC_AXICLK, "axi_clk_edmac", NULL,
+ CLK_SET_RATE_PARENT, 0x194, 2, 0,
+ },
+ {
+ GK7202V300_EDMAC_CLK, "clk_edmac", NULL,
+ CLK_SET_RATE_PARENT, 0x194, 1, 0,
+ },
+ /* usb */
+ {
+ GK7202V300_USB2_BUS_CLK, "clk_usb2_bus", "usb2_mux",
+ CLK_SET_RATE_PARENT, 0x140, 8, 0,
+ },
+ {
+ GK7202V300_USB2_REF_CLK, "clk_usb2_ref", "usb2_mux",
+ CLK_SET_RATE_PARENT, 0x140, 9, 0,
+ },
+ {
+ GK7202V300_USB2_UTMI_CLK, "clk_usb2_utmi", "usb2_mux",
+ CLK_SET_RATE_PARENT, 0x140, 12, 0,
+ },
+ {
+ GK7202V300_USB2_PHY_APB_CLK, "clk_u2phy_apb_ref",NULL,
+ CLK_SET_RATE_PARENT, 0x140, 11, 0,
+ },
+ {
+ GK7202V300_USB2_PHY_PLL_CLK, "clk_u2phy_pll_ref",NULL,
+ CLK_SET_RATE_PARENT, 0x140, 4, 0,
+ },
+ {
+ GK7202V300_USB2_PHY_XO_CLK, "clk_u2phy_xo_ref",NULL,
+ CLK_SET_RATE_PARENT, 0x140, 2, 0,
+ },
+};
+
+static void __init gk7202v300_clk_init(struct device_node *np)
+{
+ struct gk_clock_data *clk_data;
+
+ clk_data = gk_clk_init(np, GK7202V300_NR_CLKS);
+ if (!clk_data)
+ return;
+ if (IS_ENABLED(CONFIG_RESET_CONTROLLER))
+ gk_reset_init(np, GK7202V300_NR_RSTS);
+
+ gk_clk_register_fixed_rate(gk7202v300_fixed_rate_clks,
+ ARRAY_SIZE(gk7202v300_fixed_rate_clks),
+ clk_data);
+ gk_clk_register_mux(gk7202v300_mux_clks, ARRAY_SIZE(gk7202v300_mux_clks),
+ clk_data);
+ gk_clk_register_fixed_factor(gk7202v300_fixed_factor_clks,
+ ARRAY_SIZE(gk7202v300_fixed_factor_clks), clk_data);
+ gk_clk_register_gate(gk7202v300_gate_clks,
+ ARRAY_SIZE(gk7202v300_gate_clks), clk_data);
+
+}
+
+CLK_OF_DECLARE(gk7202v300_clk, "goke,gk7202v300-clock", gk7202v300_clk_init);
+
diff -urN linux-4.9.37/drivers/clk/goke/clk-gk7205v200.c linux-4.9.y/drivers/clk/goke/clk-gk7205v200.c
--- linux-4.9.37/drivers/clk/goke/clk-gk7205v200.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/clk/goke/clk-gk7205v200.c 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#include <dt-bindings/clock/gk7205v200-clock.h>
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include "clk.h"
+#include "reset.h"
+
+static struct gk_fixed_rate_clock gk7205v200_fixed_rate_clks[] __initdata = {
+ { GK7205V200_FIXED_100K, "100k", NULL, 0, 100000, },
+ { GK7205V200_FIXED_400K, "400k", NULL, 0, 400000, },
+ { GK7205V200_FIXED_3M, "3m", NULL, 0, 3000000, },
+ { GK7205V200_FIXED_6M, "6m", NULL, 0, 6000000, },
+ { GK7205V200_FIXED_12M, "12m", NULL, 0, 12000000, },
+ { GK7205V200_FIXED_24M, "24m", NULL, 0, 24000000, },
+ { GK7205V200_FIXED_25M, "25m", NULL, 0, 25000000, },
+ { GK7205V200_FIXED_50M, "50m", NULL, 0, 50000000, },
+ { GK7205V200_FIXED_83P3M, "83.3m",NULL, 0, 83300000, },
+ { GK7205V200_FIXED_90M, "90m", NULL, 0, 90000000, },
+ { GK7205V200_FIXED_100M, "100m", NULL, 0, 100000000, },
+ { GK7205V200_FIXED_112M, "112m", NULL, 0, 112000000, },
+ { GK7205V200_FIXED_125M, "125m", NULL, 0, 125000000, },
+ { GK7205V200_FIXED_150M, "150m", NULL, 0, 150000000, },
+ { GK7205V200_FIXED_200M, "200m", NULL, 0, 200000000, },
+ { GK7205V200_FIXED_250M, "250m", NULL, 0, 250000000, },
+ { GK7205V200_FIXED_300M, "300m", NULL, 0, 300000000, },
+ { GK7205V200_FIXED_324M, "324m", NULL, 0, 324000000, },
+ { GK7205V200_FIXED_342M, "342m", NULL, 0, 342000000, },
+ { GK7205V200_FIXED_342M, "375m", NULL, 0, 375000000, },
+ { GK7205V200_FIXED_400M, "400m", NULL, 0, 400000000, },
+ { GK7205V200_FIXED_448M, "448m", NULL, 0, 448000000, },
+ { GK7205V200_FIXED_500M, "500m", NULL, 0, 500000000, },
+ { GK7205V200_FIXED_540M, "540m", NULL, 0, 540000000, },
+ { GK7205V200_FIXED_600M, "600m", NULL, 0, 600000000, },
+ { GK7205V200_FIXED_750M, "750m", NULL, 0, 750000000, },
+ { GK7205V200_FIXED_1000M, "1000m",NULL, 0, 1000000000, },
+ { GK7205V200_FIXED_1500M, "1500m",NULL, 0, 1500000000UL, },
+};
+
+static const char *sysaxi_mux_p[] __initconst = {
+ "24m", "200m"
+};
+static const char *sysapb_mux_p[] __initconst = {"24m", "50m"};
+static const char *uart_mux_p[] __initconst = {"24m", "6m"};
+static const char *fmc_mux_p[] __initconst = {"24m", "100m", "150m", "200m", "300m", "360m"};
+static const char *mmc_mux_p[] __initdata = {
+ "100k", "400k", "25m", "50m", "90m", "112m", "150m"
+};
+static const char *eth_mux_p[] __initconst = {"100m", "54m"};
+static const char *usb_mux_p[] __initdata = {"phy", "crg",};
+
+static u32 sysaxi_mux_table[] = {0, 1};
+static u32 sysapb_mux_table[] = {0, 1};
+static u32 uart_mux_table[] = {0, 1};
+static u32 fmc_mux_table[] = {0, 1, 2, 3, 4, 5, 6, 7};
+static u32 mmc_mux_table[] = {0, 1, 2, 3, 4, 5, 6};
+static u32 eth_mux_table[] = {0, 1};
+static u32 usb_mux_table[] = {0, 1};
+
+static struct gk_mux_clock gk7205v200_mux_clks[] __initdata = {
+ {
+ GK7205V200_SYSAXI_CLK, "sysaxi_mux", sysaxi_mux_p,
+ ARRAY_SIZE(sysaxi_mux_p),
+ CLK_SET_RATE_PARENT, 0x80, 6, 1, 0, sysaxi_mux_table,
+ },
+ {
+ GK7205V200_SYSAPB_CLK, "sysapb_mux", sysapb_mux_p,
+ ARRAY_SIZE(sysapb_mux_p),
+ CLK_SET_RATE_PARENT, 0x80, 10, 1, 0, sysapb_mux_table,
+ },
+ {
+ GK7205V200_FMC_MUX, "fmc_mux", fmc_mux_p, ARRAY_SIZE(fmc_mux_p),
+ CLK_SET_RATE_PARENT, 0x144, 2, 3, 0, fmc_mux_table,
+ },
+ {
+ GK7205V200_MMC0_MUX, "mmc0_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
+ CLK_SET_RATE_PARENT, 0x1f4, 24, 3, 0, mmc_mux_table,
+ },
+ {
+ GK7205V200_MMC1_MUX, "mmc1_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
+ CLK_SET_RATE_PARENT, 0x22c, 24, 3, 0, mmc_mux_table,
+ },
+ {
+ GK7205V200_UART_MUX, "uart_mux0", uart_mux_p,
+ ARRAY_SIZE(uart_mux_p),
+ CLK_SET_RATE_PARENT, 0x1bc, 18, 1, 0, uart_mux_table,
+ },
+ {
+ GK7205V200_UART_MUX, "uart_mux1", uart_mux_p,
+ ARRAY_SIZE(uart_mux_p),
+ CLK_SET_RATE_PARENT, 0x1bc, 19, 1, 0, uart_mux_table,
+ },
+ {
+ GK7205V200_UART_MUX, "uart_mux2", uart_mux_p,
+ ARRAY_SIZE(uart_mux_p),
+ CLK_SET_RATE_PARENT, 0x1bc, 20, 1, 0, uart_mux_table,
+ },
+ {
+ GK7205V200_ETH_MUX, "eth_mux", eth_mux_p, ARRAY_SIZE(eth_mux_p),
+ CLK_SET_RATE_PARENT, 0x16c, 7, 1, 0, eth_mux_table,
+ },
+ {
+ GK7205V200_USB2_MUX, "usb2_mux", usb_mux_p, ARRAY_SIZE(usb_mux_p),
+ CLK_SET_RATE_PARENT, 0x140, 13, 0, 0, usb_mux_table
+ },
+};
+
+#if 1
+static struct gk_fixed_factor_clock gk7205v200_fixed_factor_clks[] __initdata = {
+ {
+ GK7205V200_SYSAXI_CLK, "clk_sysaxi", "sysaxi_mux", 1, 4,
+ CLK_SET_RATE_PARENT
+ },
+};
+#endif
+
+static struct gk_gate_clock gk7205v200_gate_clks[] __initdata = {
+ /* fmc */
+ {
+ GK7205V200_FMC_CLK, "clk_fmc", "fmc_mux",
+ CLK_SET_RATE_PARENT, 0x144, 1, 0,
+ },
+ /* mmc */
+ {
+ GK7205V200_MMC0_CLK, "clk_mmc0", "mmc0_mux",
+ CLK_SET_RATE_PARENT, 0x1f4, 28, 0,
+ },
+ {
+ GK7205V200_MMC1_CLK, "clk_mmc1", "mmc1_mux",
+ CLK_SET_RATE_PARENT, 0x22c, 28, 0,
+ },
+ /* uart */
+ {
+ GK7205V200_UART0_CLK, "clk_uart0", "24m",
+ CLK_SET_RATE_PARENT, 0x1b8, 0, 0,
+ },
+ {
+ GK7205V200_UART1_CLK, "clk_uart1", "uart_mux1",
+ CLK_SET_RATE_PARENT, 0x1b8, 1, 0,
+ },
+ {
+ GK7205V200_UART2_CLK, "clk_uart2", "uart_mux2",
+ CLK_SET_RATE_PARENT, 0x1b8, 2, 0,
+ },
+ /* spi */
+ {
+ GK7205V200_SPI0_CLK, "clk_spi0", "100m",
+ CLK_SET_RATE_PARENT, 0x1bc, 12, 0,
+ },
+ {
+ GK7205V200_SPI1_CLK, "clk_spi1", "100m",
+ CLK_SET_RATE_PARENT, 0x1bc, 13, 0,
+ },
+ /* i2c */
+ {
+ GK7205V200_I2C0_CLK, "clk_i2c0", "50m",
+ CLK_SET_RATE_PARENT, 0x1b8, 11, 0,
+ },
+ {
+ GK7205V200_I2C1_CLK, "clk_i2c1", "50m",
+ CLK_SET_RATE_PARENT, 0x1b8, 12, 0,
+ },
+ {
+ GK7205V200_I2C2_CLK, "clk_i2c2", "50m",
+ CLK_SET_RATE_PARENT, 0x1b8, 13, 0,
+ },
+ /* ethernet mac */
+ {
+ GK7205V200_ETH0_CLK, "clk_eth0", "eth_mux",
+ CLK_SET_RATE_PARENT, 0x16c, 1, 0,
+ },
+ /* edmac */
+ {
+ GK7205V200_EDMAC_AXICLK, "axi_clk_edmac", NULL,
+ CLK_SET_RATE_PARENT, 0x194, 2, 0,
+ },
+ {
+ GK7205V200_EDMAC_CLK, "clk_edmac", NULL,
+ CLK_SET_RATE_PARENT, 0x194, 1, 0,
+ },
+ /* usb */
+ {
+ GK7205V200_USB2_BUS_CLK, "clk_usb2_bus", "usb2_mux",
+ CLK_SET_RATE_PARENT, 0x140, 8, 0,
+ },
+ {
+ GK7205V200_USB2_REF_CLK, "clk_usb2_ref", "usb2_mux",
+ CLK_SET_RATE_PARENT, 0x140, 9, 0,
+ },
+ {
+ GK7205V200_USB2_UTMI_CLK, "clk_usb2_utmi", "usb2_mux",
+ CLK_SET_RATE_PARENT, 0x140, 12, 0,
+ },
+ {
+ GK7205V200_USB2_PHY_APB_CLK, "clk_u2phy_apb_ref",NULL,
+ CLK_SET_RATE_PARENT, 0x140, 11, 0,
+ },
+ {
+ GK7205V200_USB2_PHY_PLL_CLK, "clk_u2phy_pll_ref",NULL,
+ CLK_SET_RATE_PARENT, 0x140, 4, 0,
+ },
+ {
+ GK7205V200_USB2_PHY_XO_CLK, "clk_u2phy_xo_ref",NULL,
+ CLK_SET_RATE_PARENT, 0x140, 2, 0,
+ },
+};
+
+static void __init gk7205v200_clk_init(struct device_node *np)
+{
+ struct gk_clock_data *clk_data;
+
+ clk_data = gk_clk_init(np, GK7205V200_NR_CLKS);
+ if (!clk_data)
+ return;
+ if (IS_ENABLED(CONFIG_RESET_CONTROLLER))
+ gk_reset_init(np, GK7205V200_NR_RSTS);
+
+ gk_clk_register_fixed_rate(gk7205v200_fixed_rate_clks,
+ ARRAY_SIZE(gk7205v200_fixed_rate_clks),
+ clk_data);
+ gk_clk_register_mux(gk7205v200_mux_clks, ARRAY_SIZE(gk7205v200_mux_clks),
+ clk_data);
+ gk_clk_register_fixed_factor(gk7205v200_fixed_factor_clks,
+ ARRAY_SIZE(gk7205v200_fixed_factor_clks), clk_data);
+ gk_clk_register_gate(gk7205v200_gate_clks,
+ ARRAY_SIZE(gk7205v200_gate_clks), clk_data);
+
+}
+
+CLK_OF_DECLARE(gk7205v200_clk, "goke,gk7205v200-clock", gk7205v200_clk_init);
+
diff -urN linux-4.9.37/drivers/clk/goke/clk-gk7205v300.c linux-4.9.y/drivers/clk/goke/clk-gk7205v300.c
--- linux-4.9.37/drivers/clk/goke/clk-gk7205v300.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/clk/goke/clk-gk7205v300.c 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#include <dt-bindings/clock/gk7205v300-clock.h>
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include "clk.h"
+#include "reset.h"
+
+static struct gk_fixed_rate_clock gk7205v300_fixed_rate_clks[] __initdata = {
+ { GK7205V300_FIXED_100K, "100k", NULL, 0, 100000, },
+ { GK7205V300_FIXED_400K, "400k", NULL, 0, 400000, },
+ { GK7205V300_FIXED_3M, "3m", NULL, 0, 3000000, },
+ { GK7205V300_FIXED_6M, "6m", NULL, 0, 6000000, },
+ { GK7205V300_FIXED_12M, "12m", NULL, 0, 12000000, },
+ { GK7205V300_FIXED_24M, "24m", NULL, 0, 24000000, },
+ { GK7205V300_FIXED_25M, "25m", NULL, 0, 25000000, },
+ { GK7205V300_FIXED_50M, "50m", NULL, 0, 50000000, },
+ { GK7205V300_FIXED_83P3M, "83.3m",NULL, 0, 83300000, },
+ { GK7205V300_FIXED_90M, "90m", NULL, 0, 90000000, },
+ { GK7205V300_FIXED_100M, "100m", NULL, 0, 100000000, },
+ { GK7205V300_FIXED_112M, "112m", NULL, 0, 112000000, },
+ { GK7205V300_FIXED_125M, "125m", NULL, 0, 125000000, },
+ { GK7205V300_FIXED_150M, "150m", NULL, 0, 150000000, },
+ { GK7205V300_FIXED_200M, "200m", NULL, 0, 200000000, },
+ { GK7205V300_FIXED_250M, "250m", NULL, 0, 250000000, },
+ { GK7205V300_FIXED_300M, "300m", NULL, 0, 300000000, },
+ { GK7205V300_FIXED_324M, "324m", NULL, 0, 324000000, },
+ { GK7205V300_FIXED_342M, "342m", NULL, 0, 342000000, },
+ { GK7205V300_FIXED_342M, "375m", NULL, 0, 375000000, },
+ { GK7205V300_FIXED_400M, "400m", NULL, 0, 400000000, },
+ { GK7205V300_FIXED_448M, "448m", NULL, 0, 448000000, },
+ { GK7205V300_FIXED_500M, "500m", NULL, 0, 500000000, },
+ { GK7205V300_FIXED_540M, "540m", NULL, 0, 540000000, },
+ { GK7205V300_FIXED_600M, "600m", NULL, 0, 600000000, },
+ { GK7205V300_FIXED_750M, "750m", NULL, 0, 750000000, },
+ { GK7205V300_FIXED_1000M, "1000m",NULL, 0, 1000000000, },
+ { GK7205V300_FIXED_1500M, "1500m",NULL, 0, 1500000000UL, },
+};
+
+static const char *sysaxi_mux_p[] __initconst = {
+ "24m", "200m"
+};
+static const char *sysapb_mux_p[] __initconst = {"24m", "50m"};
+static const char *uart_mux_p[] __initconst = {"24m", "6m"};
+static const char *fmc_mux_p[] __initconst = {"24m", "100m", "150m", "200m", "300m", "360m"};
+static const char *mmc_mux_p[] __initdata = {
+ "100k", "400k", "25m", "50m", "90m", "112m", "150m"
+};
+static const char *eth_mux_p[] __initconst = {"100m", "54m"};
+static const char *usb_mux_p[] __initdata = {"phy", "crg",};
+
+static u32 sysaxi_mux_table[] = {0, 1};
+static u32 sysapb_mux_table[] = {0, 1};
+static u32 uart_mux_table[] = {0, 1};
+static u32 fmc_mux_table[] = {0, 1, 2, 3, 4, 5, 6, 7};
+static u32 mmc_mux_table[] = {0, 1, 2, 3, 4, 5, 6};
+static u32 eth_mux_table[] = {0, 1};
+static u32 usb_mux_table[] = {0, 1};
+
+static struct gk_mux_clock gk7205v300_mux_clks[] __initdata = {
+ {
+ GK7205V300_SYSAXI_CLK, "sysaxi_mux", sysaxi_mux_p,
+ ARRAY_SIZE(sysaxi_mux_p),
+ CLK_SET_RATE_PARENT, 0x80, 6, 1, 0, sysaxi_mux_table,
+ },
+ {
+ GK7205V300_SYSAPB_CLK, "sysapb_mux", sysapb_mux_p,
+ ARRAY_SIZE(sysapb_mux_p),
+ CLK_SET_RATE_PARENT, 0x80, 10, 1, 0, sysapb_mux_table,
+ },
+ {
+ GK7205V300_FMC_MUX, "fmc_mux", fmc_mux_p, ARRAY_SIZE(fmc_mux_p),
+ CLK_SET_RATE_PARENT, 0x144, 2, 3, 0, fmc_mux_table,
+ },
+ {
+ GK7205V300_MMC0_MUX, "mmc0_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
+ CLK_SET_RATE_PARENT, 0x1f4, 24, 3, 0, mmc_mux_table,
+ },
+ {
+ GK7205V300_MMC1_MUX, "mmc1_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
+ CLK_SET_RATE_PARENT, 0x22c, 24, 3, 0, mmc_mux_table,
+ },
+ {
+ GK7205V300_UART_MUX, "uart_mux0", uart_mux_p,
+ ARRAY_SIZE(uart_mux_p),
+ CLK_SET_RATE_PARENT, 0x1bc, 18, 1, 0, uart_mux_table,
+ },
+ {
+ GK7205V300_UART_MUX, "uart_mux1", uart_mux_p,
+ ARRAY_SIZE(uart_mux_p),
+ CLK_SET_RATE_PARENT, 0x1bc, 19, 1, 0, uart_mux_table,
+ },
+ {
+ GK7205V300_UART_MUX, "uart_mux2", uart_mux_p,
+ ARRAY_SIZE(uart_mux_p),
+ CLK_SET_RATE_PARENT, 0x1bc, 20, 1, 0, uart_mux_table,
+ },
+ {
+ GK7205V300_ETH_MUX, "eth_mux", eth_mux_p, ARRAY_SIZE(eth_mux_p),
+ CLK_SET_RATE_PARENT, 0x16c, 7, 1, 0, eth_mux_table,
+ },
+ {
+ GK7205V300_USB2_MUX, "usb2_mux", usb_mux_p, ARRAY_SIZE(usb_mux_p),
+ CLK_SET_RATE_PARENT, 0x140, 13, 0, 0, usb_mux_table
+ },
+};
+
+static struct gk_fixed_factor_clock gk7205v300_fixed_factor_clks[] __initdata = {
+ {
+ GK7205V300_SYSAXI_CLK, "clk_sysaxi", "sysaxi_mux", 1, 4,
+ CLK_SET_RATE_PARENT
+ },
+};
+
+static struct gk_gate_clock gk7205v300_gate_clks[] __initdata = {
+ /* fmc */
+ {
+ GK7205V300_FMC_CLK, "clk_fmc", "fmc_mux",
+ CLK_SET_RATE_PARENT, 0x144, 1, 0,
+ },
+ /* mmc */
+ {
+ GK7205V300_MMC0_CLK, "clk_mmc0", "mmc0_mux",
+ CLK_SET_RATE_PARENT, 0x1f4, 28, 0,
+ },
+ {
+ GK7205V300_MMC1_CLK, "clk_mmc1", "mmc1_mux",
+ CLK_SET_RATE_PARENT, 0x22c, 28, 0,
+ },
+ /* uart */
+ {
+ GK7205V300_UART0_CLK, "clk_uart0", "24m",
+ CLK_SET_RATE_PARENT, 0x1b8, 0, 0,
+ },
+ {
+ GK7205V300_UART1_CLK, "clk_uart1", "24m",
+ CLK_SET_RATE_PARENT, 0x1b8, 1, 0,
+ },
+ {
+ GK7205V300_UART2_CLK, "clk_uart2", "24m",
+ CLK_SET_RATE_PARENT, 0x1b8, 2, 0,
+ },
+ /* spi */
+ {
+ GK7205V300_SPI0_CLK, "clk_spi0", "100m",
+ CLK_SET_RATE_PARENT, 0x1bc, 12, 0,
+ },
+ {
+ GK7205V300_SPI1_CLK, "clk_spi1", "100m",
+ CLK_SET_RATE_PARENT, 0x1bc, 13, 0,
+ },
+ /* i2c */
+ {
+ GK7205V300_I2C0_CLK, "clk_i2c0", "50m",
+ CLK_SET_RATE_PARENT, 0x1b8, 11, 0,
+ },
+ {
+ GK7205V300_I2C1_CLK, "clk_i2c1", "50m",
+ CLK_SET_RATE_PARENT, 0x1b8, 12, 0,
+ },
+ {
+ GK7205V300_I2C2_CLK, "clk_i2c2", "50m",
+ CLK_SET_RATE_PARENT, 0x1b8, 13, 0,
+ },
+ /* ethernet mac */
+ {
+ GK7205V300_ETH0_CLK, "clk_eth0", "eth_mux",
+ CLK_SET_RATE_PARENT, 0x16c, 1, 0,
+ },
+ /* edmac */
+ {
+ GK7205V300_EDMAC_AXICLK, "axi_clk_edmac", NULL,
+ CLK_SET_RATE_PARENT, 0x194, 2, 0,
+ },
+ {
+ GK7205V300_EDMAC_CLK, "clk_edmac", NULL,
+ CLK_SET_RATE_PARENT, 0x194, 1, 0,
+ },
+ /* usb */
+ {
+ GK7205V300_USB2_BUS_CLK, "clk_usb2_bus", "usb2_mux",
+ CLK_SET_RATE_PARENT, 0x140, 8, 0,
+ },
+ {
+ GK7205V300_USB2_REF_CLK, "clk_usb2_ref", "usb2_mux",
+ CLK_SET_RATE_PARENT, 0x140, 9, 0,
+ },
+ {
+ GK7205V300_USB2_UTMI_CLK, "clk_usb2_utmi", "usb2_mux",
+ CLK_SET_RATE_PARENT, 0x140, 12, 0,
+ },
+ {
+ GK7205V300_USB2_PHY_APB_CLK, "clk_u2phy_apb_ref",NULL,
+ CLK_SET_RATE_PARENT, 0x140, 11, 0,
+ },
+ {
+ GK7205V300_USB2_PHY_PLL_CLK, "clk_u2phy_pll_ref",NULL,
+ CLK_SET_RATE_PARENT, 0x140, 4, 0,
+ },
+ {
+ GK7205V300_USB2_PHY_XO_CLK, "clk_u2phy_xo_ref",NULL,
+ CLK_SET_RATE_PARENT, 0x140, 2, 0,
+ },
+};
+
+static void __init gk7205v300_clk_init(struct device_node *np)
+{
+ struct gk_clock_data *clk_data;
+
+ clk_data = gk_clk_init(np, GK7205V300_NR_CLKS);
+ if (!clk_data)
+ return;
+ if (IS_ENABLED(CONFIG_RESET_CONTROLLER))
+ gk_reset_init(np, GK7205V300_NR_RSTS);
+
+ gk_clk_register_fixed_rate(gk7205v300_fixed_rate_clks,
+ ARRAY_SIZE(gk7205v300_fixed_rate_clks),
+ clk_data);
+ gk_clk_register_mux(gk7205v300_mux_clks, ARRAY_SIZE(gk7205v300_mux_clks),
+ clk_data);
+ gk_clk_register_fixed_factor(gk7205v300_fixed_factor_clks,
+ ARRAY_SIZE(gk7205v300_fixed_factor_clks), clk_data);
+ gk_clk_register_gate(gk7205v300_gate_clks,
+ ARRAY_SIZE(gk7205v300_gate_clks), clk_data);
+
+}
+
+CLK_OF_DECLARE(gk7205v300_clk, "goke,gk7205v300-clock", gk7205v300_clk_init);
+
diff -urN linux-4.9.37/drivers/clk/goke/clk-gk7605v100.c linux-4.9.y/drivers/clk/goke/clk-gk7605v100.c
--- linux-4.9.37/drivers/clk/goke/clk-gk7605v100.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/clk/goke/clk-gk7605v100.c 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#include <dt-bindings/clock/gk7605v100-clock.h>
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include "clk.h"
+#include "reset.h"
+
+static struct gk_fixed_rate_clock gk7605v100_fixed_rate_clks[] __initdata = {
+ { GK7605V100_FIXED_100K, "100k", NULL, 0, 100000, },
+ { GK7605V100_FIXED_400K, "400k", NULL, 0, 400000, },
+ { GK7605V100_FIXED_3M, "3m", NULL, 0, 3000000, },
+ { GK7605V100_FIXED_6M, "6m", NULL, 0, 6000000, },
+ { GK7605V100_FIXED_12M, "12m", NULL, 0, 12000000, },
+ { GK7605V100_FIXED_24M, "24m", NULL, 0, 24000000, },
+ { GK7605V100_FIXED_25M, "25m", NULL, 0, 25000000, },
+ { GK7605V100_FIXED_50M, "50m", NULL, 0, 50000000, },
+ { GK7605V100_FIXED_83P3M, "83.3m",NULL, 0, 83300000, },
+ { GK7605V100_FIXED_90M, "90m", NULL, 0, 90000000, },
+ { GK7605V100_FIXED_100M, "100m", NULL, 0, 100000000, },
+ { GK7605V100_FIXED_112M, "112m", NULL, 0, 112000000, },
+ { GK7605V100_FIXED_125M, "125m", NULL, 0, 125000000, },
+ { GK7605V100_FIXED_150M, "150m", NULL, 0, 150000000, },
+ { GK7605V100_FIXED_200M, "200m", NULL, 0, 200000000, },
+ { GK7605V100_FIXED_250M, "250m", NULL, 0, 250000000, },
+ { GK7605V100_FIXED_300M, "300m", NULL, 0, 300000000, },
+ { GK7605V100_FIXED_324M, "324m", NULL, 0, 324000000, },
+ { GK7605V100_FIXED_342M, "342m", NULL, 0, 342000000, },
+ { GK7605V100_FIXED_342M, "375m", NULL, 0, 375000000, },
+ { GK7605V100_FIXED_400M, "400m", NULL, 0, 400000000, },
+ { GK7605V100_FIXED_448M, "448m", NULL, 0, 448000000, },
+ { GK7605V100_FIXED_500M, "500m", NULL, 0, 500000000, },
+ { GK7605V100_FIXED_540M, "540m", NULL, 0, 540000000, },
+ { GK7605V100_FIXED_600M, "600m", NULL, 0, 600000000, },
+ { GK7605V100_FIXED_750M, "750m", NULL, 0, 750000000, },
+ { GK7605V100_FIXED_1000M, "1000m",NULL, 0, 1000000000, },
+ { GK7605V100_FIXED_1500M, "1500m",NULL, 0, 1500000000UL, },
+};
+
+static const char *sysaxi_mux_p[] __initconst = {
+ "24m", "200m"
+};
+static const char *sysapb_mux_p[] __initconst = {"24m", "50m"};
+static const char *uart_mux_p[] __initconst = {"24m", "6m"};
+static const char *fmc_mux_p[] __initconst = {"24m", "100", "150m", "200m", "300m", "360m"};
+static const char *mmc_mux_p[] __initdata = {
+ "100k", "400k", "25m", "50m", "90m", "112m", "150m"
+};
+static const char *eth_mux_p[] __initconst = {"100m", "54m"};
+static const char *usb_mux_p[] __initdata = {"phy", "crg",};
+
+static u32 sysaxi_mux_table[] = {0, 1};
+static u32 sysapb_mux_table[] = {0, 1};
+static u32 uart_mux_table[] = {0, 1};
+static u32 fmc_mux_table[] = {0, 1, 2, 3, 4, 5, 6, 7};
+static u32 mmc_mux_table[] = {0, 1, 2, 3, 4, 5, 6};
+static u32 eth_mux_table[] = {0, 1};
+static u32 usb_mux_table[] = {0, 1};
+
+static struct gk_mux_clock gk7605v100_mux_clks[] __initdata = {
+ {
+ GK7605V100_SYSAXI_CLK, "sysaxi_mux", sysaxi_mux_p,
+ ARRAY_SIZE(sysaxi_mux_p),
+ CLK_SET_RATE_PARENT, 0x80, 6, 1, 0, sysaxi_mux_table,
+ },
+ {
+ GK7605V100_SYSAPB_CLK, "sysapb_mux", sysapb_mux_p,
+ ARRAY_SIZE(sysapb_mux_p),
+ CLK_SET_RATE_PARENT, 0x80, 10, 1, 0, sysapb_mux_table,
+ },
+ {
+ GK7605V100_FMC_MUX, "fmc_mux", fmc_mux_p, ARRAY_SIZE(fmc_mux_p),
+ CLK_SET_RATE_PARENT, 0x144, 2, 3, 0, fmc_mux_table,
+ },
+ {
+ GK7605V100_MMC0_MUX, "mmc0_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
+ CLK_SET_RATE_PARENT, 0x1f4, 24, 3, 0, mmc_mux_table,
+ },
+ {
+ GK7605V100_MMC1_MUX, "mmc1_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
+ CLK_SET_RATE_PARENT, 0x22c, 24, 3, 0, mmc_mux_table,
+ },
+ {
+ GK7605V100_UART_MUX, "uart_mux0", uart_mux_p,
+ ARRAY_SIZE(uart_mux_p),
+ CLK_SET_RATE_PARENT, 0x1bc, 18, 1, 0, uart_mux_table,
+ },
+ {
+ GK7605V100_UART_MUX, "uart_mux1", uart_mux_p,
+ ARRAY_SIZE(uart_mux_p),
+ CLK_SET_RATE_PARENT, 0x1bc, 19, 1, 0, uart_mux_table,
+ },
+ {
+ GK7605V100_UART_MUX, "uart_mux2", uart_mux_p,
+ ARRAY_SIZE(uart_mux_p),
+ CLK_SET_RATE_PARENT, 0x1bc, 20, 1, 0, uart_mux_table,
+ },
+ {
+ GK7605V100_ETH_MUX, "eth_mux", eth_mux_p, ARRAY_SIZE(eth_mux_p),
+ CLK_SET_RATE_PARENT, 0x16c, 7, 1, 0, eth_mux_table,
+ },
+ {
+ GK7605V100_USB2_MUX, "usb2_mux", usb_mux_p, ARRAY_SIZE(usb_mux_p),
+ CLK_SET_RATE_PARENT, 0x140, 13, 0, 0, usb_mux_table
+ },
+};
+
+static struct gk_fixed_factor_clock gk7605v100_fixed_factor_clks[] __initdata = {
+ {
+ GK7605V100_SYSAXI_CLK, "clk_sysaxi", "sysaxi_mux", 1, 4,
+ CLK_SET_RATE_PARENT
+ },
+};
+
+static struct gk_gate_clock gk7605v100_gate_clks[] __initdata = {
+ /* fmc */
+ {
+ GK7605V100_FMC_CLK, "clk_fmc", "fmc_mux",
+ CLK_SET_RATE_PARENT, 0x144, 1, 0,
+ },
+ /* mmc */
+ {
+ GK7605V100_MMC0_CLK, "clk_mmc0", "mmc0_mux",
+ CLK_SET_RATE_PARENT, 0x1f4, 28, 0,
+ },
+ {
+ GK7605V100_MMC1_CLK, "clk_mmc1", "mmc1_mux",
+ CLK_SET_RATE_PARENT, 0x22c, 28, 0,
+ },
+ /* uart */
+ {
+ GK7605V100_UART0_CLK, "clk_uart0", "24m",
+ CLK_SET_RATE_PARENT, 0x1b8, 0, 0,
+ },
+ {
+ GK7605V100_UART1_CLK, "clk_uart1", "24m",
+ CLK_SET_RATE_PARENT, 0x1b8, 1, 0,
+ },
+ {
+ GK7605V100_UART2_CLK, "clk_uart2", "24m",
+ CLK_SET_RATE_PARENT, 0x1b8, 2, 0,
+ },
+ /* spi */
+ {
+ GK7605V100_SPI0_CLK, "clk_spi0", "100m",
+ CLK_SET_RATE_PARENT, 0x1bc, 12, 0,
+ },
+ {
+ GK7605V100_SPI1_CLK, "clk_spi1", "100m",
+ CLK_SET_RATE_PARENT, 0x1bc, 13, 0,
+ },
+ /* i2c */
+ {
+ GK7605V100_I2C0_CLK, "clk_i2c0", "50m",
+ CLK_SET_RATE_PARENT, 0x1b8, 11, 0,
+ },
+ {
+ GK7605V100_I2C1_CLK, "clk_i2c1", "50m",
+ CLK_SET_RATE_PARENT, 0x1b8, 12, 0,
+ },
+ {
+ GK7605V100_I2C2_CLK, "clk_i2c2", "50m",
+ CLK_SET_RATE_PARENT, 0x1b8, 13, 0,
+ },
+ /* ethernet mac */
+ {
+ GK7605V100_ETH0_CLK, "clk_eth0", "eth_mux",
+ CLK_SET_RATE_PARENT, 0x16c, 1, 0,
+ },
+ /* edmac */
+ {
+ GK7605V100_EDMAC_AXICLK, "axi_clk_edmac", NULL,
+ CLK_SET_RATE_PARENT, 0x194, 2, 0,
+ },
+ {
+ GK7605V100_EDMAC_CLK, "clk_edmac", NULL,
+ CLK_SET_RATE_PARENT, 0x194, 1, 0,
+ },
+ /* usb */
+ {
+ GK7605V100_USB2_BUS_CLK, "clk_usb2_bus", "usb2_mux",
+ CLK_SET_RATE_PARENT, 0x140, 8, 0,
+ },
+ {
+ GK7605V100_USB2_REF_CLK, "clk_usb2_ref", "usb2_mux",
+ CLK_SET_RATE_PARENT, 0x140, 9, 0,
+ },
+ {
+ GK7605V100_USB2_UTMI_CLK, "clk_usb2_utmi", "usb2_mux",
+ CLK_SET_RATE_PARENT, 0x140, 12, 0,
+ },
+ {
+ GK7605V100_USB2_PHY_APB_CLK, "clk_u2phy_apb_ref",NULL,
+ CLK_SET_RATE_PARENT, 0x140, 11, 0,
+ },
+ {
+ GK7605V100_USB2_PHY_PLL_CLK, "clk_u2phy_pll_ref",NULL,
+ CLK_SET_RATE_PARENT, 0x140, 4, 0,
+ },
+ {
+ GK7605V100_USB2_PHY_XO_CLK, "clk_u2phy_xo_ref",NULL,
+ CLK_SET_RATE_PARENT, 0x140, 2, 0,
+ },
+};
+
+static void __init gk7605v100_clk_init(struct device_node *np)
+{
+ struct gk_clock_data *clk_data;
+
+ clk_data = gk_clk_init(np, GK7605V100_NR_CLKS);
+ if (!clk_data)
+ return;
+ if (IS_ENABLED(CONFIG_RESET_CONTROLLER))
+ gk_reset_init(np, GK7605V100_NR_RSTS);
+
+ gk_clk_register_fixed_rate(gk7605v100_fixed_rate_clks,
+ ARRAY_SIZE(gk7605v100_fixed_rate_clks),
+ clk_data);
+ gk_clk_register_mux(gk7605v100_mux_clks, ARRAY_SIZE(gk7605v100_mux_clks),
+ clk_data);
+ gk_clk_register_fixed_factor(gk7605v100_fixed_factor_clks,
+ ARRAY_SIZE(gk7605v100_fixed_factor_clks), clk_data);
+ gk_clk_register_gate(gk7605v100_gate_clks,
+ ARRAY_SIZE(gk7605v100_gate_clks), clk_data);
+
+}
+
+CLK_OF_DECLARE(gk7605v100_clk, "goke,gk7605v100-clock", gk7605v100_clk_init);
+
diff -urN linux-4.9.37/drivers/clk/goke/clk.h linux-4.9.y/drivers/clk/goke/clk.h
--- linux-4.9.37/drivers/clk/goke/clk.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/clk/goke/clk.h 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#ifndef __GOKE_CLK_H
+#define __GOKE_CLK_H
+
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+
+struct platform_device;
+
+struct gk_clock_data {
+ struct clk_onecell_data clk_data;
+ void __iomem *base;
+};
+
+struct gk_fixed_rate_clock {
+ unsigned int id;
+ char *name;
+ const char *parent_name;
+ unsigned long flags;
+ unsigned long fixed_rate;
+};
+
+struct gk_fixed_factor_clock {
+ unsigned int id;
+ char *name;
+ const char *parent_name;
+ unsigned long mult;
+ unsigned long div;
+ unsigned long flags;
+};
+
+struct gk_mux_clock {
+ unsigned int id;
+ const char *name;
+ const char *const *parent_names;
+ u8 num_parents;
+ unsigned long flags;
+ unsigned long offset;
+ u8 shift;
+ u8 width;
+ u8 mux_flags;
+ u32 *table;
+ const char *alias;
+};
+
+struct gk_gate_clock {
+ unsigned int id;
+ const char *name;
+ const char *parent_name;
+ unsigned long flags;
+ unsigned long offset;
+ u8 bit_idx;
+ u8 gate_flags;
+ const char *alias;
+};
+
+struct gk_clock_data *gk_clk_init(struct device_node *, int);
+int gk_clk_register_fixed_rate(const struct gk_fixed_rate_clock *,
+ int, struct gk_clock_data *);
+int gk_clk_register_fixed_factor(const struct gk_fixed_factor_clock *,
+ int, struct gk_clock_data *);
+int gk_clk_register_mux(const struct gk_mux_clock *, int,
+ struct gk_clock_data *);
+int gk_clk_register_gate(const struct gk_gate_clock *,
+ int, struct gk_clock_data *);
+
+#define gk_clk_unregister(type) \
+static inline \
+void gk_clk_unregister_##type(const struct gk_##type##_clock *clks, \
+ int nums, struct gk_clock_data *data) \
+{ \
+ struct clk **clocks = data->clk_data.clks; \
+ int i; \
+ for (i = 0; i < nums; i++) { \
+ int id = clks[i].id; \
+ if (clocks[id]) \
+ clk_unregister_##type(clocks[id]); \
+ } \
+}
+
+gk_clk_unregister(fixed_rate)
+gk_clk_unregister(fixed_factor)
+gk_clk_unregister(mux)
+gk_clk_unregister(gate)
+
+#endif /* __GOKE_CLK_H */
diff -urN linux-4.9.37/drivers/clk/goke/Kconfig linux-4.9.y/drivers/clk/goke/Kconfig
--- linux-4.9.37/drivers/clk/goke/Kconfig 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/clk/goke/Kconfig 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,39 @@
+config COMMON_CLK_GK7205V200
+ tristate "GK7205V200 Clock Driver"
+ depends on ARCH_GK7205V200 || COMPILE_TEST
+ select RESET_GOKE
+ default ARCH_GOKE
+ help
+ Build the clock driver for GK7205V200.
+
+config COMMON_CLK_GK7205V300
+ tristate "GK7205V300 Clock Driver"
+ depends on ARCH_GK7205V300 || COMPILE_TEST
+ select RESET_GOKE
+ default ARCH_GOKE
+ help
+ Build the clock driver for GK7205V300.
+
+config COMMON_CLK_GK7202V300
+ tristate "GK7202V300 Clock Driver"
+ depends on ARCH_GK7202V300 || COMPILE_TEST
+ select RESET_GOKE
+ default ARCH_GOKE
+ help
+ Build the clock driver for GK7202V300.
+
+config COMMON_CLK_GK7605V100
+ tristate "GK7605V100 Clock Driver"
+ depends on ARCH_GK7605V100 || COMPILE_TEST
+ select RESET_GOKE
+ default ARCH_GOKE
+ help
+ Build the clock driver for GK7605V100.
+
+config RESET_GOKE
+ bool "Goke Reset Controller Driver"
+ depends on ARCH_GOKE || COMPILE_TEST || ARCH_GOKE
+ select RESET_CONTROLLER
+ help
+ Build reset controller driver for Goke device chipsets.
+
diff -urN linux-4.9.37/drivers/clk/goke/Makefile linux-4.9.y/drivers/clk/goke/Makefile
--- linux-4.9.37/drivers/clk/goke/Makefile 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/clk/goke/Makefile 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,10 @@
+#
+# Goke Clock specific Makefile
+#
+
+obj-y += clk.o
+obj-$(CONFIG_COMMON_CLK_GK7205V200) += clk-gk7205v200.o
+obj-$(CONFIG_COMMON_CLK_GK7205V300) += clk-gk7205v300.o
+obj-$(CONFIG_COMMON_CLK_GK7202V300) += clk-gk7202v300.o
+obj-$(CONFIG_COMMON_CLK_GK7605V100) += clk-gk7605v100.o
+obj-$(CONFIG_RESET_GOKE) += reset.o
diff -urN linux-4.9.37/drivers/clk/goke/reset.c linux-4.9.y/drivers/clk/goke/reset.c
--- linux-4.9.37/drivers/clk/goke/reset.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/clk/goke/reset.c 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include "reset.h"
+
+#define GOKE_RESET_BIT_MASK 0x1f
+#define GOKE_RESET_OFFSET_SHIFT 8
+#define GOKE_RESET_OFFSET_MASK 0xffff00
+
+struct gk_reset_controller {
+ spinlock_t lock;
+ void __iomem *membase;
+ struct reset_controller_dev rcdev;
+};
+
+
+#define to_gk_reset_controller(rcdev) \
+ container_of(rcdev, struct gk_reset_controller, rcdev)
+
+static int gk_reset_of_xlate(struct reset_controller_dev *rcdev,
+ const struct of_phandle_args *reset_spec)
+{
+ u32 offset;
+ u8 bit;
+
+ offset = (reset_spec->args[0] << GOKE_RESET_OFFSET_SHIFT)
+ & GOKE_RESET_OFFSET_MASK;
+ bit = reset_spec->args[1] & GOKE_RESET_BIT_MASK;
+
+ return (offset | bit);
+}
+
+static int gk_reset_assert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct gk_reset_controller *rstc = to_gk_reset_controller(rcdev);
+ unsigned long flags;
+ u32 offset, reg;
+ u8 bit;
+
+ offset = (id & GOKE_RESET_OFFSET_MASK) >> GOKE_RESET_OFFSET_SHIFT;
+ bit = id & GOKE_RESET_BIT_MASK;
+
+ spin_lock_irqsave(&rstc->lock, flags);
+
+ reg = readl(rstc->membase + offset);
+ writel(reg | BIT(bit), rstc->membase + offset);
+
+ spin_unlock_irqrestore(&rstc->lock, flags);
+
+ return 0;
+}
+
+static int gk_reset_deassert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct gk_reset_controller *rstc = to_gk_reset_controller(rcdev);
+ unsigned long flags;
+ u32 offset, reg;
+ u8 bit;
+
+ offset = (id & GOKE_RESET_OFFSET_MASK) >> GOKE_RESET_OFFSET_SHIFT;
+ bit = id & GOKE_RESET_BIT_MASK;
+
+ spin_lock_irqsave(&rstc->lock, flags);
+
+ reg = readl(rstc->membase + offset);
+ writel(reg & ~BIT(bit), rstc->membase + offset);
+
+ spin_unlock_irqrestore(&rstc->lock, flags);
+
+ return 0;
+}
+
+static const struct reset_control_ops gk_reset_ops = {
+ .assert = gk_reset_assert,
+ .deassert = gk_reset_deassert,
+};
+
+int __init gk_reset_init(struct device_node *np,
+ int nr_rsts)
+{
+ struct gk_reset_controller *rstc;
+
+ rstc = kzalloc(sizeof(*rstc), GFP_KERNEL);
+ if (!rstc)
+ return -ENOMEM;
+
+ rstc->membase = of_iomap(np, 0);
+ if (!rstc->membase){
+ kfree(rstc);
+ return -EINVAL;
+ }
+
+ spin_lock_init(&rstc->lock);
+
+ rstc->rcdev.owner = THIS_MODULE;
+ rstc->rcdev.nr_resets = nr_rsts;
+ rstc->rcdev.ops = &gk_reset_ops;
+ rstc->rcdev.of_node = np;
+ rstc->rcdev.of_reset_n_cells = 2;
+ rstc->rcdev.of_xlate = gk_reset_of_xlate;
+
+ return reset_controller_register(&rstc->rcdev);
+}
+EXPORT_SYMBOL_GPL(gk_reset_init);
diff -urN linux-4.9.37/drivers/clk/goke/reset.h linux-4.9.y/drivers/clk/goke/reset.h
--- linux-4.9.37/drivers/clk/goke/reset.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/clk/goke/reset.h 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#ifndef __GOKE_RESET_H
+#define __GOKE_RESET_H
+
+struct device_node;
+struct gk_reset_controller;
+
+#ifdef CONFIG_RESET_CONTROLLER
+int __init gk_reset_init(struct device_node *np, int nr_rsts);
+#endif
+
+#endif /* __GOKE_RESET_H */
diff -urN linux-4.9.37/drivers/clk/Kconfig linux-4.9.y/drivers/clk/Kconfig
--- linux-4.9.37/drivers/clk/Kconfig 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/clk/Kconfig 2021-06-07 13:01:33.000000000 +0300
@@ -210,5 +210,6 @@
source "drivers/clk/tegra/Kconfig"
source "drivers/clk/ti/Kconfig"
source "drivers/clk/uniphier/Kconfig"
+source "drivers/clk/goke/Kconfig"
endmenu
diff -urN linux-4.9.37/drivers/clk/Makefile linux-4.9.y/drivers/clk/Makefile
--- linux-4.9.37/drivers/clk/Makefile 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/clk/Makefile 2021-06-07 13:01:33.000000000 +0300
@@ -92,3 +92,4 @@
endif
obj-$(CONFIG_ARCH_ZX) += zte/
obj-$(CONFIG_ARCH_ZYNQ) += zynq/
+obj-$(CONFIG_ARCH_GOKE) += goke/
\ В конце файла нет новой строки
diff -urN linux-4.9.37/drivers/clocksource/arm_arch_timer.c linux-4.9.y/drivers/clocksource/arm_arch_timer.c
--- linux-4.9.37/drivers/clocksource/arm_arch_timer.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/clocksource/arm_arch_timer.c 2021-06-07 13:01:33.000000000 +0300
@@ -449,7 +449,10 @@
| ARCH_TIMER_USR_PCT_ACCESS_EN);
/* Enable user access to the virtual counter */
- cntkctl |= ARCH_TIMER_USR_VCT_ACCESS_EN;
+ if (IS_ENABLED(CONFIG_ARM_ARCH_TIMER_VCT_ACCESS))
+ cntkctl |= ARCH_TIMER_USR_VCT_ACCESS_EN;
+ else
+ cntkctl &= ~ARCH_TIMER_USR_VCT_ACCESS_EN;
arch_timer_set_cntkctl(cntkctl);
}
diff -urN linux-4.9.37/drivers/clocksource/Kconfig linux-4.9.y/drivers/clocksource/Kconfig
--- linux-4.9.37/drivers/clocksource/Kconfig 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/clocksource/Kconfig 2021-06-07 13:01:33.000000000 +0300
@@ -305,6 +305,14 @@
This must be disabled for hardware validation purposes to detect any
hardware anomalies of missing events.
+config ARM_ARCH_TIMER_VCT_ACCESS
+ bool "Support for ARM architected timer virtual counter access in userspace"
+ default n
+ depends on ARM_ARCH_TIMER
+ help
+ This option enables support for reading the ARM architected timer's
+ virtual counter in userspace.
+
config FSL_ERRATUM_A008585
bool "Workaround for Freescale/NXP Erratum A-008585"
default y
diff -urN linux-4.9.37/drivers/clocksource/timer-sp804.c linux-4.9.y/drivers/clocksource/timer-sp804.c
--- linux-4.9.37/drivers/clocksource/timer-sp804.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/clocksource/timer-sp804.c 2021-06-07 13:01:33.000000000 +0300
@@ -235,6 +235,10 @@
writel(0, base + TIMER_CTRL);
writel(0, base + TIMER_2_BASE + TIMER_CTRL);
+ /* Ensure timer interrupts are clear */
+ writel(1, base + TIMER_INTCLR);
+ writel(1, base + TIMER_2_BASE + TIMER_INTCLR);
+
if (initialized || !of_device_is_available(np)) {
ret = -EINVAL;
goto err;
diff -urN linux-4.9.37/drivers/crypto/qat/qat_common/.gitignore linux-4.9.y/drivers/crypto/qat/qat_common/.gitignore
--- linux-4.9.37/drivers/crypto/qat/qat_common/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/crypto/qat/qat_common/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-*-asn1.[ch]
diff -urN linux-4.9.37/drivers/crypto/vmx/.gitignore linux-4.9.y/drivers/crypto/vmx/.gitignore
--- linux-4.9.37/drivers/crypto/vmx/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/crypto/vmx/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,2 +0,0 @@
-aesp8-ppc.S
-ghashp8-ppc.S
diff -urN linux-4.9.37/drivers/dma/edmac_goke.c linux-4.9.y/drivers/dma/edmac_goke.c
--- linux-4.9.37/drivers/dma/edmac_goke.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/dma/edmac_goke.c 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,1286 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/reset.h>
+#include <linux/platform_device.h>
+#include <linux/device.h>
+#include <linux/dmaengine.h>
+#include <linux/dmapool.h>
+#include <linux/dma-mapping.h>
+#include <linux/export.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_dma.h>
+#include <linux/pm_runtime.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+
+#include "edmac_goke.h"
+#include "dmaengine.h"
+#include "virt-dma.h"
+
+#define DRIVER_NAME "edmac-goke"
+
+int edmac_trace_level = EDMAC_TRACE_LEVEL;
+
+typedef struct edmac_lli {
+ u64 next_lli;
+ u32 reserved[5];
+ u32 count;
+ u64 src_addr;
+ u64 dest_addr;
+ u32 config;
+ u32 pad[3];
+} edmac_lli;
+
+struct edmac_sg {
+ dma_addr_t src_addr;
+ dma_addr_t dst_addr;
+ size_t len;
+ struct list_head node;
+};
+
+struct transfer_desc {
+ struct virt_dma_desc virt_desc;
+
+ dma_addr_t llis_busaddr;
+ u64 *llis_vaddr;
+ u32 ccfg;
+ size_t size;
+ bool done;
+ bool cyclic;
+};
+
+enum edmac_dma_chan_state {
+ EDMAC_CHAN_IDLE,
+ EDMAC_CHAN_RUNNING,
+ EDMAC_CHAN_PAUSED,
+ EDMAC_CHAN_WAITING,
+};
+
+struct edmac_dma_chan {
+ bool slave;
+ int signal;
+ int id;
+ struct virt_dma_chan virt_chan;
+ struct edmac_phy_chan *phychan;
+ struct dma_slave_config cfg;
+ struct transfer_desc *at;
+ struct edmac_driver_data *host;
+ enum edmac_dma_chan_state state;
+};
+
+struct edmac_phy_chan {
+ unsigned int id;
+ void __iomem *base;
+ spinlock_t lock;
+ struct edmac_dma_chan *serving;
+};
+
+struct edmac_driver_data {
+ struct platform_device *dev;
+ struct dma_device slave;
+ struct dma_device memcpy;
+ void __iomem *base;
+ struct regmap *misc_regmap;
+ void __iomem *crg_ctrl;
+ struct edmac_phy_chan *phy_chans;
+ struct dma_pool *pool;
+ unsigned int misc_ctrl_base;
+ int irq;
+ unsigned int id;
+ struct clk *clk;
+ struct clk *axi_clk;
+ struct reset_control *rstc;
+ unsigned int channels;
+ unsigned int slave_requests;
+ unsigned int max_transfer_size;
+};
+
+#ifdef DEBUG_EDMAC
+void dump_lli(u64 *llis_vaddr, unsigned int num)
+{
+
+ edmac_lli *plli = (edmac_lli *)llis_vaddr;
+ unsigned int i;
+
+ edmac_trace(3, "lli num = 0%d\n", num);
+ for (i = 0; i < num; i++) {
+ printk("lli%d:lli_L: 0x%llx\n", i, plli[i].next_lli & 0xffffffff);
+ printk("lli%d:lli_H: 0x%llx\n", i, plli[i].next_lli >> 32 & 0xffffffff);
+ printk("lli%d:count: 0x%llx\n", i, plli[i].count);
+ printk("lli%d:src_addr_L: 0x%llx\n", i, plli[i].src_addr & 0xffffffff);
+ printk("lli%d:src_addr_H: 0x%llx\n", i, plli[i].src_addr >> 32 & 0xffffffff);
+ printk("lli%d:dst_addr_L: 0x%llx\n", i, plli[i].dest_addr & 0xffffffff);
+ printk("lli%d:dst_addr_H: 0x%llx\n", i, plli[i].dest_addr >> 32 & 0xffffffff);
+ printk("lli%d:CONFIG: 0x%llx\n", i, plli[i].config);
+ }
+}
+
+#else
+void dump_lli(u64 *llis_vaddr, unsigned int num)
+{
+}
+#endif
+
+static inline struct edmac_dma_chan *to_edamc_chan(struct dma_chan *chan)
+{
+ return container_of(chan, struct edmac_dma_chan, virt_chan.chan);
+}
+
+static inline struct transfer_desc *to_edmac_transfer_desc(struct dma_async_tx_descriptor *tx)
+{
+ return container_of(tx, struct transfer_desc, virt_desc.tx);
+}
+
+static struct dma_chan *edmac_find_chan_id(struct edmac_driver_data *edmac,
+ int request_num)
+{
+ struct edmac_dma_chan *edmac_dma_chan = NULL;
+
+ list_for_each_entry(edmac_dma_chan, &edmac->slave.channels, virt_chan.chan.device_node) {
+ if (edmac_dma_chan->id == request_num) {
+ return &edmac_dma_chan->virt_chan.chan;
+ }
+ }
+ return NULL;
+}
+
+static struct dma_chan *edma_of_xlate(struct of_phandle_args *dma_spec,
+ struct of_dma *ofdma)
+{
+ struct edmac_driver_data *edmac = ofdma->of_dma_data;
+ struct edmac_dma_chan *edmac_dma_chan = NULL;
+ struct dma_chan *dma_chan = NULL;
+ struct regmap *misc = NULL;
+ unsigned int signal = 0, request_num = 0;
+ unsigned int reg = 0, offset = 0;
+
+ if (!edmac) {
+ return NULL;
+ }
+
+ misc = edmac->misc_regmap;
+
+ if (dma_spec->args_count != 2) {
+ edmac_error("args count not true!\n");
+ return NULL;
+ }
+
+ request_num = dma_spec->args[0];
+ signal = dma_spec->args[1];
+
+ edmac_trace(3, "host->id = %d,signal = %d, request_num = %d\n", edmac->id, signal, request_num);
+
+ if (misc != NULL) {
+#ifdef CONFIG_ACCESS_M7_DEV
+ offset = edmac->misc_ctrl_base;
+ reg = 0xc0;
+ regmap_write(misc, offset, reg);
+#else
+ offset = edmac->misc_ctrl_base + (request_num & (~0x3));
+ regmap_read(misc, offset, &reg);
+ reg &= ~(0x3f << ((request_num & 0x3) << 3));
+ reg |= signal << ((request_num & 0x3) << 3);
+ regmap_write(misc, offset, reg);
+#endif
+ }
+
+ edmac_trace(3, "offset = 0x%x, reg = 0x%x\n", offset, reg);
+
+ dma_chan = edmac_find_chan_id(edmac, request_num);
+ if (!dma_chan) {
+ edmac_error("DMA slave channel is not found!\n");
+ return NULL;
+ }
+
+ edmac_dma_chan = to_edamc_chan(dma_chan);
+ edmac_dma_chan->signal = request_num;
+
+ return dma_get_slave_channel(dma_chan);
+}
+
+
+static int get_of_probe(struct edmac_driver_data *edmac)
+{
+ struct resource *res = NULL;
+ struct platform_device *platdev = edmac->dev;
+ struct device_node *np = platdev->dev.of_node;
+ int ret;
+
+ ret = of_property_read_u32((&platdev->dev)->of_node,
+ "devid", &(edmac->id));
+ if (ret) {
+ edmac_error("get edmac id fail\n");
+ return -ENODEV;
+ }
+
+ edmac->clk = devm_clk_get(&(platdev->dev), "apb_pclk");
+ if (IS_ERR(edmac->clk)) {
+ return PTR_ERR(edmac->clk);
+ }
+
+ edmac->axi_clk = devm_clk_get(&(platdev->dev), "axi_aclk");
+ if (IS_ERR(edmac->axi_clk)) {
+ return PTR_ERR(edmac->axi_clk);
+ }
+
+ edmac->rstc = devm_reset_control_get(&(platdev->dev), "dma-reset");
+ if (IS_ERR(edmac->rstc)) {
+ return PTR_ERR(edmac->rstc);
+ }
+
+ res = platform_get_resource(platdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ edmac_error("no reg resource\n");
+ return -ENODEV;
+ }
+
+ edmac->base = devm_ioremap_resource(&(platdev->dev), res);
+ if (IS_ERR(edmac->base)) {
+ return PTR_ERR(edmac->base);
+ }
+#if defined(CONFIG_ARCH_GK7205V200) || defined(CONFIG_ARCH_GK7205V300) || \
+ defined(CONFIG_ARCH_GK7202V300) || defined(CONFIG_ARCH_GK7605V100)
+ edmac->misc_regmap = 0;
+ (void)np;
+#else
+ edmac->misc_regmap = syscon_regmap_lookup_by_phandle(np, "misc_regmap");
+ if (IS_ERR(edmac->misc_regmap)) {
+ return PTR_ERR(edmac->misc_regmap);
+ }
+
+ ret = of_property_read_u32((&platdev->dev)->of_node,
+ "misc_ctrl_base", &(edmac->misc_ctrl_base));
+ if (ret) {
+ edmac_error( "get dma-misc_ctrl_base fail\n");
+ return -ENODEV;
+ }
+#endif
+ edmac->irq = platform_get_irq(platdev, 0);
+ if (unlikely(edmac->irq < 0)) {
+ return -ENODEV;
+ }
+
+ ret = of_property_read_u32((&platdev->dev)->of_node,
+ "dma-channels", &(edmac->channels));
+ if (ret) {
+ edmac_error( "get dma-channels fail\n");
+ return -ENODEV;
+ }
+ ret = of_property_read_u32((&platdev->dev)->of_node,
+ "dma-requests", &(edmac->slave_requests));
+ if (ret) {
+ edmac_error( "get dma-requests fail\n");
+ return -ENODEV;
+ }
+ edmac_trace(2, "dma-channels = %d, dma-requests = %d\n",
+ edmac->channels, edmac->slave_requests);
+ return of_dma_controller_register(platdev->dev.of_node, edma_of_xlate, edmac);
+}
+
+static void edmac_free_chan_resources(struct dma_chan *chan)
+{
+ vchan_free_chan_resources(to_virt_chan(chan));
+}
+
+static enum dma_status edmac_tx_status(struct dma_chan *chan,
+ dma_cookie_t cookie, struct dma_tx_state *txstate)
+{
+ enum dma_status ret = DMA_COMPLETE;
+ struct edmac_dma_chan *edmac_dma_chan = to_edamc_chan(chan);
+ struct edmac_phy_chan *phychan = edmac_dma_chan->phychan;
+ struct edmac_driver_data *edmac = edmac_dma_chan->host;
+ struct virt_dma_desc *vd = NULL;
+ struct transfer_desc *tsf_desc = NULL;
+ unsigned long flags;
+ size_t bytes = 0;
+ u64 curr_lli = 0, curr_residue_bytes = 0, temp = 0;
+ edmac_lli *plli = NULL;
+ unsigned int i = 0, index = 0;
+
+ ret = dma_cookie_status(chan, cookie, txstate);
+ if (ret == DMA_COMPLETE) {
+ return ret;
+ }
+
+ spin_lock_irqsave(&edmac_dma_chan->virt_chan.lock, flags);
+ vd = vchan_find_desc(&edmac_dma_chan->virt_chan, cookie);
+ if (vd) {
+ /* no been trasfer */
+ tsf_desc = to_edmac_transfer_desc(&vd->tx);
+ bytes = tsf_desc->size;
+ } else {
+ /* trasfering */
+ tsf_desc = edmac_dma_chan->at;
+
+ if (!phychan || !tsf_desc) {
+ spin_unlock_irqrestore(&edmac_dma_chan->virt_chan.lock, flags);
+ goto out;
+ }
+ curr_lli = (edmac_readl(edmac->base + EDMAC_Cx_LLI_L(phychan->id)) & (~(EDMAC_LLI_ALIGN - 1)));
+ curr_lli |= ((u64)(edmac_readl(edmac->base + EDMAC_Cx_LLI_H(phychan->id)) & 0xffffffff) << 32);
+ curr_residue_bytes = edmac_readl(edmac->base + EDMAC_Cx_CURR_CNT0(phychan->id));
+ if (curr_lli == 0) {
+ /* It means non-lli mode */
+ bytes = curr_residue_bytes;
+ } else {
+ /* It means lli mode */
+ index = (curr_lli - tsf_desc->llis_busaddr) / sizeof(edmac_lli) - 1;
+ plli = (edmac_lli *)(tsf_desc->llis_vaddr);
+ for (i = 0; i < index; i++) {
+ temp += plli[i].count;
+ }
+ temp += plli[i].count - curr_residue_bytes;
+ bytes = tsf_desc->size - temp;
+ }
+ }
+ spin_unlock_irqrestore(&edmac_dma_chan->virt_chan.lock, flags);
+
+ dma_set_residue(txstate, bytes);
+
+ if (edmac_dma_chan->state == EDMAC_CHAN_PAUSED && ret == DMA_IN_PROGRESS) {
+ ret = DMA_PAUSED;
+ return ret;
+ }
+
+out:
+ return ret;
+}
+
+static struct edmac_phy_chan *edmac_get_phy_channel(
+ struct edmac_driver_data *edmac,
+ struct edmac_dma_chan *edmac_dma_chan)
+{
+ struct edmac_phy_chan *ch = NULL;
+ unsigned long flags;
+ int i;
+
+ for (i = 0; i < edmac->channels; i++) {
+ ch = &edmac->phy_chans[i];
+
+ spin_lock_irqsave(&ch->lock, flags);
+
+ if (!ch->serving) {
+ ch->serving = edmac_dma_chan;
+ spin_unlock_irqrestore(&ch->lock, flags);
+ break;
+ }
+ spin_unlock_irqrestore(&ch->lock, flags);
+ }
+
+ if (i == edmac->channels) {
+ return NULL;
+ }
+
+ return ch;
+}
+
+static void edmac_write_lli(struct edmac_driver_data *edmac,
+ struct edmac_phy_chan *phychan,
+ struct transfer_desc *tsf_desc)
+{
+
+ edmac_lli *plli = (edmac_lli *)tsf_desc->llis_vaddr;
+
+ if (plli->next_lli != 0x0) {
+ edmac_writel((plli->next_lli & 0xffffffff) | EDMAC_LLI_ENABLE, edmac->base + EDMAC_Cx_LLI_L(phychan->id));
+ } else {
+ edmac_writel((plli->next_lli & 0xffffffff), edmac->base + EDMAC_Cx_LLI_L(phychan->id));
+ }
+
+ edmac_writel(((plli->next_lli >> 32) & 0xffffffff), edmac->base + EDMAC_Cx_LLI_H(phychan->id));
+ edmac_writel(plli->count, edmac->base + EDMAC_Cx_CNT0(phychan->id));
+ edmac_writel(plli->src_addr & 0xffffffff, edmac->base + EDMAC_Cx_SRC_ADDR_L(phychan->id));
+ edmac_writel((plli->src_addr >> 32) & 0xffffffff, edmac->base + EDMAC_Cx_SRC_ADDR_H(phychan->id));
+ edmac_writel(plli->dest_addr & 0xffffffff, edmac->base + EDMAC_Cx_DEST_ADDR_L(phychan->id));
+ edmac_writel((plli->dest_addr >> 32) & 0xffffffff, edmac->base + EDMAC_Cx_DEST_ADDR_H(phychan->id));
+ edmac_writel(plli->config, edmac->base + EDMAC_Cx_CONFIG(phychan->id));
+}
+
+static void edmac_start_next_txd(struct edmac_dma_chan *edmac_dma_chan)
+{
+ struct edmac_driver_data *edmac = edmac_dma_chan->host;
+ struct edmac_phy_chan *phychan = edmac_dma_chan->phychan;
+ struct virt_dma_desc *vd = vchan_next_desc(&edmac_dma_chan->virt_chan);
+ struct transfer_desc *tsf_desc = to_edmac_transfer_desc(&vd->tx);
+ unsigned int val = 0;
+
+ list_del(&tsf_desc->virt_desc.node);
+
+ edmac_dma_chan->at = tsf_desc;
+
+ edmac_write_lli(edmac, phychan, tsf_desc);
+
+ val = edmac_readl(edmac->base + EDMAC_Cx_CONFIG(phychan->id));
+
+ edmac_trace(2, " EDMAC_Cx_CONFIG = 0x%x\n", val);
+ edmac_writel(val | EDMAC_CxCONFIG_LLI_START, edmac->base + EDMAC_Cx_CONFIG(phychan->id));
+}
+
+static void edmac_start(struct edmac_dma_chan * edmac_dma_chan)
+{
+ struct edmac_driver_data *edmac = edmac_dma_chan->host;
+ struct edmac_phy_chan *ch;
+
+ ch = edmac_get_phy_channel(edmac, edmac_dma_chan);
+ if (!ch) {
+ edmac_error("no phy channel available !\n");
+ edmac_dma_chan->state = EDMAC_CHAN_WAITING;
+ return;
+ }
+
+ edmac_dma_chan->phychan = ch;
+ edmac_dma_chan->state = EDMAC_CHAN_RUNNING;
+
+ edmac_start_next_txd(edmac_dma_chan);
+}
+
+static void edmac_issue_pending(struct dma_chan *chan)
+{
+ struct edmac_dma_chan *edmac_dma_chan = to_edamc_chan(chan);
+ unsigned long flags;
+
+ spin_lock_irqsave(&edmac_dma_chan->virt_chan.lock, flags);
+ if (vchan_issue_pending(&edmac_dma_chan->virt_chan)) {
+ if (!edmac_dma_chan->phychan && edmac_dma_chan->state != EDMAC_CHAN_WAITING) {
+ edmac_start(edmac_dma_chan);
+ }
+ }
+ spin_unlock_irqrestore(&edmac_dma_chan->virt_chan.lock, flags);
+}
+
+static void edmac_free_txd_list(struct edmac_dma_chan *edmac_dma_chan)
+{
+ LIST_HEAD(head);
+
+ vchan_get_all_descriptors(&edmac_dma_chan->virt_chan, &head);
+ vchan_dma_desc_free_list(&edmac_dma_chan->virt_chan, &head);
+}
+
+static int edmac_config(struct dma_chan *chan,
+ struct dma_slave_config *config)
+{
+ struct edmac_dma_chan *edmac_dma_chan = to_edamc_chan(chan);
+
+ if (!edmac_dma_chan->slave) {
+ edmac_error("slave is null!");
+ return -EINVAL;
+ }
+
+ edmac_dma_chan->cfg = *config;
+
+ return 0;
+}
+
+static void edmac_pause_phy_chan(struct edmac_dma_chan *edmac_dma_chan)
+{
+ struct edmac_driver_data *edmac = edmac_dma_chan->host;
+ struct edmac_phy_chan *phychan = edmac_dma_chan->phychan;
+ unsigned int val;
+ int timeout;
+
+
+ val = edmac_readl(edmac->base + EDMAC_Cx_CONFIG(phychan->id));
+ val &= ~CCFG_EN;
+ edmac_writel(val, edmac->base + EDMAC_Cx_CONFIG(phychan->id));
+
+ /* Wait for channel inactive */
+ for (timeout = 2000; timeout > 0; timeout--) {
+ if (!(0x1 << phychan->id & edmac_readl(edmac->base + EDMAC_CH_STAT))) {
+ break;
+ }
+ edmac_writel(val, edmac->base + EDMAC_Cx_CONFIG(phychan->id));
+ udelay(1);
+ }
+
+ if (timeout == 0) {
+ edmac_error(":channel%u timeout waiting for pause, timeout:%d\n",
+ phychan->id, timeout);
+ }
+}
+
+static int edmac_pause(struct dma_chan *chan)
+{
+ struct edmac_dma_chan *edmac_dma_chan = to_edamc_chan(chan);
+ unsigned long flags;
+
+ spin_lock_irqsave(&edmac_dma_chan->virt_chan.lock, flags);
+
+ if (!edmac_dma_chan->phychan) {
+ spin_unlock_irqrestore(&edmac_dma_chan->virt_chan.lock, flags);
+ return 0;
+ }
+
+ edmac_pause_phy_chan(edmac_dma_chan);
+ edmac_dma_chan->state = EDMAC_CHAN_PAUSED;
+ spin_unlock_irqrestore(&edmac_dma_chan->virt_chan.lock, flags);
+
+ return 0;
+}
+
+static void edmac_resume_phy_chan(struct edmac_dma_chan *edmac_dma_chan)
+{
+ struct edmac_driver_data *edmac = edmac_dma_chan->host;
+ struct edmac_phy_chan *phychan = edmac_dma_chan->phychan;
+ unsigned int val;
+
+ val = edmac_readl(edmac->base + EDMAC_Cx_CONFIG(phychan->id));
+ val |= CCFG_EN;
+ edmac_writel(val, edmac->base + EDMAC_Cx_CONFIG(phychan->id));
+}
+
+static int edmac_resume(struct dma_chan *chan)
+{
+ struct edmac_dma_chan *edmac_dma_chan = to_edamc_chan(chan);
+ unsigned long flags;
+
+ spin_lock_irqsave(&edmac_dma_chan->virt_chan.lock, flags);
+
+ if (!edmac_dma_chan->phychan) {
+ spin_unlock_irqrestore(&edmac_dma_chan->virt_chan.lock, flags);
+ return 0;
+ }
+
+ edmac_resume_phy_chan(edmac_dma_chan);
+ edmac_dma_chan->state = EDMAC_CHAN_RUNNING;
+ spin_unlock_irqrestore(&edmac_dma_chan->virt_chan.lock, flags);
+
+ return 0;
+}
+
+void edmac_phy_free(struct edmac_dma_chan *chan);
+static void edmac_desc_free(struct virt_dma_desc *vd);
+static int edmac_terminate_all(struct dma_chan *chan)
+{
+ struct edmac_dma_chan *edmac_dma_chan = to_edamc_chan(chan);
+ unsigned long flags;
+
+ spin_lock_irqsave(&edmac_dma_chan->virt_chan.lock, flags);
+ if (!edmac_dma_chan->phychan && !edmac_dma_chan->at) {
+ spin_unlock_irqrestore(&edmac_dma_chan->virt_chan.lock, flags);
+ return 0;
+ }
+
+ edmac_dma_chan->state = EDMAC_CHAN_IDLE;
+
+ if (edmac_dma_chan->phychan) {
+ edmac_phy_free(edmac_dma_chan);
+ }
+
+ if (edmac_dma_chan->at) {
+ edmac_desc_free(&edmac_dma_chan->at->virt_desc);
+ edmac_dma_chan->at = NULL;
+ }
+ edmac_free_txd_list(edmac_dma_chan);
+
+ spin_unlock_irqrestore(&edmac_dma_chan->virt_chan.lock, flags);
+
+ return 0;
+}
+
+static struct transfer_desc *edmac_get_tsf_desc(struct edmac_driver_data *plchan)
+{
+ struct transfer_desc *tsf_desc = kzalloc(sizeof(struct transfer_desc), GFP_NOWAIT);
+
+ if (tsf_desc) {
+ tsf_desc->ccfg = 0;
+ }
+
+ return tsf_desc;
+}
+
+static void edmac_free_tsf_desc(struct edmac_driver_data *edmac,
+ struct transfer_desc *tsf_desc)
+{
+ if (tsf_desc->llis_vaddr) {
+ dma_pool_free(edmac->pool, tsf_desc->llis_vaddr, tsf_desc->llis_busaddr);
+ }
+
+ kfree(tsf_desc);
+}
+
+static u32 get_width(enum dma_slave_buswidth width)
+{
+ switch (width) {
+ case DMA_SLAVE_BUSWIDTH_1_BYTE:
+ return EDMAC_WIDTH_8BIT;
+ case DMA_SLAVE_BUSWIDTH_2_BYTES:
+ return EDMAC_WIDTH_16BIT;
+ case DMA_SLAVE_BUSWIDTH_4_BYTES:
+ return EDMAC_WIDTH_32BIT;
+ case DMA_SLAVE_BUSWIDTH_8_BYTES:
+ return EDMAC_WIDTH_64BIT;
+ default:
+ edmac_error("check here, width warning!\n");
+ return ~0;
+ }
+}
+
+struct transfer_desc *edmac_init_tsf_desc (
+ struct dma_chan *chan,
+ enum dma_transfer_direction direction,
+ dma_addr_t *slave_addr)
+{
+ struct edmac_dma_chan *edmac_dma_chan = to_edamc_chan(chan);
+ struct edmac_driver_data *edmac = edmac_dma_chan->host;
+ struct transfer_desc *tsf_desc;
+ unsigned int config = 0, burst = 0;
+ unsigned int addr_width = 0, maxburst = 0;
+ unsigned int width = 0;
+
+ tsf_desc = edmac_get_tsf_desc(edmac);
+ if (!tsf_desc) {
+ edmac_error("get tsf desc fail!\n");
+ return NULL;
+ }
+
+ if (direction == DMA_MEM_TO_DEV) {
+ config = EDMAC_CONFIG_SRC_INC;
+ *slave_addr = edmac_dma_chan->cfg.dst_addr;
+ addr_width = edmac_dma_chan->cfg.dst_addr_width;
+ maxburst = edmac_dma_chan->cfg.dst_maxburst;
+ } else if (direction == DMA_DEV_TO_MEM) {
+ config = EDMAC_CONFIG_DST_INC;
+ *slave_addr = edmac_dma_chan->cfg.src_addr;
+ addr_width = edmac_dma_chan->cfg.src_addr_width;
+ maxburst = edmac_dma_chan->cfg.src_maxburst;
+ } else {
+ edmac_free_tsf_desc(edmac, tsf_desc);
+ edmac_error("direction unsupported!\n");
+ return NULL;
+ }
+
+ edmac_trace(3, "addr_width = 0x%x\n", addr_width);
+ width = get_width(addr_width);
+ edmac_trace(3, "width = 0x%x\n", width);
+ config |= width << EDMAC_CONFIG_SRC_WIDTH_SHIFT;
+ config |= width << EDMAC_CONFIG_DST_WIDTH_SHIFT;
+ edmac_trace(2, "tsf_desc->ccfg = 0x%x\n", config);
+
+ edmac_trace(3, "maxburst = 0x%x\n", maxburst);
+ if (maxburst > (EDMAC_MAX_BURST_WIDTH)) {
+ burst |= (EDMAC_MAX_BURST_WIDTH - 1);
+ } else if (maxburst == 0) {
+ burst |= EDMAC_MIN_BURST_WIDTH;
+ } else {
+ burst |= (maxburst - 1);
+ }
+ edmac_trace(3, "burst = 0x%x\n", burst);
+ config |= burst << EDMAC_CONFIG_SRC_BURST_SHIFT;
+ config |= burst << EDMAC_CONFIG_DST_BURST_SHIFT;
+
+ if (edmac_dma_chan->signal >= 0) {
+ edmac_trace(2, "edmac_dma_chan->signal = %d\n", edmac_dma_chan->signal);
+ config |= (unsigned int)edmac_dma_chan->signal << EDMAC_CXCONFIG_SIGNAL_SHIFT;
+ }
+
+ config |= EDMAC_CXCONFIG_DEV_MEM_TYPE << EDMAC_CXCONFIG_TSF_TYPE_SHIFT;
+ tsf_desc->ccfg = config;
+ edmac_trace(2, "tsf_desc->ccfg = 0x%x\n", tsf_desc->ccfg);
+
+ return tsf_desc;
+}
+
+static void edmac_fill_desc(struct transfer_desc *tsf_desc, dma_addr_t src,
+ dma_addr_t dst, unsigned int length, unsigned int num)
+{
+ edmac_lli *plli;
+
+ plli = (edmac_lli *)(tsf_desc->llis_vaddr);
+ memset(&plli[num], 0x0, sizeof(edmac_lli));
+
+ plli[num].src_addr = src;
+ plli[num].dest_addr = dst;
+ plli[num].config = tsf_desc->ccfg;
+ plli[num].count = length;
+ tsf_desc->size += length;
+
+ if (num > 0) {
+ plli[num - 1].next_lli = (tsf_desc->llis_busaddr + (num) * sizeof(edmac_lli)) & (~(EDMAC_LLI_ALIGN - 1));
+ plli[num - 1].next_lli |= EDMAC_LLI_ENABLE;
+ }
+}
+
+static struct dma_async_tx_descriptor *edmac_perp_slave_sg(
+ struct dma_chan *chan, struct scatterlist *sgl,
+ unsigned int sg_len, enum dma_transfer_direction direction,
+ unsigned long flags, void *context)
+{
+ struct edmac_dma_chan *edmac_dma_chan = to_edamc_chan(chan);
+ struct edmac_driver_data *edmac = edmac_dma_chan->host;
+ struct transfer_desc *tsf_desc = NULL;
+ struct scatterlist *sg = NULL;
+ int tmp = 0;
+ dma_addr_t src = 0, dst = 0, addr = 0, slave_addr = 0;
+ unsigned int length = 0, num = 0;
+
+ edmac_lli *last_plli = NULL;
+
+ if (sgl == NULL) {
+ edmac_error("sgl is null!\n");
+ return NULL;
+ }
+
+ tsf_desc = edmac_init_tsf_desc(chan, direction, &slave_addr);
+ if (!tsf_desc) {
+ edmac_error("desc init fail\n");
+ return NULL;
+ }
+
+ tsf_desc->llis_vaddr = dma_pool_alloc(edmac->pool, GFP_NOWAIT, &tsf_desc->llis_busaddr);
+ if (!tsf_desc->llis_vaddr) {
+ edmac_free_tsf_desc(edmac, tsf_desc);
+ edmac_error("malloc memory from pool fail !\n");
+ return 0;
+ }
+
+ for_each_sg(sgl, sg, sg_len, tmp) {
+ addr = sg_dma_address(sg);
+ length = sg_dma_len(sg);
+ if (direction == DMA_MEM_TO_DEV) {
+ src = addr;
+ dst = slave_addr;
+ } else if (direction == DMA_DEV_TO_MEM) {
+ src = slave_addr;
+ dst = addr;
+ }
+ edmac_fill_desc(tsf_desc, src, dst, length, num);
+ num++;
+ }
+
+ last_plli = (edmac_lli *)((unsigned long)tsf_desc->llis_vaddr + (num - 1) * sizeof(edmac_lli));
+ last_plli->next_lli |= EDMAC_LLI_DISABLE;
+ dump_lli(tsf_desc->llis_vaddr, num);
+
+ return vchan_tx_prep(&edmac_dma_chan->virt_chan, &tsf_desc->virt_desc, flags);
+}
+
+static struct dma_async_tx_descriptor *edmac_prep_dma_memcpy(
+ struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
+ size_t len, unsigned long flags)
+{
+ struct edmac_dma_chan *edmac_dma_chan = to_edamc_chan(chan);
+ struct edmac_driver_data *edmac = edmac_dma_chan->host;
+ struct transfer_desc *tsf_desc = NULL;
+ u32 config = 0;
+ size_t num = 0;
+ size_t length = 0;
+ edmac_lli *last_plli = NULL;
+
+ if (!len) {
+ return NULL;
+ }
+
+ tsf_desc = edmac_get_tsf_desc(edmac);
+ if (!tsf_desc) {
+ edmac_error("get tsf desc fail!\n");
+ return NULL;
+ }
+
+ tsf_desc->llis_vaddr = dma_pool_alloc(edmac->pool, GFP_NOWAIT, &tsf_desc->llis_busaddr);
+ if (!tsf_desc->llis_vaddr) {
+ edmac_free_tsf_desc(edmac, tsf_desc);
+ edmac_error("malloc memory from pool fail !\n");
+ return 0;
+ }
+
+ config |= EDMAC_CONFIG_SRC_INC | EDMAC_CONFIG_DST_INC;
+ config |= EDMAC_CXCONFIG_MEM_TYPE << EDMAC_CXCONFIG_TSF_TYPE_SHIFT;
+
+ /* max burst width is 16 ,but reg value set 0xf */
+ config |= (EDMAC_MAX_BURST_WIDTH - 1) << EDMAC_CONFIG_SRC_BURST_SHIFT;
+ config |= (EDMAC_MAX_BURST_WIDTH - 1) << EDMAC_CONFIG_DST_BURST_SHIFT;
+
+ tsf_desc->ccfg = config;
+
+ do {
+ length = min_t(size_t, len, MAX_TRANSFER_BYTES);
+ edmac_fill_desc(tsf_desc, src, dest, length, num);
+
+ src += length;
+ dest += length;
+ len -= length;
+ num++;
+ } while(len);
+
+ last_plli = (edmac_lli *)((unsigned long)tsf_desc->llis_vaddr + (num - 1) * sizeof(edmac_lli));
+ last_plli->next_lli |= EDMAC_LLI_DISABLE;
+ dump_lli(tsf_desc->llis_vaddr, num);
+
+ return vchan_tx_prep(&edmac_dma_chan->virt_chan, &tsf_desc->virt_desc, flags);
+}
+
+
+
+static struct dma_async_tx_descriptor *edma_prep_dma_cyclic(
+ struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
+ size_t period_len, enum dma_transfer_direction direction,
+ unsigned long flags)
+{
+ struct edmac_dma_chan *edmac_dma_chan = to_edamc_chan(chan);
+ struct edmac_driver_data *edmac = edmac_dma_chan->host;
+ struct transfer_desc *tsf_desc;
+ dma_addr_t src = 0, dst = 0, addr = 0, slave_addr = 0;
+ size_t length = 0, since = 0, total = 0, num = 0, len = 0;
+ edmac_lli *last_plli = NULL;
+ edmac_lli *plli = NULL;
+
+ tsf_desc = edmac_init_tsf_desc(chan, direction, &slave_addr);
+ if (!tsf_desc) {
+ edmac_error("desc init fail\n");
+ return NULL;
+ }
+
+ tsf_desc->llis_vaddr = dma_pool_alloc(edmac->pool, GFP_NOWAIT, &tsf_desc->llis_busaddr);
+ if (!tsf_desc->llis_vaddr) {
+ edmac_free_tsf_desc(edmac, tsf_desc);
+ edmac_error("malloc memory from pool fail !\n");
+ return 0;
+ }
+
+ tsf_desc->cyclic = true;
+ addr = buf_addr;
+ total = buf_len;
+
+ if (period_len < MAX_TRANSFER_BYTES) {
+ len = period_len;
+ }
+ do {
+ length = min_t(size_t, total, len);
+
+ if (direction == DMA_MEM_TO_DEV) {
+ src = addr;
+ dst = slave_addr;
+ } else if (direction == DMA_DEV_TO_MEM) {
+ src = slave_addr;
+ dst = addr;
+ }
+
+ edmac_fill_desc(tsf_desc, src, dst, length, num);
+
+ since += length;
+ if (since >= period_len) {
+ plli = (edmac_lli *)((unsigned long)tsf_desc->llis_vaddr + (num) * sizeof(edmac_lli));
+ plli->config |= EDMAC_CXCONFIG_ITC_EN << EDMAC_CXCONFIG_ITC_EN_SHIFT;
+ since -= period_len;
+ }
+ addr += length;
+ total -= length;
+ num++;
+ } while(total);
+
+ last_plli = (edmac_lli *)((unsigned long)tsf_desc->llis_vaddr + (num - 1) * sizeof(edmac_lli));
+
+ last_plli->next_lli = (unsigned long)(tsf_desc->llis_vaddr);
+
+ dump_lli(tsf_desc->llis_vaddr, num);
+
+ return vchan_tx_prep(&edmac_dma_chan->virt_chan, &tsf_desc->virt_desc, flags);
+}
+
+
+static void edmac_phy_reassign(struct edmac_phy_chan *phy_chan,
+ struct edmac_dma_chan *chan)
+{
+ phy_chan->serving = chan;
+ chan->phychan = phy_chan;
+ chan->state = EDMAC_CHAN_RUNNING;
+
+ edmac_start_next_txd(chan);
+}
+
+static void edmac_terminate_phy_chan(struct edmac_driver_data *edmac,
+ struct edmac_dma_chan *edmac_dma_chan)
+{
+ unsigned int val;
+ struct edmac_phy_chan *phychan = edmac_dma_chan->phychan;
+
+ edmac_pause_phy_chan(edmac_dma_chan);
+
+ val = 0x1 << phychan->id;
+
+ edmac_writel(val, edmac->base + EDMAC_INT_TC1_RAW);
+ edmac_writel(val, edmac->base + EDMAC_INT_ERR1_RAW);
+ edmac_writel(val, edmac->base + EDMAC_INT_ERR2_RAW);
+}
+
+void edmac_phy_free(struct edmac_dma_chan *chan)
+{
+ struct edmac_driver_data *edmac = chan->host;
+ struct edmac_dma_chan *p = NULL;
+ struct edmac_dma_chan *next = NULL;
+
+ list_for_each_entry(p, &edmac->memcpy.channels, virt_chan.chan.device_node) {
+ if (p->state == EDMAC_CHAN_WAITING) {
+ next = p;
+ break;
+ }
+ }
+
+ if (!next) {
+ list_for_each_entry(p, &edmac->slave.channels, virt_chan.chan.device_node) {
+ if (p->state == EDMAC_CHAN_WAITING) {
+ next = p;
+ break;
+ }
+ }
+ }
+ edmac_terminate_phy_chan(edmac, chan);
+
+ if (next) {
+ spin_lock(&next->virt_chan.lock);
+ edmac_phy_reassign(chan->phychan, next);
+ spin_unlock(&next->virt_chan.lock);
+ } else {
+ chan->phychan->serving = NULL;
+ }
+
+ chan->phychan = NULL;
+ chan->state = EDMAC_CHAN_IDLE;
+}
+
+static irqreturn_t edmac_irq(int irq, void *dev)
+{
+ struct edmac_driver_data *edmac = (struct edmac_driver_data *)dev;
+ struct edmac_dma_chan *chan = NULL;
+ struct edmac_phy_chan *phy_chan = NULL;
+ struct transfer_desc * tsf_desc = NULL;
+
+ u32 mask = 0;
+ unsigned int channel_err_status[3];
+ unsigned int channel_status = 0;
+ unsigned int temp = 0;
+ unsigned int channel_tc_status = -1;
+ unsigned int i = 0;
+
+ channel_status = edmac_readl(edmac->base + EDMAC_INT_STAT);
+
+ if (!channel_status) {
+ edmac_error("channel_status = 0x%x\n", channel_status);
+ return IRQ_NONE;
+ }
+
+ for (i = 0; i < edmac->channels; i++) {
+ temp = (channel_status >> i) & 0x1;
+ if (temp) {
+ phy_chan = &edmac->phy_chans[i];
+ chan = phy_chan->serving;
+ if (!chan) {
+ edmac_error("error interrupt on chan: %d!\n", i);
+ continue;
+ }
+ tsf_desc = chan->at;
+
+ channel_tc_status = edmac_readl(edmac->base + EDMAC_INT_TC1_RAW);
+ channel_tc_status = (channel_tc_status >> i) & 0x01;
+ if (channel_tc_status) {
+ edmac_writel(channel_tc_status << i, edmac->base + EDMAC_INT_TC1_RAW);
+ }
+
+ channel_tc_status = edmac_readl(edmac->base + EDMAC_INT_TC2);
+ channel_tc_status = (channel_tc_status >> i) & 0x01;
+ if (channel_tc_status) {
+ edmac_writel(channel_tc_status << i, edmac->base + EDMAC_INT_TC2_RAW);
+ }
+
+ channel_err_status[0] = edmac_readl(edmac->base + EDMAC_INT_ERR1);
+ channel_err_status[0] = (channel_err_status[0] >> i) & 0x01;
+ channel_err_status[1] = edmac_readl(edmac->base + EDMAC_INT_ERR2);
+ channel_err_status[1] = (channel_err_status[1] >> i) & 0x01;
+ channel_err_status[2] = edmac_readl(edmac->base + EDMAC_INT_ERR3);
+ channel_err_status[2] = (channel_err_status[2] >> i) & 0x01;
+ if (channel_err_status[0] | channel_err_status[1] | channel_err_status[2]) {
+ edmac_error("Error in edmac %d finish!,ERR1 = 0x%x,ERR2 = 0x%x,ERR3 = 0x%x\n",
+ i, channel_err_status[0], channel_err_status[1], channel_err_status[2]);
+ edmac_writel(1 << i, edmac->base + EDMAC_INT_ERR1_RAW);
+ edmac_writel(1 << i, edmac->base + EDMAC_INT_ERR2_RAW);
+ edmac_writel(1 << i, edmac->base + EDMAC_INT_ERR3_RAW);
+ }
+
+ spin_lock(&chan->virt_chan.lock);
+
+ if (tsf_desc->cyclic) {
+ vchan_cyclic_callback(&tsf_desc->virt_desc);
+ spin_unlock(&chan->virt_chan.lock);
+ continue;
+ }
+ chan->at = NULL;
+ tsf_desc->done = true;
+ vchan_cookie_complete(&tsf_desc->virt_desc);
+
+ if (vchan_next_desc(&chan->virt_chan)) {
+ edmac_start_next_txd(chan);
+ } else {
+ edmac_phy_free(chan);
+ }
+
+ spin_unlock(&chan->virt_chan.lock);
+ mask |= (1 << i);
+ }
+ }
+
+ return mask ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static void edmac_dma_slave_init(struct edmac_dma_chan *chan)
+{
+ chan->slave = true;
+}
+
+static void edmac_desc_free(struct virt_dma_desc *vd)
+{
+ struct transfer_desc *tsf_desc = to_edmac_transfer_desc(&vd->tx);
+ struct edmac_dma_chan * edmac_dma_chan = to_edamc_chan(vd->tx.chan);
+
+ dma_descriptor_unmap(&vd->tx);
+ edmac_free_tsf_desc(edmac_dma_chan->host, tsf_desc);
+}
+
+static int edmac_init_virt_channels(struct edmac_driver_data *edmac,
+ struct dma_device *dmadev, unsigned int channels, bool slave)
+{
+ struct edmac_dma_chan *chan = NULL;
+ int i;
+ INIT_LIST_HEAD(&dmadev->channels);
+
+ for (i = 0; i < channels; i++) {
+ chan = kzalloc(sizeof(struct edmac_dma_chan), GFP_KERNEL);
+ if (!chan) {
+ edmac_error("fail to allocate memory for virt channels!");
+ return -1;
+ }
+
+ chan->host = edmac;
+ chan->state = EDMAC_CHAN_IDLE;
+ chan->signal = -1;
+
+ if (slave) {
+ chan->id = i;
+ edmac_dma_slave_init(chan);
+ }
+ chan->virt_chan.desc_free = edmac_desc_free;
+ vchan_init(&chan->virt_chan, dmadev);
+ }
+ return 0;
+}
+
+void edmac_free_virt_channels(struct dma_device *dmadev)
+{
+ struct edmac_dma_chan *chan = NULL;
+ struct edmac_dma_chan *next = NULL;
+
+ list_for_each_entry_safe(chan,
+ next, &dmadev->channels, virt_chan.chan.device_node) {
+ list_del(&chan->virt_chan.chan.device_node);
+ kfree(chan);
+ }
+}
+
+
+#define MAX_TSFR_LLIS 32
+#define EDMACV300_LLI_WORDS 16
+#define EDMACV300_POOL_ALIGN 16
+
+static int __init edmac_probe(struct platform_device *pdev)
+{
+
+ int ret = 0, i = 0;
+ struct edmac_driver_data *edmac = NULL;
+ size_t trasfer_size = 0;
+
+ ret = dma_set_mask_and_coherent(&(pdev->dev), DMA_BIT_MASK(64));
+ if (ret) {
+ return ret;
+ }
+
+ edmac = kzalloc(sizeof(*edmac), GFP_KERNEL);
+ if (!edmac) {
+ edmac_error("malloc for edmac fail!");
+ ret = -ENOMEM;
+ return ret;
+ }
+ edmac->dev = pdev;
+
+ ret = get_of_probe(edmac);
+ if (ret) {
+ edmac_error("get dts info fail!");
+ goto free_edmac;
+ }
+
+
+ clk_prepare_enable(edmac->clk);
+ clk_prepare_enable(edmac->axi_clk);
+
+ reset_control_deassert(edmac->rstc);
+
+ dma_cap_set(DMA_MEMCPY, edmac->memcpy.cap_mask);
+ edmac->memcpy.dev = &pdev->dev;
+ edmac->memcpy.device_free_chan_resources = edmac_free_chan_resources;
+ edmac->memcpy.device_prep_dma_memcpy = edmac_prep_dma_memcpy;
+ edmac->memcpy.device_tx_status = edmac_tx_status;
+ edmac->memcpy.device_issue_pending = edmac_issue_pending;
+ edmac->memcpy.device_config = edmac_config;
+ edmac->memcpy.device_pause = edmac_pause;
+ edmac->memcpy.device_resume = edmac_resume;
+ edmac->memcpy.device_terminate_all = edmac_terminate_all;
+ edmac->memcpy.directions = BIT(DMA_MEM_TO_MEM);
+ edmac->memcpy.residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT;
+
+ dma_cap_set(DMA_SLAVE, edmac->slave.cap_mask);
+ dma_cap_set(DMA_CYCLIC, edmac->slave.cap_mask);
+ edmac->slave.dev = &pdev->dev;
+ edmac->slave.device_free_chan_resources = edmac_free_chan_resources;
+ edmac->slave.device_tx_status = edmac_tx_status;
+ edmac->slave.device_issue_pending = edmac_issue_pending;
+ edmac->slave.device_prep_slave_sg = edmac_perp_slave_sg;
+ edmac->slave.device_prep_dma_cyclic = edma_prep_dma_cyclic;
+ edmac->slave.device_config = edmac_config;
+ edmac->slave.device_resume = edmac_resume;
+ edmac->slave.device_pause = edmac_pause;
+ edmac->slave.device_terminate_all = edmac_terminate_all;
+ edmac->slave.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
+ edmac->slave.residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT;
+
+ edmac->max_transfer_size = MAX_TRANSFER_BYTES;
+ trasfer_size = MAX_TSFR_LLIS * EDMACV300_LLI_WORDS * sizeof(u32);
+
+ edmac->pool = dma_pool_create(DRIVER_NAME, &(pdev->dev),
+ trasfer_size, EDMACV300_POOL_ALIGN, 0);
+ if (!edmac->pool) {
+ edmac_error("create pool fail!");
+ ret = -ENOMEM;
+ goto free_edmac;
+ }
+
+ edmac_writel(EDMAC_ALL_CHAN_CLR, edmac->base + EDMAC_INT_TC1_RAW);
+ edmac_writel(EDMAC_ALL_CHAN_CLR, edmac->base + EDMAC_INT_TC2_RAW);
+ edmac_writel(EDMAC_ALL_CHAN_CLR, edmac->base + EDMAC_INT_ERR1_RAW);
+ edmac_writel(EDMAC_ALL_CHAN_CLR, edmac->base + EDMAC_INT_ERR2_RAW);
+ edmac_writel(EDMAC_ALL_CHAN_CLR, edmac->base + EDMAC_INT_ERR3_RAW);
+
+ edmac_writel(EDMAC_INT_ENABLE_ALL_CHAN, edmac->base + EDMAC_INT_TC1_MASK);
+ edmac_writel(EDMAC_INT_ENABLE_ALL_CHAN, edmac->base + EDMAC_INT_TC2_MASK);
+ edmac_writel(EDMAC_INT_ENABLE_ALL_CHAN, edmac->base + EDMAC_INT_ERR1_MASK);
+ edmac_writel(EDMAC_INT_ENABLE_ALL_CHAN, edmac->base + EDMAC_INT_ERR2_MASK);
+ edmac_writel(EDMAC_INT_ENABLE_ALL_CHAN, edmac->base + EDMAC_INT_ERR3_MASK);
+
+ ret = request_irq(edmac->irq, edmac_irq, 0, DRIVER_NAME, edmac);
+ if (ret) {
+ edmac_error("fail to request irq");
+ goto free_pool;
+ }
+
+ edmac->phy_chans = kzalloc((edmac->channels * sizeof(struct edmac_phy_chan)),
+ GFP_KERNEL);
+ if (!edmac->phy_chans) {
+ edmac_error("malloc for phy chans fail!");
+ ret = -ENOMEM;
+ goto free_irq_res;
+ }
+
+ /* initialize the phy chan */
+ for (i = 0; i < edmac->channels; i++) {
+ struct edmac_phy_chan* phy_ch = &edmac->phy_chans[i];
+ phy_ch->id = i;
+ phy_ch->base = edmac->base + EDMAC_Cx_BASE(i);
+ spin_lock_init(&phy_ch->lock);
+ phy_ch->serving = NULL;
+ }
+
+ /* initialize the memory virt chan */
+ ret = edmac_init_virt_channels(edmac, &edmac->memcpy, edmac->channels, false);
+ if (ret) {
+ edmac_error("fail to init memory virt channels!");
+ goto free_phychans;
+ }
+
+ /* initialize the slave virt chan */
+ ret = edmac_init_virt_channels(edmac, &edmac->slave, edmac->slave_requests, true);
+ if (ret) {
+ edmac_error("fail to init slave virt channels!");
+ goto free_memory_virt_channels;
+
+ }
+
+ ret = dma_async_device_register(&edmac->memcpy);
+ if (ret) {
+ edmac_error(
+ "%s failed to register memcpy as an async device - %d\n",
+ __func__, ret);
+ goto free_slave_virt_channels;
+ }
+
+ ret = dma_async_device_register(&edmac->slave);
+ if (ret) {
+ edmac_error(
+ "%s failed to register slave as an async device - %d\n",
+ __func__, ret);
+ goto free_memcpy_device;
+ }
+
+ return 0;
+
+free_memcpy_device:
+ dma_async_device_unregister(&edmac->memcpy);
+free_slave_virt_channels:
+ edmac_free_virt_channels(&edmac->slave);
+free_memory_virt_channels:
+ edmac_free_virt_channels(&edmac->memcpy);
+free_phychans:
+ kfree(edmac->phy_chans);
+free_irq_res:
+ free_irq(edmac->irq, edmac);
+free_pool:
+ dma_pool_destroy(edmac->pool);
+free_edmac:
+ kfree(edmac);
+
+ return ret;
+}
+
+
+static int edma_remove(struct platform_device *pdev)
+{
+ int err = 0;
+ return err;
+}
+
+
+static const struct of_device_id edmac_match[] = {
+ { .compatible = "goke,edmac" },
+ {},
+};
+
+
+static struct platform_driver edmac_driver = {
+ .remove = edma_remove,
+ .driver = {
+ .name = "edmac",
+ .of_match_table = edmac_match,
+ },
+};
+
+static int __init edmac_init(void)
+{
+ return platform_driver_probe(&edmac_driver, edmac_probe);
+}
+subsys_initcall(edmac_init);
+
+static void __exit edmac_exit(void)
+{
+ platform_driver_unregister(&edmac_driver);
+}
+module_exit(edmac_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Goke");
diff -urN linux-4.9.37/drivers/dma/edmac_goke.h linux-4.9.y/drivers/dma/edmac_goke.h
--- linux-4.9.37/drivers/dma/edmac_goke.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/dma/edmac_goke.h 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#ifndef __EDMAC_H__
+#define __EDMAC_H__
+
+/* debug control */
+extern int edmac_trace_level;
+#define EDMAC_TRACE_LEVEL 5
+
+#define EDMAC_TRACE_FMT KERN_INFO
+
+//#define DEBUG_EDMAC
+#ifdef DEBUG_EDMAC
+
+#define edmac_trace(level, msg...) do { \
+ if ((level) >= edmac_trace_level) { \
+ printk(EDMAC_TRACE_FMT"%s:%d: ", __func__, __LINE__); \
+ printk(msg); \
+ printk("\n"); \
+ } \
+} while (0)
+
+
+#define edmac_assert(cond) do { \
+ if (!(cond)) { \
+ printk(KERN_ERR "Assert:edmac:%s:%d\n", \
+ __func__, \
+ __LINE__); \
+ BUG(); \
+ } \
+} while (0)
+
+#define edmac_error(s...) do { \
+ printk(KERN_ERR "edmac:%s:%d: ", __func__, __LINE__); \
+ printk(s); \
+ printk("\n"); \
+} while (0)
+
+#else
+
+#define edmac_trace(level, msg...) do { } while (0)
+#define edmac_assert(level, msg...) do { } while (0)
+#define edmac_error(level, msg...) do { } while (0)
+
+#endif
+
+#define edmac_readl(addr) ({ unsigned int reg = readl((void *)(addr)); \
+ reg; })
+
+#define edmac_writel(v, addr) do { writel(v, (void *)(addr)); \
+} while (0)
+
+
+#define MAX_TRANSFER_BYTES 0xffff
+
+/* reg offset */
+#define EDMAC_INT_STAT (0x0)
+#define EDMAC_INT_TC1 (0x4)
+#define EDMAC_INT_TC2 (0x8)
+#define EDMAC_INT_ERR1 (0xc)
+#define EDMAC_INT_ERR2 (0x10)
+#define EDMAC_INT_ERR3 (0x14)
+
+#define EDMAC_INT_TC1_MASK (0x18)
+#define EDMAC_INT_TC2_MASK (0x1c)
+#define EDMAC_INT_ERR1_MASK (0x20)
+#define EDMAC_INT_ERR2_MASK (0x24)
+#define EDMAC_INT_ERR3_MASK (0x28)
+
+#define EDMAC_INT_TC1_RAW (0x600)
+#define EDMAC_INT_TC2_RAW (0x608)
+#define EDMAC_INT_ERR1_RAW (0x610)
+#define EDMAC_INT_ERR2_RAW (0x618)
+#define EDMAC_INT_ERR3_RAW (0x620)
+
+#define EDMAC_Cx_CURR_CNT0(cn) (0x404+cn*0x20)
+#define EDMAC_Cx_CURR_SRC_ADDR_L(cn) (0x408+cn*0x20)
+#define EDMAC_Cx_CURR_SRC_ADDR_H(cn) (0x40c+cn*0x20)
+#define EDMAC_Cx_CURR_DEST_ADDR_L(cn) (0x410+cn*0x20)
+#define EDMAC_Cx_CURR_DEST_ADDR_H(cn) (0x414+cn*0x20)
+
+#define EDMAC_CH_PRI (0x688)
+#define EDMAC_CH_STAT (0x690)
+#define EDMAC_DMA_CTRL (0x698)
+
+#define EDMAC_Cx_BASE(cn) (0x800+cn*0x40)
+#define EDMAC_Cx_LLI_L(cn) (0x800+cn*0x40)
+#define EDMAC_Cx_LLI_H(cn) (0x804+cn*0x40)
+#define EDMAC_Cx_CNT0(cn) (0x81c+cn*0x40)
+#define EDMAC_Cx_SRC_ADDR_L(cn) (0x820+cn*0x40)
+#define EDMAC_Cx_SRC_ADDR_H(cn) (0x824+cn*0x40)
+#define EDMAC_Cx_DEST_ADDR_L(cn) (0x828+cn*0x40)
+#define EDMAC_Cx_DEST_ADDR_H(cn) (0x82c+cn*0x40)
+#define EDMAC_Cx_CONFIG(cn) (0x830+cn*0x40)
+
+#define EDMAC_ALL_CHAN_CLR (0xff)
+#define EDMAC_INT_ENABLE_ALL_CHAN (0xff)
+
+
+#define EDMAC_CONFIG_SRC_INC (1<<31)
+#define EDMAC_CONFIG_DST_INC (1<<30)
+
+#define EDMAC_CONFIG_SRC_WIDTH_SHIFT (16)
+#define EDMAC_CONFIG_DST_WIDTH_SHIFT (12)
+#define EDMAC_WIDTH_8BIT (0x0)
+#define EDMAC_WIDTH_16BIT (0x1)
+#define EDMAC_WIDTH_32BIT (0x10)
+#define EDMAC_WIDTH_64BIT (0x11)
+
+#define EDMAC_MAX_BURST_WIDTH (16)
+#define EDMAC_MIN_BURST_WIDTH (1)
+#define EDMAC_CONFIG_SRC_BURST_SHIFT (24)
+#define EDMAC_CONFIG_DST_BURST_SHIFT (20)
+
+#define EDMAC_LLI_ALIGN 0x40
+#define EDMAC_LLI_DISABLE 0x0
+#define EDMAC_LLI_ENABLE 0x2
+
+#define EDMAC_CXCONFIG_SIGNAL_SHIFT (0x4)
+#define EDMAC_CXCONFIG_MEM_TYPE (0x0)
+#define EDMAC_CXCONFIG_DEV_MEM_TYPE (0x1)
+#define EDMAC_CXCONFIG_TSF_TYPE_SHIFT (0x2)
+#define EDMAC_CxCONFIG_LLI_START (0x1)
+
+#define EDMAC_CXCONFIG_ITC_EN (0x1)
+#define EDMAC_CXCONFIG_ITC_EN_SHIFT (0x1)
+
+#define CCFG_EN 0x1
+
+#endif
diff -urN linux-4.9.37/drivers/dma/Kconfig linux-4.9.y/drivers/dma/Kconfig
--- linux-4.9.37/drivers/dma/Kconfig 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/dma/Kconfig 2021-06-07 13:01:33.000000000 +0300
@@ -564,6 +564,19 @@
help
Support the DMA engine for ZTE ZX296702 platform devices.
+config EDMAC
+ tristate "Goke EDMAC Controller support"
+ depends on (ARCH_GK7205V300 || ARCH_GK7205V200 || ARCH_GK7202V300 || ARCH_GK7605V100)
+ select DMA_ENGINE
+ select DMA_VIRTUAL_CHANNELS
+ help
+ The Direction Memory Access(EDMA) is a high-speed data transfer
+ operation. It supports data read/write between peripherals and
+ memories without using the CPU.
+ Goke EDMA Controller(EDMAC) directly transfers data between
+ a memory and a peripheral, between peripherals, or between memories.
+ This avoids the CPU intervention and reduces the interrupt handling
+ overhead of the CPU.
# driver files
source "drivers/dma/bestcomm/Kconfig"
diff -urN linux-4.9.37/drivers/dma/Makefile linux-4.9.y/drivers/dma/Makefile
--- linux-4.9.37/drivers/dma/Makefile 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/dma/Makefile 2021-06-07 13:01:33.000000000 +0300
@@ -67,6 +67,7 @@
obj-$(CONFIG_TI_EDMA) += edma.o
obj-$(CONFIG_XGENE_DMA) += xgene-dma.o
obj-$(CONFIG_ZX_DMA) += zx296702_dma.o
+obj-$(CONFIG_EDMAC) += edmac_goke.o
obj-y += qcom/
obj-y += xilinx/
diff -urN linux-4.9.37/drivers/dma-buf/fence.c linux-4.9.y/drivers/dma-buf/fence.c
--- linux-4.9.37/drivers/dma-buf/fence.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/dma-buf/fence.c 2021-06-07 13:01:33.000000000 +0300
@@ -68,6 +68,8 @@
struct fence_cb *cur, *tmp;
int ret = 0;
+ lockdep_assert_held(fence->lock);
+
if (WARN_ON(!fence))
return -EINVAL;
@@ -159,9 +161,6 @@
if (WARN_ON(timeout < 0))
return -EINVAL;
- if (timeout == 0)
- return fence_is_signaled(fence);
-
trace_fence_wait_start(fence);
ret = fence->ops->wait(fence, intr, timeout);
trace_fence_wait_end(fence);
@@ -304,8 +303,12 @@
spin_lock_irqsave(fence->lock, flags);
ret = !list_empty(&cb->node);
- if (ret)
+ if (ret) {
list_del_init(&cb->node);
+ if (list_empty(&fence->cb_list))
+ if (fence->ops->disable_signaling)
+ fence->ops->disable_signaling(fence);
+ }
spin_unlock_irqrestore(fence->lock, flags);
diff -urN linux-4.9.37/drivers/dma-buf/reservation.c linux-4.9.y/drivers/dma-buf/reservation.c
--- linux-4.9.37/drivers/dma-buf/reservation.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/dma-buf/reservation.c 2021-06-07 13:01:33.000000000 +0300
@@ -280,18 +280,24 @@
unsigned *pshared_count,
struct fence ***pshared)
{
- unsigned shared_count = 0;
- unsigned retry = 1;
- struct fence **shared = NULL, *fence_excl = NULL;
- int ret = 0;
+ struct fence **shared = NULL;
+ struct fence *fence_excl;
+ unsigned int shared_count;
+ int ret = 1;
- while (retry) {
+ do {
struct reservation_object_list *fobj;
unsigned seq;
+ unsigned int i;
- seq = read_seqcount_begin(&obj->seq);
+ shared_count = i = 0;
rcu_read_lock();
+ seq = read_seqcount_begin(&obj->seq);
+
+ fence_excl = rcu_dereference(obj->fence_excl);
+ if (fence_excl && !fence_get_rcu(fence_excl))
+ goto unlock;
fobj = rcu_dereference(obj->fence);
if (fobj) {
@@ -309,52 +315,37 @@
}
ret = -ENOMEM;
- shared_count = 0;
break;
}
shared = nshared;
- memcpy(shared, fobj->shared, sz);
shared_count = fobj->shared_count;
- } else
- shared_count = 0;
- fence_excl = rcu_dereference(obj->fence_excl);
-
- retry = read_seqcount_retry(&obj->seq, seq);
- if (retry)
- goto unlock;
-
- if (!fence_excl || fence_get_rcu(fence_excl)) {
- unsigned i;
for (i = 0; i < shared_count; ++i) {
- if (fence_get_rcu(shared[i]))
- continue;
-
- /* uh oh, refcount failed, abort and retry */
- while (i--)
- fence_put(shared[i]);
-
- if (fence_excl) {
- fence_put(fence_excl);
- fence_excl = NULL;
- }
-
- retry = 1;
- break;
+ shared[i] = rcu_dereference(fobj->shared[i]);
+ if (!fence_get_rcu(shared[i]))
+ break;
}
- } else
- retry = 1;
+ }
+
+ if ((i > 0) && (i != shared_count || read_seqcount_retry(&obj->seq, seq))) {
+ while (i--)
+ fence_put(shared[i]);
+ fence_put(fence_excl);
+ goto unlock;
+ }
+ ret = 0;
unlock:
rcu_read_unlock();
- }
- *pshared_count = shared_count;
- if (shared_count)
- *pshared = shared;
- else {
- *pshared = NULL;
+ } while (ret);
+
+ if (!shared_count) {
kfree(shared);
+ shared = NULL;
}
+
+ *pshared_count = shared_count;
+ *pshared = shared;
*pfence_excl = fence_excl;
return ret;
@@ -379,10 +370,7 @@
{
struct fence *fence;
unsigned seq, shared_count, i = 0;
- long ret = timeout;
-
- if (!timeout)
- return reservation_object_test_signaled_rcu(obj, wait_all);
+ long ret = timeout ? timeout : 1;
retry:
fence = NULL;
@@ -397,9 +385,6 @@
if (fobj)
shared_count = fobj->shared_count;
- if (read_seqcount_retry(&obj->seq, seq))
- goto unlock_retry;
-
for (i = 0; i < shared_count; ++i) {
struct fence *lfence = rcu_dereference(fobj->shared[i]);
@@ -422,9 +407,6 @@
if (!shared_count) {
struct fence *fence_excl = rcu_dereference(obj->fence_excl);
- if (read_seqcount_retry(&obj->seq, seq))
- goto unlock_retry;
-
if (fence_excl &&
!test_bit(FENCE_FLAG_SIGNALED_BIT, &fence_excl->flags)) {
if (!fence_get_rcu(fence_excl))
@@ -439,6 +421,11 @@
rcu_read_unlock();
if (fence) {
+ if (read_seqcount_retry(&obj->seq, seq)) {
+ fence_put(fence);
+ goto retry;
+ }
+
ret = fence_wait_timeout(fence, intr, ret);
fence_put(fence);
if (ret > 0 && wait_all && (i + 1 < shared_count))
@@ -484,12 +471,13 @@
bool test_all)
{
unsigned seq, shared_count;
- int ret = true;
+ int ret;
+ rcu_read_lock();
retry:
+ ret = true;
shared_count = 0;
seq = read_seqcount_begin(&obj->seq);
- rcu_read_lock();
if (test_all) {
unsigned i;
@@ -500,46 +488,35 @@
if (fobj)
shared_count = fobj->shared_count;
- if (read_seqcount_retry(&obj->seq, seq))
- goto unlock_retry;
-
for (i = 0; i < shared_count; ++i) {
struct fence *fence = rcu_dereference(fobj->shared[i]);
ret = reservation_object_test_signaled_single(fence);
if (ret < 0)
- goto unlock_retry;
+ goto retry;
else if (!ret)
break;
}
- /*
- * There could be a read_seqcount_retry here, but nothing cares
- * about whether it's the old or newer fence pointers that are
- * signaled. That race could still have happened after checking
- * read_seqcount_retry. If you care, use ww_mutex_lock.
- */
+ if (read_seqcount_retry(&obj->seq, seq))
+ goto retry;
}
if (!shared_count) {
struct fence *fence_excl = rcu_dereference(obj->fence_excl);
- if (read_seqcount_retry(&obj->seq, seq))
- goto unlock_retry;
-
if (fence_excl) {
ret = reservation_object_test_signaled_single(
fence_excl);
if (ret < 0)
- goto unlock_retry;
+ goto retry;
+
+ if (read_seqcount_retry(&obj->seq, seq))
+ goto retry;
}
}
rcu_read_unlock();
return ret;
-
-unlock_retry:
- rcu_read_unlock();
- goto retry;
}
EXPORT_SYMBOL_GPL(reservation_object_test_signaled_rcu);
diff -urN linux-4.9.37/drivers/dma-buf/sw_sync.c linux-4.9.y/drivers/dma-buf/sw_sync.c
--- linux-4.9.37/drivers/dma-buf/sw_sync.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/dma-buf/sw_sync.c 2021-06-07 13:01:33.000000000 +0300
@@ -234,6 +234,13 @@
return true;
}
+static void timeline_fence_disable_signaling(struct fence *fence)
+{
+ struct sync_pt *pt = container_of(fence, struct sync_pt, base);
+
+ list_del_init(&pt->active_list);
+}
+
static void timeline_fence_value_str(struct fence *fence,
char *str, int size)
{
@@ -252,6 +259,7 @@
.get_driver_name = timeline_fence_get_driver_name,
.get_timeline_name = timeline_fence_get_timeline_name,
.enable_signaling = timeline_fence_enable_signaling,
+ .disable_signaling = timeline_fence_disable_signaling,
.signaled = timeline_fence_signaled,
.wait = fence_default_wait,
.release = timeline_fence_release,
@@ -316,8 +324,8 @@
}
sync_file = sync_file_create(&pt->base);
+ fence_put(&pt->base);
if (!sync_file) {
- fence_put(&pt->base);
err = -ENOMEM;
goto err;
}
diff -urN linux-4.9.37/drivers/dma-buf/_sw_sync.h linux-4.9.y/drivers/dma-buf/_sw_sync.h
--- linux-4.9.37/drivers/dma-buf/_sw_sync.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/dma-buf/_sw_sync.h 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2012 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _UAPI_LINUX_SW_SYNC_H
+#define _UAPI_LINUX_SW_SYNC_H
+
+#include <linux/types.h>
+
+struct sw_sync_create_fence_data {
+ __u32 value;
+ char name[32];
+ __s32 fence; /* fd of new fence */
+};
+
+#define SW_SYNC_IOC_MAGIC 'W'
+
+#define SW_SYNC_IOC_CREATE_FENCE _IOWR(SW_SYNC_IOC_MAGIC, 0,\
+ struct sw_sync_create_fence_data)
+#define SW_SYNC_IOC_INC _IOW(SW_SYNC_IOC_MAGIC, 1, __u32)
+
+#endif /* _UAPI_LINUX_SW_SYNC_H */
diff -urN linux-4.9.37/drivers/dma-buf/sw_sync.h linux-4.9.y/drivers/dma-buf/sw_sync.h
--- linux-4.9.37/drivers/dma-buf/sw_sync.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/dma-buf/sw_sync.h 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,43 @@
+/*
+ * include/linux/sw_sync.h
+ *
+ * Copyright (C) 2012 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _LINUX_SW_SYNC_H
+#define _LINUX_SW_SYNC_H
+
+#include <linux/types.h>
+#include <linux/kconfig.h>
+#include "sync.h"
+#include "_sw_sync.h"
+#include <linux/sync_file.h>
+
+struct sw_sync_timeline {
+ struct sync_timeline obj;
+
+ u32 value;
+};
+
+struct sw_sync_pt {
+ struct sync_pt pt;
+
+ u32 value;
+};
+
+struct sw_sync_timeline *bsp_sw_sync_timeline_create(const char *name);
+void bsp_sw_sync_timeline_inc(struct sw_sync_timeline *obj, u32 inc);
+
+struct sync_pt *bsp_sw_sync_pt_create(struct sw_sync_timeline *obj, u32 value);
+
+#endif /* _LINUX_SW_SYNC_H */
diff -urN linux-4.9.37/drivers/dma-buf/sync.c linux-4.9.y/drivers/dma-buf/sync.c
--- linux-4.9.37/drivers/dma-buf/sync.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/dma-buf/sync.c 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,738 @@
+/*
+ * drivers/base/sync.c
+ *
+ * Copyright (C) 2012 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/debugfs.h>
+#include <linux/export.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/poll.h>
+#include <linux/sched.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/anon_inodes.h>
+
+#include "sync.h"
+
+#include <linux/version.h>
+
+static const struct fence_ops android_fence_ops;
+static const struct file_operations sync_fence_fops;
+
+struct sync_timeline *bsp_sync_timeline_create(const struct sync_timeline_ops *ops,
+ int size, const char *name)
+{
+ struct sync_timeline *obj = NULL;
+
+ if (size < sizeof(struct sync_timeline))
+ return NULL;
+
+ obj = kzalloc(size, GFP_KERNEL);
+ if (obj == NULL)
+ return NULL;
+
+ kref_init(&obj->kref);
+ obj->ops = ops;
+ obj->context = fence_context_alloc(1);
+ strlcpy(obj->name, name, sizeof(obj->name));
+
+ INIT_LIST_HEAD(&obj->child_list_head);
+ INIT_LIST_HEAD(&obj->active_list_head);
+ spin_lock_init(&obj->child_list_lock);
+#if 0
+ bsp_sync_timeline_debug_add(obj);
+#endif
+
+ return obj;
+}
+EXPORT_SYMBOL(bsp_sync_timeline_create);
+
+static void sync_timeline_free(struct kref *kref)
+{
+ struct sync_timeline *obj =
+ container_of(kref, struct sync_timeline, kref);
+#if 0
+ bsp_sync_timeline_debug_remove(obj);
+#endif
+ if (obj->ops->release_obj)
+ obj->ops->release_obj(obj);
+
+ kfree(obj);
+}
+
+static void sync_timeline_get(struct sync_timeline *obj)
+{
+ kref_get(&obj->kref);
+}
+
+static void sync_timeline_put(struct sync_timeline *obj)
+{
+ kref_put(&obj->kref, sync_timeline_free);
+}
+
+void bsp_sync_timeline_destroy(struct sync_timeline *obj)
+{
+ obj->destroyed = true;
+ /*
+ * Ensure timeline is marked as destroyed before
+ * changing timeline's fences status.
+ */
+ smp_wmb();
+
+ /*
+ * signal any children that their parent is going away.
+ */
+ bsp_sync_timeline_signal(obj);
+ sync_timeline_put(obj);
+}
+EXPORT_SYMBOL(bsp_sync_timeline_destroy);
+
+void bsp_sync_timeline_signal(struct sync_timeline *obj)
+{
+ unsigned long flags;
+ LIST_HEAD(signaled_pts);
+ struct sync_pt *pt = NULL;
+ struct sync_pt *next = NULL;
+
+ spin_lock_irqsave(&obj->child_list_lock, flags);
+
+ list_for_each_entry_safe(pt, next, &obj->active_list_head,
+ active_list) {
+ if (fence_is_signaled_locked(&pt->base)) {
+ list_del_init(&pt->active_list);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
+ fence_put(&pt->base);
+#endif
+ }
+ }
+
+ spin_unlock_irqrestore(&obj->child_list_lock, flags);
+}
+EXPORT_SYMBOL(bsp_sync_timeline_signal);
+
+struct sync_pt *bsp_sync_pt_create(struct sync_timeline *obj, int size)
+{
+ unsigned long flags;
+ struct sync_pt *pt = NULL;
+
+ if (size < sizeof(struct sync_pt))
+ return NULL;
+
+ pt = kzalloc(size, GFP_KERNEL);
+ if (pt == NULL)
+ return NULL;
+
+ spin_lock_irqsave(&obj->child_list_lock, flags);
+ sync_timeline_get(obj);
+ fence_init(&pt->base, &android_fence_ops, &obj->child_list_lock,
+ obj->context, ++obj->value);
+ list_add_tail(&pt->child_list, &obj->child_list_head);
+ INIT_LIST_HEAD(&pt->active_list);
+ spin_unlock_irqrestore(&obj->child_list_lock, flags);
+ return pt;
+}
+EXPORT_SYMBOL(bsp_sync_pt_create);
+
+void bsp_sync_pt_free(struct sync_pt *pt)
+{
+ fence_put(&pt->base);
+}
+EXPORT_SYMBOL(bsp_sync_pt_free);
+
+#if 0
+static struct sync_fence *sync_fence_alloc(int size, const char *name)
+{
+ struct sync_fence *fence;
+
+ fence = kzalloc(size, GFP_KERNEL);
+ if (fence == NULL)
+ return NULL;
+
+ fence->file = anon_inode_getfile("sync_fence", &sync_fence_fops,
+ fence, 0);
+ if (IS_ERR(fence->file))
+ goto err;
+
+ kref_init(&fence->kref);
+ strlcpy(fence->name, name, sizeof(fence->name));
+
+ init_waitqueue_head(&fence->wq);
+
+ return fence;
+
+err:
+ kfree(fence);
+ return NULL;
+}
+
+static void fence_check_cb_func(struct fence *f, struct fence_cb *cb)
+{
+ struct sync_fence_cb *check;
+ struct sync_fence *fence;
+
+ check = container_of(cb, struct sync_fence_cb, cb);
+ fence = check->fence;
+
+ if (atomic_dec_and_test(&fence->status))
+ wake_up_all(&fence->wq);
+}
+
+/* TODO: implement a create which takes more that one sync_pt */
+struct sync_fence *bsp_sync_fence_create(const char *name, struct sync_pt *pt)
+{
+ struct sync_fence *fence;
+
+ fence = sync_fence_alloc(offsetof(struct sync_fence, cbs[1]), name);
+ if (fence == NULL)
+ return NULL;
+
+ fence->num_fences = 1;
+ atomic_set(&fence->status, 1);
+
+ fence->cbs[0].sync_pt = &pt->base;
+ fence->cbs[0].fence = fence;
+ if (fence_add_callback(&pt->base, &fence->cbs[0].cb,
+ fence_check_cb_func))
+ atomic_dec(&fence->status);
+#if 0
+ bsp_sync_fence_debug_add(fence);
+#endif
+
+ return fence;
+}
+EXPORT_SYMBOL(bsp_sync_fence_create);
+
+struct sync_fence *bsp_sync_fence_fdget(int fd)
+{
+ struct file *file = fget(fd);
+
+ if (file == NULL)
+ return NULL;
+
+ if (file->f_op != &sync_fence_fops)
+ goto err;
+
+ return file->private_data;
+
+err:
+ fput(file);
+ return NULL;
+}
+EXPORT_SYMBOL(bsp_sync_fence_fdget);
+
+void bsp_sync_fence_put(struct sync_fence *fence)
+{
+ fput(fence->file);
+}
+EXPORT_SYMBOL(bsp_sync_fence_put);
+
+void bsp_sync_fence_install(struct sync_fence *fence, int fd)
+{
+ printk("<%s> Line %d: fd =%d, fence=%p, name=%s\n", __func__, __LINE__, fd, fence, fence->name);
+ fd_install(fd, fence->file);
+}
+EXPORT_SYMBOL(bsp_sync_fence_install);
+
+static void sync_fence_add_pt(struct sync_fence *fence,
+ int *i, struct fence *pt)
+{
+ fence->cbs[*i].sync_pt = pt;
+ fence->cbs[*i].fence = fence;
+
+ if (!fence_add_callback(pt, &fence->cbs[*i].cb, fence_check_cb_func)) {
+ fence_get(pt);
+ (*i)++;
+ }
+}
+
+struct sync_fence *bsp_sync_fence_merge(const char *name,
+ struct sync_fence *a, struct sync_fence *b)
+{
+ int num_fences = a->num_fences + b->num_fences;
+ struct sync_fence *fence;
+ int i, i_a, i_b;
+ unsigned long size = offsetof(struct sync_fence, cbs[num_fences]);
+
+ fence = sync_fence_alloc(size, name);
+ if (fence == NULL)
+ return NULL;
+
+ atomic_set(&fence->status, num_fences);
+
+ /*
+ * Assume sync_fence a and b are both ordered and have no
+ * duplicates with the same context.
+ *
+ * If a sync_fence can only be created with sync_fence_merge
+ * and sync_fence_create, this is a reasonable assumption.
+ */
+ for (i = i_a = i_b = 0; i_a < a->num_fences && i_b < b->num_fences; ) {
+ struct fence *pt_a = a->cbs[i_a].sync_pt;
+ struct fence *pt_b = b->cbs[i_b].sync_pt;
+
+ if (pt_a->context < pt_b->context) {
+ sync_fence_add_pt(fence, &i, pt_a);
+
+ i_a++;
+ } else if (pt_a->context > pt_b->context) {
+ sync_fence_add_pt(fence, &i, pt_b);
+
+ i_b++;
+ } else {
+ if (pt_a->seqno - pt_b->seqno <= INT_MAX)
+ sync_fence_add_pt(fence, &i, pt_a);
+ else
+ sync_fence_add_pt(fence, &i, pt_b);
+
+ i_a++;
+ i_b++;
+ }
+ }
+
+ for (; i_a < a->num_fences; i_a++)
+ sync_fence_add_pt(fence, &i, a->cbs[i_a].sync_pt);
+
+ for (; i_b < b->num_fences; i_b++)
+ sync_fence_add_pt(fence, &i, b->cbs[i_b].sync_pt);
+
+ if (num_fences > i)
+ atomic_sub(num_fences - i, &fence->status);
+ fence->num_fences = i;
+#if 0
+ bsp_sync_fence_debug_add(fence);
+#endif
+ return fence;
+}
+EXPORT_SYMBOL(bsp_sync_fence_merge);
+
+int bsp_sync_fence_wake_up_wq(wait_queue_t *curr, unsigned mode,
+ int wake_flags, void *key)
+{
+ struct sync_fence_waiter *wait;
+
+ wait = container_of(curr, struct sync_fence_waiter, work);
+ list_del_init(&wait->work.task_list);
+
+ wait->callback(wait->work.private, wait);
+ return 1;
+}
+
+int bsp_sync_fence_wait_async(struct sync_fence *fence,
+ struct sync_fence_waiter *waiter)
+{
+ int err = atomic_read(&fence->status);
+ unsigned long flags;
+
+ if (err < 0)
+ return err;
+
+ if (!err)
+ return 1;
+
+ init_waitqueue_func_entry(&waiter->work, bsp_sync_fence_wake_up_wq);
+ waiter->work.private = fence;
+
+ spin_lock_irqsave(&fence->wq.lock, flags);
+ err = atomic_read(&fence->status);
+ if (err > 0)
+ __add_wait_queue_tail(&fence->wq, &waiter->work);
+ spin_unlock_irqrestore(&fence->wq.lock, flags);
+
+ if (err < 0)
+ return err;
+
+ return !err;
+}
+EXPORT_SYMBOL(bsp_sync_fence_wait_async);
+
+int bsp_sync_fence_cancel_async(struct sync_fence *fence,
+ struct sync_fence_waiter *waiter)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ spin_lock_irqsave(&fence->wq.lock, flags);
+ if (!list_empty(&waiter->work.task_list))
+ list_del_init(&waiter->work.task_list);
+ else
+ ret = -ENOENT;
+ spin_unlock_irqrestore(&fence->wq.lock, flags);
+ return ret;
+}
+EXPORT_SYMBOL(bsp_sync_fence_cancel_async);
+
+int bsp_sync_fence_wait(struct sync_fence *fence, long timeout)
+{
+ long ret;
+
+ if (timeout < 0)
+ timeout = MAX_SCHEDULE_TIMEOUT;
+ else
+ timeout = msecs_to_jiffies(timeout);
+
+ ret = wait_event_interruptible_timeout(fence->wq,
+ atomic_read(&fence->status) <= 0,
+ timeout);
+
+ if (ret < 0) {
+ return ret;
+ } else if (ret == 0) {
+ if (timeout) {
+ pr_info("fence timeout on [%p] after %dms\n", fence,
+ jiffies_to_msecs(timeout));
+ bsp_sync_dump();
+ }
+ return -ETIME;
+ }
+
+ ret = atomic_read(&fence->status);
+ if (ret) {
+ pr_info("fence error %ld on [%p]\n", ret, fence);
+ bsp_sync_dump();
+ }
+ return ret;
+}
+EXPORT_SYMBOL(bsp_sync_fence_wait);
+
+#endif
+static const char *android_fence_get_driver_name(struct fence *fence)
+{
+ struct sync_pt *pt = container_of(fence, struct sync_pt, base);
+ struct sync_timeline *parent = sync_pt_parent(pt);
+
+ return parent->ops->driver_name;
+}
+
+static const char *android_fence_get_timeline_name(struct fence *fence)
+{
+ struct sync_pt *pt = container_of(fence, struct sync_pt, base);
+ struct sync_timeline *parent = sync_pt_parent(pt);
+
+ return parent->name;
+}
+
+static void android_fence_release(struct fence *fence)
+{
+ struct sync_pt *pt = container_of(fence, struct sync_pt, base);
+ struct sync_timeline *parent = sync_pt_parent(pt);
+ unsigned long flags;
+
+ spin_lock_irqsave(fence->lock, flags);
+ list_del(&pt->child_list);
+ if (WARN_ON_ONCE(!list_empty(&pt->active_list)))
+ list_del(&pt->active_list);
+ spin_unlock_irqrestore(fence->lock, flags);
+
+ if (parent->ops->free_pt)
+ parent->ops->free_pt(pt);
+
+ sync_timeline_put(parent);
+ fence_free(&pt->base);
+}
+
+static bool android_fence_signaled(struct fence *fence)
+{
+ struct sync_pt *pt = container_of(fence, struct sync_pt, base);
+ struct sync_timeline *parent = sync_pt_parent(pt);
+ int ret;
+
+ ret = parent->ops->has_signaled(pt);
+ if (ret < 0)
+ fence->status = ret;
+ return ret;
+}
+
+static bool android_fence_enable_signaling(struct fence *fence)
+{
+ struct sync_pt *pt = container_of(fence, struct sync_pt, base);
+ struct sync_timeline *parent = sync_pt_parent(pt);
+
+ if (android_fence_signaled(fence))
+ return false;
+
+ list_add_tail(&pt->active_list, &parent->active_list_head);
+ return true;
+}
+
+static void android_fence_disable_signaling(struct fence *fence)
+{
+ struct sync_pt *pt = container_of(fence, struct sync_pt, base);
+
+ list_del_init(&pt->active_list);
+}
+
+static int android_fence_fill_driver_data(struct fence *fence,
+ void *data, int size)
+{
+ struct sync_pt *pt = container_of(fence, struct sync_pt, base);
+ struct sync_timeline *parent = sync_pt_parent(pt);
+
+ if (!parent->ops->fill_driver_data)
+ return 0;
+ return parent->ops->fill_driver_data(pt, data, size);
+}
+
+static void android_fence_value_str(struct fence *fence,
+ char *str, int size)
+{
+ struct sync_pt *pt = container_of(fence, struct sync_pt, base);
+ struct sync_timeline *parent = sync_pt_parent(pt);
+
+ if (!parent->ops->pt_value_str) {
+ if (size)
+ *str = 0;
+ return;
+ }
+ parent->ops->pt_value_str(pt, str, size);
+}
+
+static void android_fence_timeline_value_str(struct fence *fence,
+ char *str, int size)
+{
+ struct sync_pt *pt = container_of(fence, struct sync_pt, base);
+ struct sync_timeline *parent = sync_pt_parent(pt);
+
+ if (!parent->ops->timeline_value_str) {
+ if (size)
+ *str = 0;
+ return;
+ }
+ parent->ops->timeline_value_str(parent, str, size);
+}
+
+static const struct fence_ops android_fence_ops = {
+ .get_driver_name = android_fence_get_driver_name,
+ .get_timeline_name = android_fence_get_timeline_name,
+ .enable_signaling = android_fence_enable_signaling,
+ .signaled = android_fence_signaled,
+ .wait = fence_default_wait,
+ .release = android_fence_release,
+ .fill_driver_data = android_fence_fill_driver_data,
+ .fence_value_str = android_fence_value_str,
+ .timeline_value_str = android_fence_timeline_value_str,
+};
+#if 0
+static void sync_fence_free(struct kref *kref)
+{
+ struct sync_fence *fence = container_of(kref, struct sync_fence, kref);
+ int i;
+
+ for (i = 0; i < fence->num_fences; ++i) {
+ fence_remove_callback(fence->cbs[i].sync_pt, &fence->cbs[i].cb);
+ fence_put(fence->cbs[i].sync_pt);
+ }
+
+ kfree(fence);
+}
+
+static int sync_fence_release(struct inode *inode, struct file *file)
+{
+ struct sync_fence *fence = file->private_data;
+
+ bsp_sync_fence_debug_remove(fence);
+
+ kref_put(&fence->kref, sync_fence_free);
+ return 0;
+}
+
+static unsigned int sync_fence_poll(struct file *file, poll_table *wait)
+{
+ struct sync_fence *fence = file->private_data;
+ int status;
+
+ poll_wait(file, &fence->wq, wait);
+
+ status = atomic_read(&fence->status);
+
+ if (!status)
+ return POLLIN;
+ else if (status < 0)
+ return POLLERR;
+ return 0;
+}
+
+static long sync_fence_ioctl_wait(struct sync_fence *fence, unsigned long arg)
+{
+ __s32 value;
+
+ if (copy_from_user(&value, (void __user *)arg, sizeof(value)))
+ return -EFAULT;
+
+ return bsp_sync_fence_wait(fence, value);
+}
+
+static long sync_fence_ioctl_merge(struct sync_fence *fence, unsigned long arg)
+{
+ int fd = get_unused_fd_flags(O_CLOEXEC);
+ int err;
+ struct sync_fence *fence2, *fence3;
+ struct sync_merge_data data;
+
+ if (fd < 0)
+ return fd;
+
+ if (copy_from_user(&data, (void __user *)arg, sizeof(data))) {
+ err = -EFAULT;
+ goto err_put_fd;
+ }
+
+ fence2 = bsp_sync_fence_fdget(data.fd2);
+ if (fence2 == NULL) {
+ err = -ENOENT;
+ goto err_put_fd;
+ }
+
+ data.name[sizeof(data.name) - 1] = '\0';
+ fence3 = bsp_sync_fence_merge(data.name, fence, fence2);
+ if (fence3 == NULL) {
+ err = -ENOMEM;
+ goto err_put_fence2;
+ }
+
+ data.fence = fd;
+ if (copy_to_user((void __user *)arg, &data, sizeof(data))) {
+ err = -EFAULT;
+ goto err_put_fence3;
+ }
+
+ bsp_sync_fence_install(fence3, fd);
+ bsp_sync_fence_put(fence2);
+ return 0;
+
+err_put_fence3:
+ bsp_sync_fence_put(fence3);
+
+err_put_fence2:
+ bsp_sync_fence_put(fence2);
+
+err_put_fd:
+ put_unused_fd(fd);
+ return err;
+}
+
+static int sync_fill_pt_info(struct fence *fence, void *data, int size)
+{
+ struct sync_pt_info *info = data;
+ int ret;
+
+ if (size < sizeof(struct sync_pt_info))
+ return -ENOMEM;
+
+ info->len = sizeof(struct sync_pt_info);
+
+ if (fence->ops->fill_driver_data) {
+ ret = fence->ops->fill_driver_data(fence, info->driver_data,
+ size - sizeof(*info));
+ if (ret < 0)
+ return ret;
+
+ info->len += ret;
+ }
+
+ strlcpy(info->obj_name, fence->ops->get_timeline_name(fence),
+ sizeof(info->obj_name));
+ strlcpy(info->driver_name, fence->ops->get_driver_name(fence),
+ sizeof(info->driver_name));
+ if (fence_is_signaled(fence))
+ info->status = fence->status >= 0 ? 1 : fence->status;
+ else
+ info->status = 0;
+ info->timestamp_ns = ktime_to_ns(fence->timestamp);
+
+ return info->len;
+}
+
+static long sync_fence_ioctl_fence_info(struct sync_fence *fence,
+ unsigned long arg)
+{
+ struct sync_fence_info_data *data;
+ __u32 size;
+ __u32 len = 0;
+ int ret, i;
+
+ if (copy_from_user(&size, (void __user *)arg, sizeof(size)))
+ return -EFAULT;
+
+ if (size < sizeof(struct sync_fence_info_data))
+ return -EINVAL;
+
+ if (size > 4096)
+ size = 4096;
+
+ data = kzalloc(size, GFP_KERNEL);
+ if (data == NULL)
+ return -ENOMEM;
+
+ strlcpy(data->name, fence->name, sizeof(data->name));
+ data->status = atomic_read(&fence->status);
+ if (data->status >= 0)
+ data->status = !data->status;
+
+ len = sizeof(struct sync_fence_info_data);
+
+ for (i = 0; i < fence->num_fences; ++i) {
+ struct fence *pt = fence->cbs[i].sync_pt;
+
+ ret = sync_fill_pt_info(pt, (u8 *)data + len, size - len);
+
+ if (ret < 0)
+ goto out;
+
+ len += ret;
+ }
+
+ data->len = len;
+
+ if (copy_to_user((void __user *)arg, data, len))
+ ret = -EFAULT;
+ else
+ ret = 0;
+
+out:
+ kfree(data);
+
+ return ret;
+}
+
+static long sync_fence_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ struct sync_fence *fence = file->private_data;
+
+ switch (cmd) {
+ case SYNC_IOC_WAIT:
+ return sync_fence_ioctl_wait(fence, arg);
+
+ case SYNC_IOC_MERGE:
+ return sync_fence_ioctl_merge(fence, arg);
+
+ case SYNC_IOC_FENCE_INFO:
+ return sync_fence_ioctl_fence_info(fence, arg);
+
+ default:
+ return -ENOTTY;
+ }
+}
+
+static const struct file_operations sync_fence_fops = {
+ .release = sync_fence_release,
+ .poll = sync_fence_poll,
+ .unlocked_ioctl = sync_fence_ioctl,
+ .compat_ioctl = sync_fence_ioctl,
+};
+#endif
+
diff -urN linux-4.9.37/drivers/dma-buf/sync_file.c linux-4.9.y/drivers/dma-buf/sync_file.c
--- linux-4.9.37/drivers/dma-buf/sync_file.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/dma-buf/sync_file.c 2021-06-07 13:01:33.000000000 +0300
@@ -67,9 +67,10 @@
* sync_file_create() - creates a sync file
* @fence: fence to add to the sync_fence
*
- * Creates a sync_file containg @fence. Once this is called, the sync_file
- * takes ownership of @fence. The sync_file can be released with
- * fput(sync_file->file). Returns the sync_file or NULL in case of error.
+ * Creates a sync_file containg @fence. This function acquires and additional
+ * reference of @fence for the newly-created &sync_file, if it succeeds. The
+ * sync_file can be released with fput(sync_file->file). Returns the
+ * sync_file or NULL in case of error.
*/
struct sync_file *sync_file_create(struct fence *fence)
{
@@ -79,7 +80,7 @@
if (!sync_file)
return NULL;
- sync_file->fence = fence;
+ sync_file->fence = fence_get(fence);
snprintf(sync_file->name, sizeof(sync_file->name), "%s-%s%llu-%d",
fence->ops->get_driver_name(fence),
@@ -90,14 +91,7 @@
}
EXPORT_SYMBOL(sync_file_create);
-/**
- * sync_file_fdget() - get a sync_file from an fd
- * @fd: fd referencing a fence
- *
- * Ensures @fd references a valid sync_file, increments the refcount of the
- * backing file. Returns the sync_file or NULL in case of error.
- */
-static struct sync_file *sync_file_fdget(int fd)
+struct sync_file *sync_file_fdget(int fd)
{
struct file *file = fget(fd);
@@ -114,6 +108,8 @@
return NULL;
}
+EXPORT_SYMBOL(sync_file_fdget);
+
/**
* sync_file_get_fence - get the fence related to the sync_file fd
* @fd: sync_file fd to get the fence from
@@ -305,10 +301,9 @@
poll_wait(file, &sync_file->wq, wait);
- if (!poll_does_not_wait(wait) &&
- !test_and_set_bit(POLL_ENABLED, &sync_file->fence->flags)) {
+ if (!test_and_set_bit(POLL_ENABLED, &sync_file->fence->flags)) {
if (fence_add_callback(sync_file->fence, &sync_file->cb,
- fence_check_cb_func) < 0)
+ fence_check_cb_func) < 0)
wake_up_all(&sync_file->wq);
}
@@ -370,7 +365,7 @@
return err;
}
-static void sync_fill_fence_info(struct fence *fence,
+static int sync_fill_fence_info(struct fence *fence,
struct sync_fence_info *info)
{
strlcpy(info->obj_name, fence->ops->get_timeline_name(fence),
@@ -382,6 +377,8 @@
else
info->status = 0;
info->timestamp_ns = ktime_to_ns(fence->timestamp);
+
+ return info->status;
}
static long sync_file_ioctl_fence_info(struct sync_file *sync_file,
@@ -407,8 +404,12 @@
* sync_fence_info and return the actual number of fences on
* info->num_fences.
*/
- if (!info.num_fences)
+ if (!info.num_fences) {
+ info.status = fence_is_signaled(sync_file->fence);
goto no_fences;
+ } else {
+ info.status = 1;
+ }
if (info.num_fences < num_fences)
return -EINVAL;
@@ -418,8 +419,10 @@
if (!fence_info)
return -ENOMEM;
- for (i = 0; i < num_fences; i++)
- sync_fill_fence_info(fences[i], &fence_info[i]);
+ for (i = 0; i < num_fences; i++) {
+ int status = sync_fill_fence_info(fences[i], &fence_info[i]);
+ info.status = info.status <= 0 ? info.status : status;
+ }
if (copy_to_user(u64_to_user_ptr(info.sync_fence_info), fence_info,
size)) {
@@ -429,7 +432,6 @@
no_fences:
strlcpy(info.name, sync_file->name, sizeof(info.name));
- info.status = fence_is_signaled(sync_file->fence);
info.num_fences = num_fences;
if (copy_to_user((void __user *)arg, &info, sizeof(info)))
@@ -443,12 +445,26 @@
return ret;
}
+#define SYNC_IOC_WAIT _IOW(SYNC_IOC_MAGIC, 0, __s32)
+static long sync_fence_ioctl_wait(struct sync_file *sync_file, unsigned long arg)
+{
+ __s32 value;
+
+ if (copy_from_user(&value, (void __user *)arg, sizeof(value)))
+ return -EFAULT;
+ if(value <= 0)
+ value = MAX_SCHEDULE_TIMEOUT;
+ return fence_wait_timeout(sync_file->fence, true, value);
+}
+
static long sync_file_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
struct sync_file *sync_file = file->private_data;
switch (cmd) {
+ case SYNC_IOC_WAIT:
+ return sync_fence_ioctl_wait(sync_file, arg);
case SYNC_IOC_MERGE:
return sync_file_ioctl_merge(sync_file, arg);
diff -urN linux-4.9.37/drivers/dma-buf/_sync.h linux-4.9.y/drivers/dma-buf/_sync.h
--- linux-4.9.37/drivers/dma-buf/_sync.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/dma-buf/_sync.h 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2012 Google, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _UAPI_LINUX_SYNC_H
+#define _UAPI_LINUX_SYNC_H
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+/**
+ * struct sync_merge_data - data passed to merge ioctl
+ * @fd2: file descriptor of second fence
+ * @name: name of new fence
+ * @fence: returns the fd of the new fence to userspace
+ */
+struct sync_merge_data {
+ __s32 fd2; /* fd of second fence */
+ char name[32]; /* name of new fence */
+ __s32 fence; /* fd on newly created fence */
+};
+
+/**
+ * struct sync_pt_info - detailed sync_pt information
+ * @len: length of sync_pt_info including any driver_data
+ * @obj_name: name of parent sync_timeline
+ * @driver_name: name of driver implementing the parent
+ * @status: status of the sync_pt 0:active 1:signaled <0:error
+ * @timestamp_ns: timestamp of status change in nanoseconds
+ * @driver_data: any driver dependent data
+ */
+struct sync_pt_info {
+ __u32 len;
+ char obj_name[32];
+ char driver_name[32];
+ __s32 status;
+ __u64 timestamp_ns;
+
+ __u8 driver_data[0];
+};
+
+/**
+ * struct sync_fence_info_data - data returned from fence info ioctl
+ * @len: ioctl caller writes the size of the buffer its passing in.
+ * ioctl returns length of sync_fence_data returned to userspace
+ * including pt_info.
+ * @name: name of fence
+ * @status: status of fence. 1: signaled 0:active <0:error
+ * @pt_info: a sync_pt_info struct for every sync_pt in the fence
+ */
+struct sync_fence_info_data {
+ __u32 len;
+ char name[32];
+ __s32 status;
+
+ __u8 pt_info[0];
+};
+
+#define SYNC_IOC_MAGIC '>'
+
+/**
+ * DOC: SYNC_IOC_WAIT - wait for a fence to signal
+ *
+ * pass timeout in milliseconds. Waits indefinitely timeout < 0.
+ */
+#define SYNC_IOC_WAIT _IOW(SYNC_IOC_MAGIC, 0, __s32)
+
+/**
+ * DOC: SYNC_IOC_MERGE - merge two fences
+ *
+ * Takes a struct sync_merge_data. Creates a new fence containing copies of
+ * the sync_pts in both the calling fd and sync_merge_data.fd2. Returns the
+ * new fence's fd in sync_merge_data.fence
+ */
+#define SYNC_IOC_MERGE _IOWR(SYNC_IOC_MAGIC, 1, struct sync_merge_data)
+
+/**
+ * DOC: SYNC_IOC_FENCE_INFO - get detailed information on a fence
+ *
+ * Takes a struct sync_fence_info_data with extra space allocated for pt_info.
+ * Caller should write the size of the buffer into len. On return, len is
+ * updated to reflect the total size of the sync_fence_info_data including
+ * pt_info.
+ *
+ * pt_info is a buffer containing sync_pt_infos for every sync_pt in the fence.
+ * To iterate over the sync_pt_infos, use the sync_pt_info.len field.
+ */
+#define SYNC_IOC_FENCE_INFO _IOWR(SYNC_IOC_MAGIC, 2,\
+ struct sync_fence_info_data)
+
+#endif /* _UAPI_LINUX_SYNC_H */
diff -urN linux-4.9.37/drivers/dma-buf/sync.h linux-4.9.y/drivers/dma-buf/sync.h
--- linux-4.9.37/drivers/dma-buf/sync.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/dma-buf/sync.h 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,363 @@
+/*
+ * include/linux/sync.h
+ *
+ * Copyright (C) 2012 Google, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _LINUX_SYNC_H
+#define _LINUX_SYNC_H
+
+#include <linux/types.h>
+#include <linux/kref.h>
+#include <linux/ktime.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
+#include <linux/fence.h>
+
+#include "_sync.h"
+
+struct sync_timeline;
+struct sync_pt;
+#if 0
+struct sync_fence;
+#endif
+
+/**
+ * struct sync_timeline_ops - sync object implementation ops
+ * @driver_name: name of the implementation
+ * @dup: duplicate a sync_pt
+ * @has_signaled: returns:
+ * 1 if pt has signaled
+ * 0 if pt has not signaled
+ * <0 on error
+ * @compare: returns:
+ * 1 if b will signal before a
+ * 0 if a and b will signal at the same time
+ * -1 if a will signal before b
+ * @free_pt: called before sync_pt is freed
+ * @release_obj: called before sync_timeline is freed
+ * @fill_driver_data: write implementation specific driver data to data.
+ * should return an error if there is not enough room
+ * as specified by size. This information is returned
+ * to userspace by SYNC_IOC_FENCE_INFO.
+ * @timeline_value_str: fill str with the value of the sync_timeline's counter
+ * @pt_value_str: fill str with the value of the sync_pt
+ */
+struct sync_timeline_ops {
+ const char *driver_name;
+
+ /* required */
+ struct sync_pt * (*dup)(struct sync_pt *pt);
+
+ /* required */
+ int (*has_signaled)(struct sync_pt *pt);
+
+ /* required */
+ int (*compare)(struct sync_pt *a, struct sync_pt *b);
+
+ /* optional */
+ void (*free_pt)(struct sync_pt *sync_pt);
+
+ /* optional */
+ void (*release_obj)(struct sync_timeline *sync_timeline);
+
+ /* optional */
+ int (*fill_driver_data)(struct sync_pt *syncpt, void *data, int size);
+
+ /* optional */
+ void (*timeline_value_str)(struct sync_timeline *timeline, char *str,
+ int size);
+
+ /* optional */
+ void (*pt_value_str)(struct sync_pt *pt, char *str, int size);
+};
+
+/**
+ * struct sync_timeline - sync object
+ * @kref: reference count on fence.
+ * @ops: ops that define the implementation of the sync_timeline
+ * @name: name of the sync_timeline. Useful for debugging
+ * @destroyed: set when sync_timeline is destroyed
+ * @child_list_head: list of children sync_pts for this sync_timeline
+ * @child_list_lock: lock protecting @child_list_head, destroyed, and
+ * sync_pt.status
+ * @active_list_head: list of active (unsignaled/errored) sync_pts
+ * @sync_timeline_list: membership in global sync_timeline_list
+ */
+struct sync_timeline {
+ struct kref kref;
+ const struct sync_timeline_ops *ops;
+ char name[32];
+
+ /* protected by child_list_lock */
+ bool destroyed;
+ int context, value;
+
+ struct list_head child_list_head;
+ spinlock_t child_list_lock;
+
+ struct list_head active_list_head;
+
+#ifdef CONFIG_DEBUG_FS
+ struct list_head sync_timeline_list;
+#endif
+};
+
+/**
+ * struct sync_pt - sync point
+ * @fence: base fence class
+ * @child_list: membership in sync_timeline.child_list_head
+ * @active_list: membership in sync_timeline.active_list_head
+ * @signaled_list: membership in temporary signaled_list on stack
+ * @fence: sync_fence to which the sync_pt belongs
+ * @pt_list: membership in sync_fence.pt_list_head
+ * @status: 1: signaled, 0:active, <0: error
+ * @timestamp: time which sync_pt status transitioned from active to
+ * signaled or error.
+ */
+struct sync_pt {
+ struct fence base;
+
+ struct list_head child_list;
+ struct list_head active_list;
+};
+
+static inline struct sync_timeline *sync_pt_parent(struct sync_pt *pt)
+{
+ return container_of(pt->base.lock, struct sync_timeline,
+ child_list_lock);
+}
+
+#if 0
+struct sync_fence_cb {
+ struct fence_cb cb;
+ struct fence *sync_pt;
+ struct sync_fence *fence;
+};
+
+/**
+ * struct sync_fence - sync fence
+ * @file: file representing this fence
+ * @kref: reference count on fence.
+ * @name: name of sync_fence. Useful for debugging
+ * @pt_list_head: list of sync_pts in the fence. immutable once fence
+ * is created
+ * @status: 0: signaled, >0:active, <0: error
+ *
+ * @wq: wait queue for fence signaling
+ * @sync_fence_list: membership in global fence list
+ */
+struct sync_fence {
+ struct file *file;
+ struct kref kref;
+ char name[32];
+#ifdef CONFIG_DEBUG_FS
+ struct list_head sync_fence_list;
+#endif
+ int num_fences;
+
+ wait_queue_head_t wq;
+ atomic_t status;
+
+ struct sync_fence_cb cbs[];
+};
+
+struct sync_fence_waiter;
+typedef void (*sync_callback_t)(struct sync_fence *fence,
+ struct sync_fence_waiter *waiter);
+
+/**
+ * struct sync_fence_waiter - metadata for asynchronous waiter on a fence
+ * @waiter_list: membership in sync_fence.waiter_list_head
+ * @callback: function pointer to call when fence signals
+ * @callback_data: pointer to pass to @callback
+ */
+struct sync_fence_waiter {
+ wait_queue_t work;
+ sync_callback_t callback;
+};
+
+static inline void sync_fence_waiter_init(struct sync_fence_waiter *waiter,
+ sync_callback_t callback)
+{
+ INIT_LIST_HEAD(&waiter->work.task_list);
+ waiter->callback = callback;
+}
+#endif
+
+/*
+ * API for sync_timeline implementers
+ */
+
+/**
+ * sync_timeline_create() - creates a sync object
+ * @ops: specifies the implementation ops for the object
+ * @size: size to allocate for this obj
+ * @name: sync_timeline name
+ *
+ * Creates a new sync_timeline which will use the implementation specified by
+ * @ops. @size bytes will be allocated allowing for implementation specific
+ * data to be kept after the generic sync_timeline struct.
+ */
+struct sync_timeline *bsp_sync_timeline_create(const struct sync_timeline_ops *ops,
+ int size, const char *name);
+
+/**
+ * sync_timeline_destroy() - destroys a sync object
+ * @obj: sync_timeline to destroy
+ *
+ * A sync implementation should call this when the @obj is going away
+ * (i.e. module unload.) @obj won't actually be freed until all its children
+ * sync_pts are freed.
+ */
+void bsp_sync_timeline_destroy(struct sync_timeline *obj);
+
+/**
+ * sync_timeline_signal() - signal a status change on a sync_timeline
+ * @obj: sync_timeline to signal
+ *
+ * A sync implementation should call this any time one of it's sync_pts
+ * has signaled or has an error condition.
+ */
+void bsp_sync_timeline_signal(struct sync_timeline *obj);
+
+/**
+ * sync_pt_create() - creates a sync pt
+ * @parent: sync_pt's parent sync_timeline
+ * @size: size to allocate for this pt
+ *
+ * Creates a new sync_pt as a child of @parent. @size bytes will be
+ * allocated allowing for implementation specific data to be kept after
+ * the generic sync_timeline struct.
+ */
+struct sync_pt *bsp_sync_pt_create(struct sync_timeline *parent, int size);
+
+/**
+ * sync_pt_free() - frees a sync pt
+ * @pt: sync_pt to free
+ *
+ * This should only be called on sync_pts which have been created but
+ * not added to a fence.
+ */
+void bsp_sync_pt_free(struct sync_pt *pt);
+
+#if 0
+/**
+ * sync_fence_create() - creates a sync fence
+ * @name: name of fence to create
+ * @pt: sync_pt to add to the fence
+ *
+ * Creates a fence containg @pt. Once this is called, the fence takes
+ * ownership of @pt.
+ */
+struct sync_fence *bsp_sync_fence_create(const char *name, struct sync_pt *pt);
+
+/*
+ * API for sync_fence consumers
+ */
+
+/**
+ * sync_fence_merge() - merge two fences
+ * @name: name of new fence
+ * @a: fence a
+ * @b: fence b
+ *
+ * Creates a new fence which contains copies of all the sync_pts in both
+ * @a and @b. @a and @b remain valid, independent fences.
+ */
+struct sync_fence *bsp_sync_fence_merge(const char *name,
+ struct sync_fence *a, struct sync_fence *b);
+
+/**
+ * sync_fence_fdget() - get a fence from an fd
+ * @fd: fd referencing a fence
+ *
+ * Ensures @fd references a valid fence, increments the refcount of the backing
+ * file, and returns the fence.
+ */
+struct sync_fence *bsp_sync_fence_fdget(int fd);
+
+/**
+ * sync_fence_put() - puts a reference of a sync fence
+ * @fence: fence to put
+ *
+ * Puts a reference on @fence. If this is the last reference, the fence and
+ * all it's sync_pts will be freed
+ */
+void bsp_sync_fence_put(struct sync_fence *fence);
+
+/**
+ * sync_fence_install() - installs a fence into a file descriptor
+ * @fence: fence to install
+ * @fd: file descriptor in which to install the fence
+ *
+ * Installs @fence into @fd. @fd's should be acquired through
+ * get_unused_fd_flags(O_CLOEXEC).
+ */
+void bsp_sync_fence_install(struct sync_fence *fence, int fd);
+
+/**
+ * sync_fence_wait_async() - registers and async wait on the fence
+ * @fence: fence to wait on
+ * @waiter: waiter callback struck
+ *
+ * Returns 1 if @fence has already signaled.
+ *
+ * Registers a callback to be called when @fence signals or has an error.
+ * @waiter should be initialized with sync_fence_waiter_init().
+ */
+int bsp_sync_fence_wait_async(struct sync_fence *fence,
+ struct sync_fence_waiter *waiter);
+
+/**
+ * sync_fence_cancel_async() - cancels an async wait
+ * @fence: fence to wait on
+ * @waiter: waiter callback struck
+ *
+ * returns 0 if waiter was removed from fence's async waiter list.
+ * returns -ENOENT if waiter was not found on fence's async waiter list.
+ *
+ * Cancels a previously registered async wait. Will fail gracefully if
+ * @waiter was never registered or if @fence has already signaled @waiter.
+ */
+int bsp_sync_fence_cancel_async(struct sync_fence *fence,
+ struct sync_fence_waiter *waiter);
+
+/**
+ * sync_fence_wait() - wait on fence
+ * @fence: fence to wait on
+ * @tiemout: timeout in ms
+ *
+ * Wait for @fence to be signaled or have an error. Waits indefinitely
+ * if @timeout < 0
+ */
+int bsp_sync_fence_wait(struct sync_fence *fence, long timeout);
+
+#ifdef CONFIG_DEBUG_FS
+
+void bsp_sync_timeline_debug_add(struct sync_timeline *obj);
+void bsp_sync_timeline_debug_remove(struct sync_timeline *obj);
+void bsp_sync_fence_debug_add(struct sync_fence *fence);
+void bsp_sync_fence_debug_remove(struct sync_fence *fence);
+void bsp_sync_dump(void);
+
+#else
+# define bsp_sync_timeline_debug_add(obj)
+# define bsp_sync_timeline_debug_remove(obj)
+# define bsp_sync_fence_debug_add(fence)
+# define bsp_sync_fence_debug_remove(fence)
+# define bsp_sync_dump()
+#endif
+int bsp_sync_fence_wake_up_wq(wait_queue_t *curr, unsigned mode,
+ int wake_flags, void *key);
+
+#endif
+
+#endif /* _LINUX_SYNC_H */
diff -urN linux-4.9.37/drivers/eisa/.gitignore linux-4.9.y/drivers/eisa/.gitignore
--- linux-4.9.37/drivers/eisa/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/eisa/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-devlist.h
diff -urN linux-4.9.37/drivers/fence/Kconfig linux-4.9.y/drivers/fence/Kconfig
--- linux-4.9.37/drivers/fence/Kconfig 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/fence/Kconfig 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,8 @@
+
+config GOKE_FENCE
+ bool "Goke fence suppport"
+ default y
+ select SW_SYNC
+ select SYNC_FILE
+ help
+ Goke fence suppport
diff -urN linux-4.9.37/drivers/fence/Makefile linux-4.9.y/drivers/fence/Makefile
--- linux-4.9.37/drivers/fence/Makefile 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/fence/Makefile 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,2 @@
+
+obj-y += sw_sync.o sync.o sync_debug.o
diff -urN linux-4.9.37/drivers/fence/sw_sync.c linux-4.9.y/drivers/fence/sw_sync.c
--- linux-4.9.37/drivers/fence/sw_sync.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/fence/sw_sync.c 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,277 @@
+/*
+ * drivers/base/sw_sync.c
+ *
+ * Copyright (C) 2012 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/export.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/syscalls.h>
+#include <linux/uaccess.h>
+
+#include "sw_sync.h"
+
+static int sw_sync_cmp(u32 a, u32 b)
+{
+ if (a == b)
+ return 0;
+
+ return ((s32)a - (s32)b) < 0 ? -1 : 1;
+}
+
+struct sync_pt *bsp_sw_sync_pt_create(struct sw_sync_timeline *obj, u32 value)
+{
+ struct sw_sync_pt *pt;
+
+ pt = (struct sw_sync_pt *)
+ bsp_sync_pt_create(&obj->obj, sizeof(struct sw_sync_pt));
+ if (pt != NULL) {
+ pt->value = value;
+ }
+
+ return (struct sync_pt *)pt;
+}
+EXPORT_SYMBOL(bsp_sw_sync_pt_create);
+
+static struct sync_pt *sw_sync_pt_dup(struct sync_pt *sync_pt)
+{
+ struct sw_sync_pt *pt = (struct sw_sync_pt *)sync_pt;
+ struct sw_sync_timeline *obj =
+ (struct sw_sync_timeline *)sync_pt_parent(sync_pt);
+
+ return (struct sync_pt *)bsp_sw_sync_pt_create(obj, pt->value);
+}
+
+static int sw_sync_pt_has_signaled(struct sync_pt *sync_pt)
+{
+ struct sw_sync_pt *pt = (struct sw_sync_pt *)sync_pt;
+ struct sw_sync_timeline *obj =
+ (struct sw_sync_timeline *)sync_pt_parent(sync_pt);
+
+ return sw_sync_cmp(obj->value, pt->value) >= 0;
+}
+
+static int sw_sync_pt_compare(struct sync_pt *a, struct sync_pt *b)
+{
+ struct sw_sync_pt *pt_a = (struct sw_sync_pt *)a;
+ struct sw_sync_pt *pt_b = (struct sw_sync_pt *)b;
+
+ return sw_sync_cmp(pt_a->value, pt_b->value);
+}
+
+static int sw_sync_fill_driver_data(struct sync_pt *sync_pt,
+ void *data, int size)
+{
+ struct sw_sync_pt *pt = (struct sw_sync_pt *)sync_pt;
+
+ if (size < sizeof(pt->value))
+ return -ENOMEM;
+
+ memcpy(data, &pt->value, sizeof(pt->value));
+
+ return sizeof(pt->value);
+}
+
+static void sw_sync_timeline_value_str(struct sync_timeline *sync_timeline,
+ char *str, int size)
+{
+ struct sw_sync_timeline *timeline =
+ (struct sw_sync_timeline *)sync_timeline;
+ snprintf(str, size, "%d", timeline->value);
+}
+
+static void sw_sync_pt_value_str(struct sync_pt *sync_pt,
+ char *str, int size)
+{
+ struct sw_sync_pt *pt = (struct sw_sync_pt *)sync_pt;
+
+ snprintf(str, size, "%d", pt->value);
+}
+
+static struct sync_timeline_ops sw_sync_timeline_ops = {
+ .driver_name = "sw_sync",
+ .dup = sw_sync_pt_dup,
+ .has_signaled = sw_sync_pt_has_signaled,
+ .compare = sw_sync_pt_compare,
+ .fill_driver_data = sw_sync_fill_driver_data,
+ .timeline_value_str = sw_sync_timeline_value_str,
+ .pt_value_str = sw_sync_pt_value_str,
+};
+
+struct sw_sync_timeline *bsp_sw_sync_timeline_create(const char *name)
+{
+ struct sw_sync_timeline *obj = (struct sw_sync_timeline *)
+ bsp_sync_timeline_create(&sw_sync_timeline_ops,
+ sizeof(struct sw_sync_timeline),
+ name);
+
+ return obj;
+}
+EXPORT_SYMBOL(bsp_sw_sync_timeline_create);
+
+void bsp_sw_sync_timeline_inc(struct sw_sync_timeline *obj, u32 inc)
+{
+ obj->value += inc;
+
+ bsp_sync_timeline_signal(&obj->obj);
+}
+EXPORT_SYMBOL(bsp_sw_sync_timeline_inc);
+
+#ifdef CONFIG_SW_SYNC_USER
+/* *WARNING*
+ *
+ * improper use of this can result in deadlocking kernel drivers from userspace.
+ */
+
+/* opening sw_sync create a new sync obj */
+static int sw_sync_open(struct inode *inode, struct file *file)
+{
+ struct sw_sync_timeline *obj = NULL;
+ char task_comm[TASK_COMM_LEN];
+
+ get_task_comm(task_comm, current);
+
+ obj = bsp_sw_sync_timeline_create(task_comm);
+ if (!obj)
+ return -ENOMEM;
+
+ file->private_data = obj;
+
+ return 0;
+}
+
+static int sw_sync_release(struct inode *inode, struct file *file)
+{
+ struct sw_sync_timeline *obj = file->private_data;
+
+ bsp_sync_timeline_destroy(&obj->obj);
+ return 0;
+}
+
+static long sw_sync_ioctl_create_fence(struct sw_sync_timeline *obj,
+ unsigned long arg)
+{
+ int fd = get_unused_fd_flags(O_CLOEXEC);
+ int err;
+ struct sync_pt *pt = NULL;
+ #if 0
+ struct sync_fence *fence;
+ #else
+ struct sync_file *fence = NULL;
+ #endif
+ struct sw_sync_create_fence_data data;
+
+ if (fd < 0)
+ return fd;
+
+ if (copy_from_user(&data, (void __user *)arg, sizeof(data))) {
+ err = -EFAULT;
+ goto err;
+ }
+
+ pt = bsp_sw_sync_pt_create(obj, data.value);
+ if (!pt) {
+ err = -ENOMEM;
+ goto err;
+ }
+
+ data.name[sizeof(data.name) - 1] = '\0';
+ #if 0
+ fence = bsp_sync_fence_create(data.name, pt);
+ #else
+ fence = sync_file_create(&pt->base);
+ #endif
+ if (!fence) {
+ bsp_sync_pt_free(pt);
+ err = -ENOMEM;
+ goto err;
+ }
+
+ data.fence = fd;
+ if (copy_to_user((void __user *)arg, &data, sizeof(data))) {
+ #if 0
+ bsp_sync_fence_put(fence);
+ #else
+ fput(fence->file);
+ #endif
+ err = -EFAULT;
+ goto err;
+ }
+
+ #if 0
+ bsp_sync_fence_install(fence, fd);
+ #else
+ fd_install(fd, fence->file);
+ #endif
+
+ return 0;
+
+err:
+ put_unused_fd(fd);
+ return err;
+}
+
+static long sw_sync_ioctl_inc(struct sw_sync_timeline *obj, unsigned long arg)
+{
+ u32 value;
+
+ if (copy_from_user(&value, (void __user *)arg, sizeof(value)))
+ return -EFAULT;
+
+ bsp_sw_sync_timeline_inc(obj, value);
+
+ return 0;
+}
+
+static long sw_sync_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ struct sw_sync_timeline *obj = file->private_data;
+
+ switch (cmd) {
+ case SW_SYNC_IOC_CREATE_FENCE:
+ return sw_sync_ioctl_create_fence(obj, arg);
+
+ case SW_SYNC_IOC_INC:
+ return sw_sync_ioctl_inc(obj, arg);
+
+ default:
+ return -ENOTTY;
+ }
+}
+
+static const struct file_operations sw_sync_fops = {
+ .owner = THIS_MODULE,
+ .open = sw_sync_open,
+ .release = sw_sync_release,
+ .unlocked_ioctl = sw_sync_ioctl,
+ .compat_ioctl = sw_sync_ioctl,
+};
+
+static struct miscdevice sw_sync_dev = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "sw_sync",
+ .fops = &sw_sync_fops,
+};
+
+static int __init sw_sync_device_init(void)
+{
+ return misc_register(&sw_sync_dev);
+}
+device_initcall(sw_sync_device_init);
+
+#endif /* CONFIG_SW_SYNC_USER */
diff -urN linux-4.9.37/drivers/fence/_sw_sync.h linux-4.9.y/drivers/fence/_sw_sync.h
--- linux-4.9.37/drivers/fence/_sw_sync.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/fence/_sw_sync.h 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2012 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _UAPI_LINUX_SW_SYNC_H
+#define _UAPI_LINUX_SW_SYNC_H
+
+#include <linux/types.h>
+
+struct sw_sync_create_fence_data {
+ __u32 value;
+ char name[32];
+ __s32 fence; /* fd of new fence */
+};
+
+#define SW_SYNC_IOC_MAGIC 'W'
+
+#define SW_SYNC_IOC_CREATE_FENCE _IOWR(SW_SYNC_IOC_MAGIC, 0,\
+ struct sw_sync_create_fence_data)
+#define SW_SYNC_IOC_INC _IOW(SW_SYNC_IOC_MAGIC, 1, __u32)
+
+#endif /* _UAPI_LINUX_SW_SYNC_H */
diff -urN linux-4.9.37/drivers/fence/sw_sync.h linux-4.9.y/drivers/fence/sw_sync.h
--- linux-4.9.37/drivers/fence/sw_sync.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/fence/sw_sync.h 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,60 @@
+/*
+ * include/linux/sw_sync.h
+ *
+ * Copyright (C) 2012 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _LINUX_SW_SYNC_H
+#define _LINUX_SW_SYNC_H
+
+#include <linux/types.h>
+#include <linux/kconfig.h>
+#include "sync.h"
+#include "_sw_sync.h"
+#include <linux/sync_file.h>
+
+struct sw_sync_timeline {
+ struct sync_timeline obj;
+
+ u32 value;
+};
+
+struct sw_sync_pt {
+ struct sync_pt pt;
+
+ u32 value;
+};
+
+#if IS_ENABLED(CONFIG_SW_SYNC)
+struct sw_sync_timeline *bsp_sw_sync_timeline_create(const char *name);
+void bsp_sw_sync_timeline_inc(struct sw_sync_timeline *obj, u32 inc);
+
+struct sync_pt *bsp_sw_sync_pt_create(struct sw_sync_timeline *obj, u32 value);
+#else
+static inline struct sw_sync_timeline *bsp_sw_sync_timeline_create(const char *name)
+{
+ return NULL;
+}
+
+static inline void bsp_sw_sync_timeline_inc(struct sw_sync_timeline *obj, u32 inc)
+{
+}
+
+static inline struct sync_pt *bsp_sw_sync_pt_create(struct sw_sync_timeline *obj,
+ u32 value)
+{
+ return NULL;
+}
+#endif /* IS_ENABLED(CONFIG_SW_SYNC) */
+
+#endif /* _LINUX_SW_SYNC_H */
diff -urN linux-4.9.37/drivers/fence/sync.c linux-4.9.y/drivers/fence/sync.c
--- linux-4.9.37/drivers/fence/sync.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/fence/sync.c 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,740 @@
+/*
+ * drivers/base/sync.c
+ *
+ * Copyright (C) 2012 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/debugfs.h>
+#include <linux/export.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/poll.h>
+#include <linux/sched.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/anon_inodes.h>
+
+#include "sync.h"
+
+#include <linux/version.h>
+
+static const struct fence_ops android_fence_ops;
+static const struct file_operations sync_fence_fops;
+
+struct sync_timeline *bsp_sync_timeline_create(const struct sync_timeline_ops *ops,
+ int size, const char *name)
+{
+ struct sync_timeline *obj = NULL;
+
+ if (size < sizeof(struct sync_timeline))
+ return NULL;
+
+ obj = kzalloc(size, GFP_KERNEL);
+ if (obj == NULL)
+ return NULL;
+
+ kref_init(&obj->kref);
+ obj->ops = ops;
+ obj->context = fence_context_alloc(1);
+ strlcpy(obj->name, name, sizeof(obj->name));
+
+ INIT_LIST_HEAD(&obj->child_list_head);
+ INIT_LIST_HEAD(&obj->active_list_head);
+ spin_lock_init(&obj->child_list_lock);
+#if 0
+ bsp_sync_timeline_debug_add(obj);
+#endif
+
+ return obj;
+}
+EXPORT_SYMBOL(bsp_sync_timeline_create);
+
+static void sync_timeline_free(struct kref *kref)
+{
+ struct sync_timeline *obj =
+ container_of(kref, struct sync_timeline, kref);
+#if 0
+ bsp_sync_timeline_debug_remove(obj);
+#endif
+ if (obj->ops->release_obj)
+ obj->ops->release_obj(obj);
+
+ kfree(obj);
+}
+
+static void sync_timeline_get(struct sync_timeline *obj)
+{
+ kref_get(&obj->kref);
+}
+
+static void sync_timeline_put(struct sync_timeline *obj)
+{
+ kref_put(&obj->kref, sync_timeline_free);
+}
+
+void bsp_sync_timeline_destroy(struct sync_timeline *obj)
+{
+ obj->destroyed = true;
+ /*
+ * Ensure timeline is marked as destroyed before
+ * changing timeline's fences status.
+ */
+ smp_wmb();
+
+ /*
+ * signal any children that their parent is going away.
+ */
+ bsp_sync_timeline_signal(obj);
+ sync_timeline_put(obj);
+}
+EXPORT_SYMBOL(bsp_sync_timeline_destroy);
+
+void bsp_sync_timeline_signal(struct sync_timeline *obj)
+{
+ unsigned long flags;
+ LIST_HEAD(signaled_pts);
+ struct sync_pt *pt = NULL;
+ struct sync_pt *next = NULL;
+
+ spin_lock_irqsave(&obj->child_list_lock, flags);
+
+ list_for_each_entry_safe(pt, next, &obj->active_list_head,
+ active_list) {
+ if (fence_is_signaled_locked(&pt->base)) {
+ list_del_init(&pt->active_list);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
+ fence_put(&pt->base);
+#endif
+ }
+ }
+
+ spin_unlock_irqrestore(&obj->child_list_lock, flags);
+}
+EXPORT_SYMBOL(bsp_sync_timeline_signal);
+
+struct sync_pt *bsp_sync_pt_create(struct sync_timeline *obj, int size)
+{
+ unsigned long flags;
+ struct sync_pt *pt = NULL;
+
+ if (size < sizeof(struct sync_pt))
+ return NULL;
+
+ pt = kzalloc(size, GFP_KERNEL);
+ if (pt == NULL)
+ return NULL;
+
+ spin_lock_irqsave(&obj->child_list_lock, flags);
+ sync_timeline_get(obj);
+ fence_init(&pt->base, &android_fence_ops, &obj->child_list_lock,
+ obj->context, ++obj->value);
+ list_add_tail(&pt->child_list, &obj->child_list_head);
+ INIT_LIST_HEAD(&pt->active_list);
+ spin_unlock_irqrestore(&obj->child_list_lock, flags);
+ return pt;
+}
+EXPORT_SYMBOL(bsp_sync_pt_create);
+
+void bsp_sync_pt_free(struct sync_pt *pt)
+{
+ fence_put(&pt->base);
+}
+EXPORT_SYMBOL(bsp_sync_pt_free);
+
+#if 0
+static struct sync_fence *sync_fence_alloc(int size, const char *name)
+{
+ struct sync_fence *fence;
+
+ fence = kzalloc(size, GFP_KERNEL);
+ if (fence == NULL)
+ return NULL;
+
+ fence->file = anon_inode_getfile("sync_fence", &sync_fence_fops,
+ fence, 0);
+ if (IS_ERR(fence->file))
+ goto err;
+
+ kref_init(&fence->kref);
+ strlcpy(fence->name, name, sizeof(fence->name));
+
+ init_waitqueue_head(&fence->wq);
+
+ return fence;
+
+err:
+ kfree(fence);
+ return NULL;
+}
+
+static void fence_check_cb_func(struct fence *f, struct fence_cb *cb)
+{
+ struct sync_fence_cb *check;
+ struct sync_fence *fence;
+
+ check = container_of(cb, struct sync_fence_cb, cb);
+ fence = check->fence;
+
+ if (atomic_dec_and_test(&fence->status))
+ wake_up_all(&fence->wq);
+}
+
+/* TODO: implement a create which takes more that one sync_pt */
+struct sync_fence *bsp_sync_fence_create(const char *name, struct sync_pt *pt)
+{
+ struct sync_fence *fence;
+
+ fence = sync_fence_alloc(offsetof(struct sync_fence, cbs[1]), name);
+ if (fence == NULL)
+ return NULL;
+
+ fence->num_fences = 1;
+ atomic_set(&fence->status, 1);
+
+ fence->cbs[0].sync_pt = &pt->base;
+ fence->cbs[0].fence = fence;
+ if (fence_add_callback(&pt->base, &fence->cbs[0].cb,
+ fence_check_cb_func))
+ atomic_dec(&fence->status);
+#if 0
+ bsp_sync_fence_debug_add(fence);
+#endif
+
+ return fence;
+}
+EXPORT_SYMBOL(bsp_sync_fence_create);
+
+struct sync_fence *bsp_sync_fence_fdget(int fd)
+{
+ struct file *file = fget(fd);
+
+ if (file == NULL)
+ return NULL;
+
+ if (file->f_op != &sync_fence_fops)
+ goto err;
+
+ return file->private_data;
+
+err:
+ fput(file);
+ return NULL;
+}
+EXPORT_SYMBOL(bsp_sync_fence_fdget);
+
+void bsp_sync_fence_put(struct sync_fence *fence)
+{
+ fput(fence->file);
+}
+EXPORT_SYMBOL(bsp_sync_fence_put);
+
+void bsp_sync_fence_install(struct sync_fence *fence, int fd)
+{
+ printk("<%s> Line %d: fd =%d, fence=%p, name=%s\n", __func__, __LINE__, fd, fence, fence->name);
+ fd_install(fd, fence->file);
+}
+EXPORT_SYMBOL(bsp_sync_fence_install);
+
+static void sync_fence_add_pt(struct sync_fence *fence,
+ int *i, struct fence *pt)
+{
+ fence->cbs[*i].sync_pt = pt;
+ fence->cbs[*i].fence = fence;
+
+ if (!fence_add_callback(pt, &fence->cbs[*i].cb, fence_check_cb_func)) {
+ fence_get(pt);
+ (*i)++;
+ }
+}
+
+struct sync_fence *bsp_sync_fence_merge(const char *name,
+ struct sync_fence *a, struct sync_fence *b)
+{
+ int num_fences = a->num_fences + b->num_fences;
+ struct sync_fence *fence;
+ int i, i_a, i_b;
+ unsigned long size = offsetof(struct sync_fence, cbs[num_fences]);
+
+ fence = sync_fence_alloc(size, name);
+ if (fence == NULL)
+ return NULL;
+
+ atomic_set(&fence->status, num_fences);
+
+ /*
+ * Assume sync_fence a and b are both ordered and have no
+ * duplicates with the same context.
+ *
+ * If a sync_fence can only be created with sync_fence_merge
+ * and sync_fence_create, this is a reasonable assumption.
+ */
+ for (i = i_a = i_b = 0; i_a < a->num_fences && i_b < b->num_fences; ) {
+ struct fence *pt_a = a->cbs[i_a].sync_pt;
+ struct fence *pt_b = b->cbs[i_b].sync_pt;
+
+ if (pt_a->context < pt_b->context) {
+ sync_fence_add_pt(fence, &i, pt_a);
+
+ i_a++;
+ } else if (pt_a->context > pt_b->context) {
+ sync_fence_add_pt(fence, &i, pt_b);
+
+ i_b++;
+ } else {
+ if (pt_a->seqno - pt_b->seqno <= INT_MAX)
+ sync_fence_add_pt(fence, &i, pt_a);
+ else
+ sync_fence_add_pt(fence, &i, pt_b);
+
+ i_a++;
+ i_b++;
+ }
+ }
+
+ for (; i_a < a->num_fences; i_a++)
+ sync_fence_add_pt(fence, &i, a->cbs[i_a].sync_pt);
+
+ for (; i_b < b->num_fences; i_b++)
+ sync_fence_add_pt(fence, &i, b->cbs[i_b].sync_pt);
+
+ if (num_fences > i)
+ atomic_sub(num_fences - i, &fence->status);
+ fence->num_fences = i;
+#if 0
+ bsp_sync_fence_debug_add(fence);
+#endif
+ return fence;
+}
+EXPORT_SYMBOL(bsp_sync_fence_merge);
+
+int bsp_sync_fence_wake_up_wq(wait_queue_t *curr, unsigned mode,
+ int wake_flags, void *key)
+{
+ struct sync_fence_waiter *wait;
+
+ wait = container_of(curr, struct sync_fence_waiter, work);
+ list_del_init(&wait->work.task_list);
+
+ wait->callback(wait->work.private, wait);
+ return 1;
+}
+
+int bsp_sync_fence_wait_async(struct sync_fence *fence,
+ struct sync_fence_waiter *waiter)
+{
+ int err = atomic_read(&fence->status);
+ unsigned long flags;
+
+ if (err < 0)
+ return err;
+
+ if (!err)
+ return 1;
+
+ init_waitqueue_func_entry(&waiter->work, bsp_sync_fence_wake_up_wq);
+ waiter->work.private = fence;
+
+ spin_lock_irqsave(&fence->wq.lock, flags);
+ err = atomic_read(&fence->status);
+ if (err > 0)
+ __add_wait_queue_tail(&fence->wq, &waiter->work);
+ spin_unlock_irqrestore(&fence->wq.lock, flags);
+
+ if (err < 0)
+ return err;
+
+ return !err;
+}
+EXPORT_SYMBOL(bsp_sync_fence_wait_async);
+
+int bsp_sync_fence_cancel_async(struct sync_fence *fence,
+ struct sync_fence_waiter *waiter)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ spin_lock_irqsave(&fence->wq.lock, flags);
+ if (!list_empty(&waiter->work.task_list))
+ list_del_init(&waiter->work.task_list);
+ else
+ ret = -ENOENT;
+ spin_unlock_irqrestore(&fence->wq.lock, flags);
+ return ret;
+}
+EXPORT_SYMBOL(bsp_sync_fence_cancel_async);
+
+int bsp_sync_fence_wait(struct sync_fence *fence, long timeout)
+{
+ long ret;
+
+ if (timeout < 0)
+ timeout = MAX_SCHEDULE_TIMEOUT;
+ else
+ timeout = msecs_to_jiffies(timeout);
+
+ ret = wait_event_interruptible_timeout(fence->wq,
+ atomic_read(&fence->status) <= 0,
+ timeout);
+
+ if (ret < 0) {
+ return ret;
+ } else if (ret == 0) {
+ if (timeout) {
+ pr_info("fence timeout on [%p] after %dms\n", fence,
+ jiffies_to_msecs(timeout));
+ bsp_sync_dump();
+ }
+ return -ETIME;
+ }
+
+ ret = atomic_read(&fence->status);
+ if (ret) {
+ pr_info("fence error %ld on [%p]\n", ret, fence);
+ bsp_sync_dump();
+ }
+ return ret;
+}
+EXPORT_SYMBOL(bsp_sync_fence_wait);
+#endif
+
+static const char *android_fence_get_driver_name(struct fence *fence)
+{
+ struct sync_pt *pt = container_of(fence, struct sync_pt, base);
+ struct sync_timeline *parent = sync_pt_parent(pt);
+
+ return parent->ops->driver_name;
+}
+
+static const char *android_fence_get_timeline_name(struct fence *fence)
+{
+ struct sync_pt *pt = container_of(fence, struct sync_pt, base);
+ struct sync_timeline *parent = sync_pt_parent(pt);
+
+ return parent->name;
+}
+
+static void android_fence_release(struct fence *fence)
+{
+ struct sync_pt *pt = container_of(fence, struct sync_pt, base);
+ struct sync_timeline *parent = sync_pt_parent(pt);
+ unsigned long flags;
+
+ spin_lock_irqsave(fence->lock, flags);
+ list_del(&pt->child_list);
+ if (WARN_ON_ONCE(!list_empty(&pt->active_list)))
+ list_del(&pt->active_list);
+ spin_unlock_irqrestore(fence->lock, flags);
+
+ if (parent->ops->free_pt)
+ parent->ops->free_pt(pt);
+
+ sync_timeline_put(parent);
+ fence_free(&pt->base);
+}
+
+static bool android_fence_signaled(struct fence *fence)
+{
+ struct sync_pt *pt = container_of(fence, struct sync_pt, base);
+ struct sync_timeline *parent = sync_pt_parent(pt);
+ int ret;
+
+ ret = parent->ops->has_signaled(pt);
+ if (ret < 0)
+ fence->status = ret;
+ return ret;
+}
+
+static bool android_fence_enable_signaling(struct fence *fence)
+{
+ struct sync_pt *pt = container_of(fence, struct sync_pt, base);
+ struct sync_timeline *parent = sync_pt_parent(pt);
+
+ if (android_fence_signaled(fence))
+ return false;
+
+ list_add_tail(&pt->active_list, &parent->active_list_head);
+ return true;
+}
+
+static void android_fence_disable_signaling(struct fence *fence)
+{
+ struct sync_pt *pt = container_of(fence, struct sync_pt, base);
+
+ list_del_init(&pt->active_list);
+}
+
+static int android_fence_fill_driver_data(struct fence *fence,
+ void *data, int size)
+{
+ struct sync_pt *pt = container_of(fence, struct sync_pt, base);
+ struct sync_timeline *parent = sync_pt_parent(pt);
+
+ if (!parent->ops->fill_driver_data)
+ return 0;
+ return parent->ops->fill_driver_data(pt, data, size);
+}
+
+static void android_fence_value_str(struct fence *fence,
+ char *str, int size)
+{
+ struct sync_pt *pt = container_of(fence, struct sync_pt, base);
+ struct sync_timeline *parent = sync_pt_parent(pt);
+
+ if (!parent->ops->pt_value_str) {
+ if (size)
+ *str = 0;
+ return;
+ }
+ parent->ops->pt_value_str(pt, str, size);
+}
+
+static void android_fence_timeline_value_str(struct fence *fence,
+ char *str, int size)
+{
+ struct sync_pt *pt = container_of(fence, struct sync_pt, base);
+ struct sync_timeline *parent = sync_pt_parent(pt);
+
+ if (!parent->ops->timeline_value_str) {
+ if (size)
+ *str = 0;
+ return;
+ }
+ parent->ops->timeline_value_str(parent, str, size);
+}
+
+static const struct fence_ops android_fence_ops = {
+ .get_driver_name = android_fence_get_driver_name,
+ .get_timeline_name = android_fence_get_timeline_name,
+ .enable_signaling = android_fence_enable_signaling,
+ .disable_signaling = android_fence_disable_signaling,
+ .signaled = android_fence_signaled,
+ .wait = fence_default_wait,
+ .release = android_fence_release,
+ .fill_driver_data = android_fence_fill_driver_data,
+ .fence_value_str = android_fence_value_str,
+ .timeline_value_str = android_fence_timeline_value_str,
+};
+
+#if 0
+static void sync_fence_free(struct kref *kref)
+{
+ struct sync_fence *fence = container_of(kref, struct sync_fence, kref);
+ int i;
+
+ for (i = 0; i < fence->num_fences; ++i) {
+ fence_remove_callback(fence->cbs[i].sync_pt, &fence->cbs[i].cb);
+ fence_put(fence->cbs[i].sync_pt);
+ }
+
+ kfree(fence);
+}
+
+static int sync_fence_release(struct inode *inode, struct file *file)
+{
+ struct sync_fence *fence = file->private_data;
+
+ bsp_sync_fence_debug_remove(fence);
+
+ kref_put(&fence->kref, sync_fence_free);
+ return 0;
+}
+
+static unsigned int sync_fence_poll(struct file *file, poll_table *wait)
+{
+ struct sync_fence *fence = file->private_data;
+ int status;
+
+ poll_wait(file, &fence->wq, wait);
+
+ status = atomic_read(&fence->status);
+
+ if (!status)
+ return POLLIN;
+ else if (status < 0)
+ return POLLERR;
+ return 0;
+}
+
+static long sync_fence_ioctl_wait(struct sync_fence *fence, unsigned long arg)
+{
+ __s32 value;
+
+ if (copy_from_user(&value, (void __user *)arg, sizeof(value)))
+ return -EFAULT;
+
+ return bsp_sync_fence_wait(fence, value);
+}
+
+static long sync_fence_ioctl_merge(struct sync_fence *fence, unsigned long arg)
+{
+ int fd = get_unused_fd_flags(O_CLOEXEC);
+ int err;
+ struct sync_fence *fence2, *fence3;
+ struct sync_merge_data data;
+
+ if (fd < 0)
+ return fd;
+
+ if (copy_from_user(&data, (void __user *)arg, sizeof(data))) {
+ err = -EFAULT;
+ goto err_put_fd;
+ }
+
+ fence2 = bsp_sync_fence_fdget(data.fd2);
+ if (fence2 == NULL) {
+ err = -ENOENT;
+ goto err_put_fd;
+ }
+
+ data.name[sizeof(data.name) - 1] = '\0';
+ fence3 = bsp_sync_fence_merge(data.name, fence, fence2);
+ if (fence3 == NULL) {
+ err = -ENOMEM;
+ goto err_put_fence2;
+ }
+
+ data.fence = fd;
+ if (copy_to_user((void __user *)arg, &data, sizeof(data))) {
+ err = -EFAULT;
+ goto err_put_fence3;
+ }
+
+ bsp_sync_fence_install(fence3, fd);
+ bsp_sync_fence_put(fence2);
+ return 0;
+
+err_put_fence3:
+ bsp_sync_fence_put(fence3);
+
+err_put_fence2:
+ bsp_sync_fence_put(fence2);
+
+err_put_fd:
+ put_unused_fd(fd);
+ return err;
+}
+
+static int sync_fill_pt_info(struct fence *fence, void *data, int size)
+{
+ struct sync_pt_info *info = data;
+ int ret;
+
+ if (size < sizeof(struct sync_pt_info))
+ return -ENOMEM;
+
+ info->len = sizeof(struct sync_pt_info);
+
+ if (fence->ops->fill_driver_data) {
+ ret = fence->ops->fill_driver_data(fence, info->driver_data,
+ size - sizeof(*info));
+ if (ret < 0)
+ return ret;
+
+ info->len += ret;
+ }
+
+ strlcpy(info->obj_name, fence->ops->get_timeline_name(fence),
+ sizeof(info->obj_name));
+ strlcpy(info->driver_name, fence->ops->get_driver_name(fence),
+ sizeof(info->driver_name));
+ if (fence_is_signaled(fence))
+ info->status = fence->status >= 0 ? 1 : fence->status;
+ else
+ info->status = 0;
+ info->timestamp_ns = ktime_to_ns(fence->timestamp);
+
+ return info->len;
+}
+
+static long sync_fence_ioctl_fence_info(struct sync_fence *fence,
+ unsigned long arg)
+{
+ struct sync_fence_info_data *data;
+ __u32 size;
+ __u32 len = 0;
+ int ret, i;
+
+ if (copy_from_user(&size, (void __user *)arg, sizeof(size)))
+ return -EFAULT;
+
+ if (size < sizeof(struct sync_fence_info_data))
+ return -EINVAL;
+
+ if (size > 4096)
+ size = 4096;
+
+ data = kzalloc(size, GFP_KERNEL);
+ if (data == NULL)
+ return -ENOMEM;
+
+ strlcpy(data->name, fence->name, sizeof(data->name));
+ data->status = atomic_read(&fence->status);
+ if (data->status >= 0)
+ data->status = !data->status;
+
+ len = sizeof(struct sync_fence_info_data);
+
+ for (i = 0; i < fence->num_fences; ++i) {
+ struct fence *pt = fence->cbs[i].sync_pt;
+
+ ret = sync_fill_pt_info(pt, (u8 *)data + len, size - len);
+
+ if (ret < 0)
+ goto out;
+
+ len += ret;
+ }
+
+ data->len = len;
+
+ if (copy_to_user((void __user *)arg, data, len))
+ ret = -EFAULT;
+ else
+ ret = 0;
+
+out:
+ kfree(data);
+
+ return ret;
+}
+
+static long sync_fence_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ struct sync_fence *fence = file->private_data;
+
+ switch (cmd) {
+ case SYNC_IOC_WAIT:
+ return sync_fence_ioctl_wait(fence, arg);
+
+ case SYNC_IOC_MERGE:
+ return sync_fence_ioctl_merge(fence, arg);
+
+ case SYNC_IOC_FENCE_INFO:
+ return sync_fence_ioctl_fence_info(fence, arg);
+
+ default:
+ return -ENOTTY;
+ }
+}
+
+static const struct file_operations sync_fence_fops = {
+ .release = sync_fence_release,
+ .poll = sync_fence_poll,
+ .unlocked_ioctl = sync_fence_ioctl,
+ .compat_ioctl = sync_fence_ioctl,
+};
+#endif
+
diff -urN linux-4.9.37/drivers/fence/sync_debug.c linux-4.9.y/drivers/fence/sync_debug.c
--- linux-4.9.37/drivers/fence/sync_debug.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/fence/sync_debug.c 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,259 @@
+/*
+ * drivers/base/sync.c
+ *
+ * Copyright (C) 2012 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/debugfs.h>
+#include <linux/export.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/poll.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/anon_inodes.h>
+#include <linux/time64.h>
+#include "sync.h"
+
+#ifdef CONFIG_DEBUG_FS
+
+static LIST_HEAD(sync_timeline_list_head);
+static DEFINE_SPINLOCK(sync_timeline_list_lock);
+#if 0
+static LIST_HEAD(sync_fence_list_head);
+static DEFINE_SPINLOCK(sync_fence_list_lock);
+#endif
+
+void bsp_sync_timeline_debug_add(struct sync_timeline *obj)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&sync_timeline_list_lock, flags);
+ list_add_tail(&obj->sync_timeline_list, &sync_timeline_list_head);
+ spin_unlock_irqrestore(&sync_timeline_list_lock, flags);
+}
+
+void bsp_sync_timeline_debug_remove(struct sync_timeline *obj)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&sync_timeline_list_lock, flags);
+ list_del(&obj->sync_timeline_list);
+ spin_unlock_irqrestore(&sync_timeline_list_lock, flags);
+}
+
+#if 0
+void bsp_sync_fence_debug_add(struct sync_fence *fence)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&sync_fence_list_lock, flags);
+ list_add_tail(&fence->sync_fence_list, &sync_fence_list_head);
+ spin_unlock_irqrestore(&sync_fence_list_lock, flags);
+}
+
+void bsp_sync_fence_debug_remove(struct sync_fence *fence)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&sync_fence_list_lock, flags);
+ list_del(&fence->sync_fence_list);
+ spin_unlock_irqrestore(&sync_fence_list_lock, flags);
+}
+#endif
+
+static const char *sync_status_str(int status)
+{
+ if (status == 0)
+ return "signaled";
+
+ if (status > 0)
+ return "active";
+
+ return "error";
+}
+
+static void sync_print_pt(struct seq_file *s, struct sync_pt *pt, bool fence)
+{
+ int status = 1;
+ struct sync_timeline *parent = sync_pt_parent(pt);
+
+ if (fence_is_signaled_locked(&pt->base))
+ status = pt->base.status;
+
+ seq_printf(s, " %s%spt %s",
+ fence ? parent->name : "",
+ fence ? "_" : "",
+ sync_status_str(status));
+
+ if (status <= 0) {
+ struct timespec64 ts64 =
+ ktime_to_timespec64(pt->base.timestamp);
+
+ seq_printf(s, "@%lld.%09ld", (s64)ts64.tv_sec, ts64.tv_nsec);
+ }
+
+ if (parent->ops->timeline_value_str &&
+ parent->ops->pt_value_str) {
+ char value[64];
+
+ parent->ops->pt_value_str(pt, value, sizeof(value));
+ seq_printf(s, ": %s", value);
+ if (fence) {
+ parent->ops->timeline_value_str(parent, value,
+ sizeof(value));
+ seq_printf(s, " / %s", value);
+ }
+ }
+
+ seq_puts(s, "\n");
+}
+
+static void sync_print_obj(struct seq_file *s, struct sync_timeline *obj)
+{
+ struct list_head *pos = NULL;
+ unsigned long flags;
+
+ seq_printf(s, "%s %s", obj->name, obj->ops->driver_name);
+
+ if (obj->ops->timeline_value_str) {
+ char value[64];
+
+ obj->ops->timeline_value_str(obj, value, sizeof(value));
+ seq_printf(s, ": %s", value);
+ }
+
+ seq_puts(s, "\n");
+
+ spin_lock_irqsave(&obj->child_list_lock, flags);
+ list_for_each(pos, &obj->child_list_head) {
+ struct sync_pt *pt =
+ container_of(pos, struct sync_pt, child_list);
+ sync_print_pt(s, pt, false);
+ }
+ spin_unlock_irqrestore(&obj->child_list_lock, flags);
+}
+#if 0
+static void sync_print_fence(struct seq_file *s, struct sync_fence *fence)
+{
+ wait_queue_t *pos;
+ unsigned long flags;
+ int i;
+
+ seq_printf(s, "[%p] %s: %s\n", fence, fence->name,
+ sync_status_str(atomic_read(&fence->status)));
+
+ for (i = 0; i < fence->num_fences; ++i) {
+ struct sync_pt *pt =
+ container_of(fence->cbs[i].sync_pt,
+ struct sync_pt, base);
+
+ sync_print_pt(s, pt, true);
+ }
+
+ spin_lock_irqsave(&fence->wq.lock, flags);
+ list_for_each_entry(pos, &fence->wq.task_list, task_list) {
+ struct sync_fence_waiter *waiter;
+
+ if (pos->func != &bsp_sync_fence_wake_up_wq)
+ continue;
+
+ waiter = container_of(pos, struct sync_fence_waiter, work);
+
+ seq_printf(s, "waiter %pF\n", waiter->callback);
+ }
+ spin_unlock_irqrestore(&fence->wq.lock, flags);
+}
+#endif
+static int sync_debugfs_show(struct seq_file *s, void *unused)
+{
+ unsigned long flags;
+ struct list_head *pos = NULL;
+
+ seq_puts(s, "objs:\n--------------\n");
+
+ spin_lock_irqsave(&sync_timeline_list_lock, flags);
+ list_for_each(pos, &sync_timeline_list_head) {
+ struct sync_timeline *obj =
+ container_of(pos, struct sync_timeline,
+ sync_timeline_list);
+
+ sync_print_obj(s, obj);
+ seq_puts(s, "\n");
+ }
+ spin_unlock_irqrestore(&sync_timeline_list_lock, flags);
+
+ seq_puts(s, "fences:\n--------------\n");
+#if 0
+ spin_lock_irqsave(&sync_fence_list_lock, flags);
+ list_for_each(pos, &sync_fence_list_head) {
+ struct sync_fence *fence =
+ container_of(pos, struct sync_fence, sync_fence_list);
+
+ sync_print_fence(s, fence);
+ seq_puts(s, "\n");
+ }
+ spin_unlock_irqrestore(&sync_fence_list_lock, flags);
+#endif
+ return 0;
+}
+
+static int sync_debugfs_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, sync_debugfs_show, inode->i_private);
+}
+
+static const struct file_operations sync_debugfs_fops = {
+ .open = sync_debugfs_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int __init _sync_debugfs_init(void)
+{
+ debugfs_create_file("sync", S_IRUGO, NULL, NULL, &sync_debugfs_fops);
+ return 0;
+}
+module_init(_sync_debugfs_init);
+
+#define DUMP_CHUNK 256
+static char sync_dump_buf[64 * 1024];
+void bsp_sync_dump(void)
+{
+ struct seq_file s = {
+ .buf = sync_dump_buf,
+ .size = sizeof(sync_dump_buf) - 1,
+ };
+ int i;
+
+ sync_debugfs_show(&s, NULL);
+
+ for (i = 0; i < s.count; i += DUMP_CHUNK) {
+ if (((s.count - i) > DUMP_CHUNK) && (i + DUMP_CHUNK < sizeof(sync_dump_buf))) {
+ char c = s.buf[i + DUMP_CHUNK];
+
+ s.buf[i + DUMP_CHUNK] = 0;
+ pr_cont("%s", s.buf + i);
+ s.buf[i + DUMP_CHUNK] = c;
+ } else {
+ s.buf[s.count] = 0;
+ pr_cont("%s", s.buf + i);
+ }
+ }
+}
+
+#endif
diff -urN linux-4.9.37/drivers/fence/_sync.h linux-4.9.y/drivers/fence/_sync.h
--- linux-4.9.37/drivers/fence/_sync.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/fence/_sync.h 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2012 Google, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _UAPI_LINUX_SYNC_H
+#define _UAPI_LINUX_SYNC_H
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+/**
+ * struct sync_merge_data - data passed to merge ioctl
+ * @fd2: file descriptor of second fence
+ * @name: name of new fence
+ * @fence: returns the fd of the new fence to userspace
+ */
+struct sync_merge_data {
+ __s32 fd2; /* fd of second fence */
+ char name[32]; /* name of new fence */
+ __s32 fence; /* fd on newly created fence */
+};
+
+/**
+ * struct sync_pt_info - detailed sync_pt information
+ * @len: length of sync_pt_info including any driver_data
+ * @obj_name: name of parent sync_timeline
+ * @driver_name: name of driver implementing the parent
+ * @status: status of the sync_pt 0:active 1:signaled <0:error
+ * @timestamp_ns: timestamp of status change in nanoseconds
+ * @driver_data: any driver dependent data
+ */
+struct sync_pt_info {
+ __u32 len;
+ char obj_name[32];
+ char driver_name[32];
+ __s32 status;
+ __u64 timestamp_ns;
+
+ __u8 driver_data[0];
+};
+
+/**
+ * struct sync_fence_info_data - data returned from fence info ioctl
+ * @len: ioctl caller writes the size of the buffer its passing in.
+ * ioctl returns length of sync_fence_data returned to userspace
+ * including pt_info.
+ * @name: name of fence
+ * @status: status of fence. 1: signaled 0:active <0:error
+ * @pt_info: a sync_pt_info struct for every sync_pt in the fence
+ */
+struct sync_fence_info_data {
+ __u32 len;
+ char name[32];
+ __s32 status;
+
+ __u8 pt_info[0];
+};
+
+#define SYNC_IOC_MAGIC '>'
+
+/**
+ * DOC: SYNC_IOC_WAIT - wait for a fence to signal
+ *
+ * pass timeout in milliseconds. Waits indefinitely timeout < 0.
+ */
+#define SYNC_IOC_WAIT _IOW(SYNC_IOC_MAGIC, 0, __s32)
+
+/**
+ * DOC: SYNC_IOC_MERGE - merge two fences
+ *
+ * Takes a struct sync_merge_data. Creates a new fence containing copies of
+ * the sync_pts in both the calling fd and sync_merge_data.fd2. Returns the
+ * new fence's fd in sync_merge_data.fence
+ */
+#define SYNC_IOC_MERGE _IOWR(SYNC_IOC_MAGIC, 1, struct sync_merge_data)
+
+/**
+ * DOC: SYNC_IOC_FENCE_INFO - get detailed information on a fence
+ *
+ * Takes a struct sync_fence_info_data with extra space allocated for pt_info.
+ * Caller should write the size of the buffer into len. On return, len is
+ * updated to reflect the total size of the sync_fence_info_data including
+ * pt_info.
+ *
+ * pt_info is a buffer containing sync_pt_infos for every sync_pt in the fence.
+ * To iterate over the sync_pt_infos, use the sync_pt_info.len field.
+ */
+#define SYNC_IOC_FENCE_INFO _IOWR(SYNC_IOC_MAGIC, 2,\
+ struct sync_fence_info_data)
+
+#endif /* _UAPI_LINUX_SYNC_H */
diff -urN linux-4.9.37/drivers/fence/sync.h linux-4.9.y/drivers/fence/sync.h
--- linux-4.9.37/drivers/fence/sync.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/fence/sync.h 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,363 @@
+/*
+ * include/linux/sync.h
+ *
+ * Copyright (C) 2012 Google, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _LINUX_SYNC_H
+#define _LINUX_SYNC_H
+
+#include <linux/types.h>
+#include <linux/kref.h>
+#include <linux/ktime.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
+#include <linux/fence.h>
+
+#include "_sync.h"
+
+struct sync_timeline;
+struct sync_pt;
+#if 0
+struct sync_fence;
+#endif
+
+/**
+ * struct sync_timeline_ops - sync object implementation ops
+ * @driver_name: name of the implementation
+ * @dup: duplicate a sync_pt
+ * @has_signaled: returns:
+ * 1 if pt has signaled
+ * 0 if pt has not signaled
+ * <0 on error
+ * @compare: returns:
+ * 1 if b will signal before a
+ * 0 if a and b will signal at the same time
+ * -1 if a will signal before b
+ * @free_pt: called before sync_pt is freed
+ * @release_obj: called before sync_timeline is freed
+ * @fill_driver_data: write implementation specific driver data to data.
+ * should return an error if there is not enough room
+ * as specified by size. This information is returned
+ * to userspace by SYNC_IOC_FENCE_INFO.
+ * @timeline_value_str: fill str with the value of the sync_timeline's counter
+ * @pt_value_str: fill str with the value of the sync_pt
+ */
+struct sync_timeline_ops {
+ const char *driver_name;
+
+ /* required */
+ struct sync_pt * (*dup)(struct sync_pt *pt);
+
+ /* required */
+ int (*has_signaled)(struct sync_pt *pt);
+
+ /* required */
+ int (*compare)(struct sync_pt *a, struct sync_pt *b);
+
+ /* optional */
+ void (*free_pt)(struct sync_pt *sync_pt);
+
+ /* optional */
+ void (*release_obj)(struct sync_timeline *sync_timeline);
+
+ /* optional */
+ int (*fill_driver_data)(struct sync_pt *syncpt, void *data, int size);
+
+ /* optional */
+ void (*timeline_value_str)(struct sync_timeline *timeline, char *str,
+ int size);
+
+ /* optional */
+ void (*pt_value_str)(struct sync_pt *pt, char *str, int size);
+};
+
+/**
+ * struct sync_timeline - sync object
+ * @kref: reference count on fence.
+ * @ops: ops that define the implementation of the sync_timeline
+ * @name: name of the sync_timeline. Useful for debugging
+ * @destroyed: set when sync_timeline is destroyed
+ * @child_list_head: list of children sync_pts for this sync_timeline
+ * @child_list_lock: lock protecting @child_list_head, destroyed, and
+ * sync_pt.status
+ * @active_list_head: list of active (unsignaled/errored) sync_pts
+ * @sync_timeline_list: membership in global sync_timeline_list
+ */
+struct sync_timeline {
+ struct kref kref;
+ const struct sync_timeline_ops *ops;
+ char name[32];
+
+ /* protected by child_list_lock */
+ bool destroyed;
+ int context, value;
+
+ struct list_head child_list_head;
+ spinlock_t child_list_lock;
+
+ struct list_head active_list_head;
+
+#ifdef CONFIG_DEBUG_FS
+ struct list_head sync_timeline_list;
+#endif
+};
+
+/**
+ * struct sync_pt - sync point
+ * @fence: base fence class
+ * @child_list: membership in sync_timeline.child_list_head
+ * @active_list: membership in sync_timeline.active_list_head
+ * @signaled_list: membership in temporary signaled_list on stack
+ * @fence: sync_fence to which the sync_pt belongs
+ * @pt_list: membership in sync_fence.pt_list_head
+ * @status: 1: signaled, 0:active, <0: error
+ * @timestamp: time which sync_pt status transitioned from active to
+ * signaled or error.
+ */
+struct sync_pt {
+ struct fence base;
+
+ struct list_head child_list;
+ struct list_head active_list;
+};
+
+static inline struct sync_timeline *sync_pt_parent(struct sync_pt *pt)
+{
+ return container_of(pt->base.lock, struct sync_timeline,
+ child_list_lock);
+}
+
+#if 0
+struct sync_fence_cb {
+ struct fence_cb cb;
+ struct fence *sync_pt;
+ struct sync_fence *fence;
+};
+
+/**
+ * struct sync_fence - sync fence
+ * @file: file representing this fence
+ * @kref: reference count on fence.
+ * @name: name of sync_fence. Useful for debugging
+ * @pt_list_head: list of sync_pts in the fence. immutable once fence
+ * is created
+ * @status: 0: signaled, >0:active, <0: error
+ *
+ * @wq: wait queue for fence signaling
+ * @sync_fence_list: membership in global fence list
+ */
+struct sync_fence {
+ struct file *file;
+ struct kref kref;
+ char name[32];
+#ifdef CONFIG_DEBUG_FS
+ struct list_head sync_fence_list;
+#endif
+ int num_fences;
+
+ wait_queue_head_t wq;
+ atomic_t status;
+
+ struct sync_fence_cb cbs[];
+};
+
+struct sync_fence_waiter;
+typedef void (*sync_callback_t)(struct sync_fence *fence,
+ struct sync_fence_waiter *waiter);
+
+/**
+ * struct sync_fence_waiter - metadata for asynchronous waiter on a fence
+ * @waiter_list: membership in sync_fence.waiter_list_head
+ * @callback: function pointer to call when fence signals
+ * @callback_data: pointer to pass to @callback
+ */
+struct sync_fence_waiter {
+ wait_queue_t work;
+ sync_callback_t callback;
+};
+
+static inline void sync_fence_waiter_init(struct sync_fence_waiter *waiter,
+ sync_callback_t callback)
+{
+ INIT_LIST_HEAD(&waiter->work.task_list);
+ waiter->callback = callback;
+}
+#endif
+
+/*
+ * API for sync_timeline implementers
+ */
+
+/**
+ * sync_timeline_create() - creates a sync object
+ * @ops: specifies the implementation ops for the object
+ * @size: size to allocate for this obj
+ * @name: sync_timeline name
+ *
+ * Creates a new sync_timeline which will use the implementation specified by
+ * @ops. @size bytes will be allocated allowing for implementation specific
+ * data to be kept after the generic sync_timeline struct.
+ */
+struct sync_timeline *bsp_sync_timeline_create(const struct sync_timeline_ops *ops,
+ int size, const char *name);
+
+/**
+ * sync_timeline_destroy() - destroys a sync object
+ * @obj: sync_timeline to destroy
+ *
+ * A sync implementation should call this when the @obj is going away
+ * (i.e. module unload.) @obj won't actually be freed until all its children
+ * sync_pts are freed.
+ */
+void bsp_sync_timeline_destroy(struct sync_timeline *obj);
+
+/**
+ * sync_timeline_signal() - signal a status change on a sync_timeline
+ * @obj: sync_timeline to signal
+ *
+ * A sync implementation should call this any time one of it's sync_pts
+ * has signaled or has an error condition.
+ */
+void bsp_sync_timeline_signal(struct sync_timeline *obj);
+
+/**
+ * sync_pt_create() - creates a sync pt
+ * @parent: sync_pt's parent sync_timeline
+ * @size: size to allocate for this pt
+ *
+ * Creates a new sync_pt as a child of @parent. @size bytes will be
+ * allocated allowing for implementation specific data to be kept after
+ * the generic sync_timeline struct.
+ */
+struct sync_pt *bsp_sync_pt_create(struct sync_timeline *parent, int size);
+
+/**
+ * sync_pt_free() - frees a sync pt
+ * @pt: sync_pt to free
+ *
+ * This should only be called on sync_pts which have been created but
+ * not added to a fence.
+ */
+void bsp_sync_pt_free(struct sync_pt *pt);
+
+#if 0
+/**
+ * sync_fence_create() - creates a sync fence
+ * @name: name of fence to create
+ * @pt: sync_pt to add to the fence
+ *
+ * Creates a fence containg @pt. Once this is called, the fence takes
+ * ownership of @pt.
+ */
+struct sync_fence *bsp_sync_fence_create(const char *name, struct sync_pt *pt);
+
+/*
+ * API for sync_fence consumers
+ */
+
+/**
+ * sync_fence_merge() - merge two fences
+ * @name: name of new fence
+ * @a: fence a
+ * @b: fence b
+ *
+ * Creates a new fence which contains copies of all the sync_pts in both
+ * @a and @b. @a and @b remain valid, independent fences.
+ */
+struct sync_fence *bsp_sync_fence_merge(const char *name,
+ struct sync_fence *a, struct sync_fence *b);
+
+/**
+ * sync_fence_fdget() - get a fence from an fd
+ * @fd: fd referencing a fence
+ *
+ * Ensures @fd references a valid fence, increments the refcount of the backing
+ * file, and returns the fence.
+ */
+struct sync_fence *bsp_sync_fence_fdget(int fd);
+
+/**
+ * sync_fence_put() - puts a reference of a sync fence
+ * @fence: fence to put
+ *
+ * Puts a reference on @fence. If this is the last reference, the fence and
+ * all it's sync_pts will be freed
+ */
+void bsp_sync_fence_put(struct sync_fence *fence);
+
+/**
+ * sync_fence_install() - installs a fence into a file descriptor
+ * @fence: fence to install
+ * @fd: file descriptor in which to install the fence
+ *
+ * Installs @fence into @fd. @fd's should be acquired through
+ * get_unused_fd_flags(O_CLOEXEC).
+ */
+void bsp_sync_fence_install(struct sync_fence *fence, int fd);
+
+/**
+ * sync_fence_wait_async() - registers and async wait on the fence
+ * @fence: fence to wait on
+ * @waiter: waiter callback struck
+ *
+ * Returns 1 if @fence has already signaled.
+ *
+ * Registers a callback to be called when @fence signals or has an error.
+ * @waiter should be initialized with sync_fence_waiter_init().
+ */
+int bsp_sync_fence_wait_async(struct sync_fence *fence,
+ struct sync_fence_waiter *waiter);
+
+/**
+ * sync_fence_cancel_async() - cancels an async wait
+ * @fence: fence to wait on
+ * @waiter: waiter callback struck
+ *
+ * returns 0 if waiter was removed from fence's async waiter list.
+ * returns -ENOENT if waiter was not found on fence's async waiter list.
+ *
+ * Cancels a previously registered async wait. Will fail gracefully if
+ * @waiter was never registered or if @fence has already signaled @waiter.
+ */
+int bsp_sync_fence_cancel_async(struct sync_fence *fence,
+ struct sync_fence_waiter *waiter);
+
+/**
+ * sync_fence_wait() - wait on fence
+ * @fence: fence to wait on
+ * @tiemout: timeout in ms
+ *
+ * Wait for @fence to be signaled or have an error. Waits indefinitely
+ * if @timeout < 0
+ */
+int bsp_sync_fence_wait(struct sync_fence *fence, long timeout);
+
+#ifdef CONFIG_DEBUG_FS
+
+void bsp_sync_timeline_debug_add(struct sync_timeline *obj);
+void bsp_sync_timeline_debug_remove(struct sync_timeline *obj);
+void bsp_sync_fence_debug_add(struct sync_fence *fence);
+void bsp_sync_fence_debug_remove(struct sync_fence *fence);
+void bsp_sync_dump(void);
+
+#else
+# define bsp_sync_timeline_debug_add(obj)
+# define bsp_sync_timeline_debug_remove(obj)
+# define bsp_sync_fence_debug_add(fence)
+# define bsp_sync_fence_debug_remove(fence)
+# define bsp_sync_dump()
+#endif
+int bsp_sync_fence_wake_up_wq(wait_queue_t *curr, unsigned mode,
+ int wake_flags, void *key);
+
+#endif
+
+#endif /* _LINUX_SYNC_H */
diff -urN linux-4.9.37/drivers/firmware/psci.c linux-4.9.y/drivers/firmware/psci.c
--- linux-4.9.37/drivers/firmware/psci.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/firmware/psci.c 2021-06-07 13:01:33.000000000 +0300
@@ -59,7 +59,9 @@
return cpu == resident_cpu;
}
-struct psci_operations psci_ops;
+struct psci_operations psci_ops = {
+ .conduit = PSCI_CONDUIT_NONE,
+};
typedef unsigned long (psci_fn)(unsigned long, unsigned long,
unsigned long, unsigned long);
@@ -210,6 +212,22 @@
0, 0, 0);
}
+static void set_conduit(enum psci_conduit conduit)
+{
+ switch (conduit) {
+ case PSCI_CONDUIT_HVC:
+ invoke_psci_fn = __invoke_psci_fn_hvc;
+ break;
+ case PSCI_CONDUIT_SMC:
+ invoke_psci_fn = __invoke_psci_fn_smc;
+ break;
+ default:
+ WARN(1, "Unexpected PSCI conduit %d\n", conduit);
+ }
+
+ psci_ops.conduit = conduit;
+}
+
static int get_set_conduit_method(struct device_node *np)
{
const char *method;
@@ -222,9 +240,9 @@
}
if (!strcmp("hvc", method)) {
- invoke_psci_fn = __invoke_psci_fn_hvc;
+ set_conduit(PSCI_CONDUIT_HVC);
} else if (!strcmp("smc", method)) {
- invoke_psci_fn = __invoke_psci_fn_smc;
+ set_conduit(PSCI_CONDUIT_SMC);
} else {
pr_warn("invalid \"method\" property: %s\n", method);
return -EINVAL;
@@ -496,6 +514,8 @@
static void __init psci_0_2_set_functions(void)
{
pr_info("Using standard PSCI v0.2 function IDs\n");
+ psci_ops.get_version = psci_get_version;
+
psci_function_id[PSCI_FN_CPU_SUSPEND] =
PSCI_FN_NATIVE(0_2, CPU_SUSPEND);
psci_ops.cpu_suspend = psci_cpu_suspend;
@@ -652,9 +672,9 @@
pr_info("probing for conduit method from ACPI.\n");
if (acpi_psci_use_hvc())
- invoke_psci_fn = __invoke_psci_fn_hvc;
+ set_conduit(PSCI_CONDUIT_HVC);
else
- invoke_psci_fn = __invoke_psci_fn_smc;
+ set_conduit(PSCI_CONDUIT_SMC);
return psci_probe();
}
diff -urN linux-4.9.37/drivers/goke/cma/cma.c linux-4.9.y/drivers/goke/cma/cma.c
--- linux-4.9.37/drivers/goke/cma/cma.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/goke/cma/cma.c 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+#include <linux/goke_cma.h>
+
+static u32 num_zones;
+static struct cma_zone zone[ZONE_MAX];
+static int use_bootargs;
+
+unsigned int get_cma_size(void)
+{
+ int i;
+ u64 total = 0;
+
+ for (i = 0; i < num_zones; i++) {
+ total += zone[i].nbytes;
+ }
+
+ /* unit is M */
+ return (unsigned int)(total >> 20);
+}
+
+int is_cma_address(phys_addr_t phys, unsigned long size)
+{
+ phys_addr_t start, end;
+ int i;
+
+ for (i = 0; i < num_zones; i++) {
+ start = zone[i].phys_start;
+ end = zone[i].phys_start + zone[i].nbytes;
+
+ if ((phys >= start) && ((phys + size) <= end)) {
+ /*
+ * Yes, found!
+ */
+ return 1;
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(is_cma_address);
+
+static int __init mmz_parse_cmdline(char *s)
+{
+ char *line = NULL;
+ char *tmp = NULL;
+ char tmpline[256];
+
+ if (s == NULL) {
+ pr_info("There is no cma zone!\n");
+ return 0;
+ }
+ strncpy(tmpline, s, sizeof(tmpline));
+ tmpline[sizeof(tmpline) - 1] = '\0';
+ tmp = tmpline;
+
+ while ((line = strsep(&tmp, ":")) != NULL) {
+ int i;
+ char *argv[6];
+
+ for (i = 0; (argv[i] = strsep(&line, ",")) != NULL;)
+ if (++i == ARRAY_SIZE(argv)) {
+ break;
+ }
+
+ zone[num_zones].pdev.coherent_dma_mask = DMA_BIT_MASK(64);
+ if (i == 4) {
+ strlcpy(zone[num_zones].name, argv[0], NAME_LEN_MAX);
+ zone[num_zones].gfp = memparse(argv[1], NULL);
+ zone[num_zones].phys_start = memparse(argv[2], NULL);
+ zone[num_zones].nbytes = memparse(argv[3], NULL);
+ }
+
+ else if (i == 6) {
+ strlcpy(zone[num_zones].name, argv[0], NAME_LEN_MAX);
+ zone[num_zones].gfp = memparse(argv[1], NULL);
+ zone[num_zones].phys_start = memparse(argv[2], NULL);
+ zone[num_zones].nbytes = memparse(argv[3], NULL);
+ zone[num_zones].alloc_type = memparse(argv[4], NULL);
+ zone[num_zones].block_align = memparse(argv[5], NULL);
+ } else {
+ pr_err("ion parameter is not correct\n");
+ continue;
+ }
+
+ num_zones++;
+ }
+ if (num_zones != 0) {
+ use_bootargs = 1;
+ }
+
+ return 0;
+}
+early_param("mmz", mmz_parse_cmdline);
+
+phys_addr_t goke_get_zones_start(void)
+{
+ int i;
+ phys_addr_t lowest_zone_base = memblock_end_of_DRAM();
+
+ for (i = 0; i < num_zones; i++) {
+ if (lowest_zone_base > zone[i].phys_start) {
+ lowest_zone_base = zone[i].phys_start;
+ }
+ }
+
+ return lowest_zone_base;
+}
+EXPORT_SYMBOL(goke_get_zones_start);
+
+struct cma_zone *goke_get_cma_zone(const char *name)
+{
+ int i = 0;
+
+ for (i = 0; i < num_zones; i++)
+ if (strcmp(zone[i].name, name) == 0) {
+ break;
+ }
+
+ if (i == num_zones) {
+ return NULL;
+ }
+
+ return &zone[i];
+}
+EXPORT_SYMBOL(goke_get_cma_zone);
+
+struct device *goke_get_cma_device(const char *name)
+{
+ int i = 0;
+
+ for (i = 0; i < num_zones; i++)
+ if (strcmp(zone[i].name, name) == 0) {
+ break;
+ }
+
+ if (i == num_zones) {
+ return NULL;
+ }
+
+ return &zone[i].pdev;
+}
+EXPORT_SYMBOL(goke_get_cma_device);
+
+int __init goke_declare_heap_memory(void)
+{
+ int i;
+ int ret = 0;
+
+ if (use_bootargs == 0) {
+ pr_info("cma zone is not set!\n");
+ return ret;
+ }
+
+ for (i = 0; i < num_zones; i++) {
+ ret = dma_declare_contiguous(&zone[i].pdev,
+ zone[i].nbytes, zone[i].phys_start, 0);
+ if (ret) {
+ panic("declare cma zone %s base: %lux size:%lux MB failed. ret:%d",
+ zone[i].name, (unsigned long)zone[i].phys_start,
+ (unsigned long)zone[i].nbytes >> 20, ret);
+ }
+ zone[i].phys_start = cma_get_base(zone[i].pdev.cma_area);
+ zone[i].nbytes = cma_get_size(zone[i].pdev.cma_area);
+
+ /* FIXME need to fix dma_declare_contiguous return value &&value type */
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(goke_declare_heap_memory);
+
+static int mmz_setup(struct reserved_mem *rmem)
+{
+ return 0;
+}
+RESERVEDMEM_OF_DECLARE(cma, "mmz", mmz_setup);
diff -urN linux-4.9.37/drivers/goke/cma/Kconfig linux-4.9.y/drivers/goke/cma/Kconfig
--- linux-4.9.37/drivers/goke/cma/Kconfig 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/goke/cma/Kconfig 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,16 @@
+
+config CMA_MEM_SHARED
+ bool "Support sharing CMA memory with the heap"
+ depends on CMA && DMA_CMA
+ default no
+ help
+ Support sharing CMA memory with the heap.
+
+config CMA_ADVANCE_SHARE
+ bool "Support cma advance share"
+ depends on CMA && DMA_CMA
+ select CMA_MEM_SHARED
+ default no
+ help
+ Support advance sharing CMA memory with the heap.
+ CMA Multiplex Ratio will be improved when this macro defined.
diff -urN linux-4.9.37/drivers/goke/cma/Makefile linux-4.9.y/drivers/goke/cma/Makefile
--- linux-4.9.37/drivers/goke/cma/Makefile 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/goke/cma/Makefile 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,2 @@
+
+obj-$(CONFIG_CMA) += cma.o
diff -urN linux-4.9.37/drivers/goke/Kconfig linux-4.9.y/drivers/goke/Kconfig
--- linux-4.9.37/drivers/goke/Kconfig 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/goke/Kconfig 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,4 @@
+menu "goke driver support"
+
+source "drivers/goke/cma/Kconfig"
+endmenu
diff -urN linux-4.9.37/drivers/goke/Makefile linux-4.9.y/drivers/goke/Makefile
--- linux-4.9.37/drivers/goke/Makefile 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/goke/Makefile 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1 @@
+obj-$(CONFIG_CMA) += cma/
diff -urN linux-4.9.37/drivers/gpio/gpio-pl061.c linux-4.9.y/drivers/gpio/gpio-pl061.c
--- linux-4.9.37/drivers/gpio/gpio-pl061.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/gpio/gpio-pl061.c 2021-06-07 13:01:33.000000000 +0300
@@ -208,6 +208,25 @@
return 0;
}
+#ifdef CONFIG_ARCH_GOKE
+static irqreturn_t pl061_irq_handler(int irq, void *data)
+{
+ unsigned long pending;
+ int offset;
+ struct gpio_chip *gc = data;
+ struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
+
+ pending = readb(chip->base + GPIOMIS);
+ writeb(pending, chip->base + GPIOIC);
+ if (pending) {
+ for_each_set_bit(offset, &pending, PL061_GPIO_NR)
+ generic_handle_irq(irq_find_mapping(gc->irqdomain,
+ offset));
+ }
+
+ return IRQ_HANDLED;
+}
+#else
static void pl061_irq_handler(struct irq_desc *desc)
{
unsigned long pending;
@@ -227,6 +246,7 @@
chained_irq_exit(irqchip, desc);
}
+#endif
static void pl061_irq_mask(struct irq_data *d)
{
@@ -308,7 +328,17 @@
return -ENODEV;
}
} else {
+#ifdef CONFIG_ARCH_GOKE
+ if (dev->of_node) {
+ i = of_alias_get_id(dev->of_node, "gpio");
+ chip->gc.base = i * PL061_GPIO_NR;
+ }
+
+ if (chip->gc.base < 0)
+ chip->gc.base = -1;
+#else
chip->gc.base = -1;
+#endif
irq_base = 0;
}
@@ -353,8 +383,21 @@
dev_info(&adev->dev, "could not add irqchip\n");
return ret;
}
+#ifdef CONFIG_ARCH_GOKE
+ ret = devm_request_irq(dev, irq, pl061_irq_handler, IRQF_SHARED,
+ dev_name(dev), &chip->gc);
+ if (ret) {
+ dev_info(dev, "request irq failed: %d\n", ret);
+ return ret;
+ }
+
+ /* Set the parent IRQ for all affected IRQs */
+ for (i = 0; i < chip->gc.ngpio; i++)
+ irq_set_parent(irq_find_mapping(chip->gc.irqdomain, i), irq);
+#else
gpiochip_set_chained_irqchip(&chip->gc, &pl061_irqchip,
irq, pl061_irq_handler);
+#endif
for (i = 0; i < PL061_GPIO_NR; i++) {
if (pdata) {
diff -urN linux-4.9.37/drivers/gpu/drm/radeon/.gitignore linux-4.9.y/drivers/gpu/drm/radeon/.gitignore
--- linux-4.9.37/drivers/gpu/drm/radeon/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/gpu/drm/radeon/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,3 +0,0 @@
-mkregtable
-*_reg_safe.h
-
diff -urN linux-4.9.37/drivers/i2c/busses/i2c-goke.c linux-4.9.y/drivers/i2c/busses/i2c-goke.c
--- linux-4.9.37/drivers/i2c/busses/i2c-goke.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/i2c/busses/i2c-goke.c 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,967 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+
+/*
+ * I2C Registers offsets
+ */
+#define GOKE_I2C_GLB 0x0
+#define GOKE_I2C_SCL_H 0x4
+#define GOKE_I2C_SCL_L 0x8
+#define GOKE_I2C_DATA1 0x10
+#define GOKE_I2C_TXF 0x20
+#define GOKE_I2C_RXF 0x24
+#define GOKE_I2C_CMD_BASE 0x30
+#define GOKE_I2C_LOOP1 0xb0
+#define GOKE_I2C_DST1 0xb4
+#define GOKE_I2C_TX_WATER 0xc8
+#define GOKE_I2C_RX_WATER 0xcc
+#define GOKE_I2C_CTRL1 0xd0
+#define GOKE_I2C_CTRL2 0xd4
+#define GOKE_I2C_STAT 0xd8
+#define GOKE_I2C_INTR_RAW 0xe0
+#define GOKE_I2C_INTR_EN 0xe4
+#define GOKE_I2C_INTR_STAT 0xe8
+
+/*
+ * I2C Global Config Register -- GOKE_I2C_GLB
+ */
+#define GLB_EN_MASK BIT(0)
+#define GLB_SDA_HOLD_MASK GENMASK(23, 8)
+#define GLB_SDA_HOLD_SHIFT (8)
+
+/*
+ * I2C Timing CMD Register -- GOKE_I2C_CMD_BASE + n * 4 (n = 0, 1, 2, ... 31)
+ */
+#define CMD_EXIT 0x0
+#define CMD_TX_S 0x1
+#define CMD_TX_D1_2 0x4
+#define CMD_TX_D1_1 0x5
+#define CMD_TX_FIFO 0x9
+#define CMD_RX_FIFO 0x12
+#define CMD_RX_ACK 0x13
+#define CMD_IGN_ACK 0x15
+#define CMD_TX_ACK 0x16
+#define CMD_TX_NACK 0x17
+#define CMD_JMP1 0x18
+#define CMD_UP_TXF 0x1d
+#define CMD_TX_RS 0x1e
+#define CMD_TX_P 0x1f
+
+/*
+ * I2C Control Register 1 -- GOKE_I2C_CTRL1
+ */
+#define CTRL1_CMD_START_MASK BIT(0)
+#define CTRL1_DMA_OP_MASK (0x3 << 8)
+#define CTRL1_DMA_R (0x3 << 8)
+#define CTRL1_DMA_W (0x2 << 8)
+
+/*
+ * I2C Status Register -- GOKE_I2C_STAT
+ */
+#define STAT_RXF_NOE_MASK BIT(16) /* RX FIFO not empty flag */
+#define STAT_TXF_NOF_MASK BIT(19) /* TX FIFO not full flag */
+
+
+/*
+ * I2C Interrupt status and mask Register --
+ * GOKE_I2C_INTR_RAW, GOKE_I2C_STAT, GOKE_I2C_INTR_STAT
+ */
+#define INTR_ABORT_MASK (BIT(0) | BIT(11))
+#define INTR_RX_MASK BIT(2)
+#define INTR_TX_MASK BIT(4)
+#define INTR_CMD_DONE_MASK BIT(12)
+#define INTR_USE_MASK (INTR_ABORT_MASK \
+ |INTR_RX_MASK \
+ | INTR_TX_MASK \
+ | INTR_CMD_DONE_MASK)
+#define INTR_ALL_MASK GENMASK(31, 0)
+
+#define I2C_DEFAULT_FREQUENCY 100000
+#define I2C_TXF_DEPTH 64
+#define I2C_RXF_DEPTH 64
+#define I2C_TXF_WATER 32
+#define I2C_RXF_WATER 32
+#define I2C_WAIT_TIMEOUT 0x400
+#define I2C_IRQ_TIMEOUT (msecs_to_jiffies(1000))
+
+
+struct goke_i2c_dev {
+ struct device *dev;
+ struct i2c_adapter adap;
+ resource_size_t phybase;
+ void __iomem *base;
+ struct clk *clk;
+ int irq;
+
+ unsigned int freq;
+ struct i2c_msg *msg;
+ unsigned int msg_num;
+ unsigned int msg_idx;
+ unsigned int msg_buf_ptr;
+ struct completion msg_complete;
+
+ spinlock_t lock;
+ int status;
+};
+static inline void goke_i2c_disable(struct goke_i2c_dev *i2c);
+static inline void goke_i2c_cfg_irq(struct goke_i2c_dev *i2c,
+ unsigned int flag);
+static inline unsigned int goke_i2c_clr_irq(struct goke_i2c_dev *i2c);
+static inline void goke_i2c_enable(struct goke_i2c_dev *i2c);
+
+#define CHECK_SDA_IN_SHIFT (16)
+#define GPIO_MODE_SHIFT (8)
+#define FORCE_SCL_OEN_SHIFT (4)
+#define FORCE_SDA_OEN_SHIFT (0)
+
+static void goke_i2c_rescue(struct goke_i2c_dev *i2c)
+{
+ unsigned int val;
+ unsigned int time_cnt;
+ int index;
+
+ goke_i2c_disable(i2c);
+ goke_i2c_cfg_irq(i2c, 0);
+ goke_i2c_clr_irq(i2c);
+
+ val = (0x1 << GPIO_MODE_SHIFT) | (0x1 << FORCE_SCL_OEN_SHIFT) | (0x1 << FORCE_SDA_OEN_SHIFT);
+ writel(val, i2c->base + GOKE_I2C_CTRL2);
+
+ time_cnt = 0;
+ do {
+ for (index = 0; index < 9; index++) {
+ val = (0x1 << GPIO_MODE_SHIFT) | 0x1;
+ writel(val, i2c->base + GOKE_I2C_CTRL2);
+
+ udelay(5);
+
+ val = (0x1 << GPIO_MODE_SHIFT) | (0x1 << FORCE_SCL_OEN_SHIFT) | (0x1 << FORCE_SDA_OEN_SHIFT);
+ writel(val, i2c->base + GOKE_I2C_CTRL2);
+
+ udelay(5);
+ }
+
+ time_cnt++;
+ if (time_cnt > I2C_WAIT_TIMEOUT) {
+ dev_err(i2c->dev, "wait Timeout!\n");
+ goto disable_rescue;
+ }
+
+ val = readl(i2c->base + GOKE_I2C_CTRL2);
+ } while(!(val & (0x1 << CHECK_SDA_IN_SHIFT)));
+
+
+ val = (0x1 << GPIO_MODE_SHIFT) | (0x1 << FORCE_SCL_OEN_SHIFT) | (0x1 << FORCE_SDA_OEN_SHIFT);
+ writel(val, i2c->base + GOKE_I2C_CTRL2);
+
+ val = (0x1 << GPIO_MODE_SHIFT) | (0x1 << FORCE_SCL_OEN_SHIFT);
+ writel(val, i2c->base + GOKE_I2C_CTRL2);
+
+ udelay(10);
+
+ val = (0x1 << GPIO_MODE_SHIFT) | (0x1 << FORCE_SCL_OEN_SHIFT) | (0x1 << FORCE_SDA_OEN_SHIFT);
+ writel(val, i2c->base + GOKE_I2C_CTRL2);
+
+disable_rescue:
+ val = (0x1 << FORCE_SCL_OEN_SHIFT) | 0x1;
+ writel(val, i2c->base + GOKE_I2C_CTRL2);
+}
+
+static inline void goke_i2c_disable(struct goke_i2c_dev *i2c)
+{
+ unsigned int val;
+
+ val = readl(i2c->base + GOKE_I2C_GLB);
+ val &= ~GLB_EN_MASK;
+ writel(val, i2c->base + GOKE_I2C_GLB);
+}
+
+static inline void goke_i2c_enable(struct goke_i2c_dev *i2c)
+{
+ unsigned int val;
+
+ val = readl(i2c->base + GOKE_I2C_GLB);
+ val |= GLB_EN_MASK;
+ writel(val, i2c->base + GOKE_I2C_GLB);
+}
+
+static inline void goke_i2c_cfg_irq(struct goke_i2c_dev *i2c,
+ unsigned int flag)
+{
+ writel(flag, i2c->base + GOKE_I2C_INTR_EN);
+}
+
+static inline void goke_i2c_disable_irq(struct goke_i2c_dev *i2c,
+ unsigned int flag)
+{
+ unsigned int val;
+
+ val = readl(i2c->base + GOKE_I2C_INTR_EN);
+ val &= ~flag;
+ writel(val, i2c->base + GOKE_I2C_INTR_EN);
+}
+
+static inline unsigned int goke_i2c_clr_irq(struct goke_i2c_dev *i2c)
+{
+ unsigned int val;
+
+ val = readl(i2c->base + GOKE_I2C_INTR_STAT);
+ writel(INTR_ALL_MASK, i2c->base + GOKE_I2C_INTR_RAW);
+
+ return val;
+}
+
+static inline void goke_i2c_cmdreg_set(struct goke_i2c_dev *i2c,
+ unsigned int cmd, unsigned int *offset)
+{
+ dev_dbg(i2c->dev, "i2c reg: offset=0x%x, cmd=0x%x...\n",
+ *offset * 4, cmd);
+ writel(cmd, i2c->base + GOKE_I2C_CMD_BASE + *offset * 4);
+ (*offset)++;
+}
+
+/*
+ * config i2c slave addr
+ */
+static inline void goke_i2c_set_addr(struct goke_i2c_dev *i2c)
+{
+ struct i2c_msg *msg = i2c->msg;
+ u16 addr;
+
+ if (msg->flags & I2C_M_TEN) {
+ /* First byte is 11110XX0 where XX is upper 2 bits */
+ addr = ((msg->addr & 0x300) << 1) | 0xf000;
+ if (msg->flags & I2C_M_RD) {
+ addr |= 1 << 8;
+ }
+
+ /* Second byte is the remaining 8 bits */
+ addr |= msg->addr & 0xff;
+ } else {
+ addr = (msg->addr & 0x7f) << 1;
+ if (msg->flags & I2C_M_RD) {
+ addr |= 1;
+ }
+ }
+
+ writel(addr, i2c->base + GOKE_I2C_DATA1);
+}
+
+/*
+ * Start command sequence
+ */
+static inline void goke_i2c_start_cmd(struct goke_i2c_dev *i2c)
+{
+ unsigned int val;
+
+ val = readl(i2c->base + GOKE_I2C_CTRL1);
+ val |= CTRL1_CMD_START_MASK;
+ writel(val, i2c->base + GOKE_I2C_CTRL1);
+}
+
+static int goke_i2c_wait_rx_noempty(struct goke_i2c_dev *i2c)
+{
+ unsigned int time_cnt = 0;
+ unsigned int val;
+
+ do {
+ val = readl(i2c->base + GOKE_I2C_STAT);
+ if (val & STAT_RXF_NOE_MASK) {
+ return 0;
+ }
+
+ udelay(50);
+ } while (time_cnt++ < I2C_WAIT_TIMEOUT);
+
+ goke_i2c_rescue(i2c);
+
+ dev_err(i2c->dev, "wait rx no empty timeout, RIS: 0x%x, SR: 0x%x\n",
+ readl(i2c->base + GOKE_I2C_INTR_RAW), val);
+ return -EIO;
+}
+
+static int goke_i2c_wait_tx_nofull(struct goke_i2c_dev *i2c)
+{
+ unsigned int time_cnt = 0;
+ unsigned int val;
+
+ do {
+ val = readl(i2c->base + GOKE_I2C_STAT);
+ if (val & STAT_TXF_NOF_MASK) {
+ return 0;
+ }
+
+ udelay(50);
+ } while (time_cnt++ < I2C_WAIT_TIMEOUT);
+
+ goke_i2c_rescue(i2c);
+
+ dev_err(i2c->dev, "wait rx no empty timeout, RIS: 0x%x, SR: 0x%x\n",
+ readl(i2c->base + GOKE_I2C_INTR_RAW), val);
+ return -EIO;
+}
+
+static int goke_i2c_wait_idle(struct goke_i2c_dev *i2c)
+{
+ unsigned int time_cnt = 0;
+ unsigned int val;
+
+ do {
+ val = readl(i2c->base + GOKE_I2C_INTR_RAW);
+ if (val & (INTR_ABORT_MASK)) {
+ dev_err(i2c->dev, "wait idle abort!, RIS: 0x%x\n",
+ val);
+ return -EIO;
+ }
+
+ if (val & INTR_CMD_DONE_MASK) {
+ return 0;
+ }
+
+ udelay(50);
+ } while (time_cnt++ < I2C_WAIT_TIMEOUT);
+
+ goke_i2c_rescue(i2c);
+
+ dev_err(i2c->dev, "wait idle timeout, RIS: 0x%x, SR: 0x%x\n",
+ val, readl(i2c->base + GOKE_I2C_STAT));
+
+ return -EIO;
+}
+
+static void goke_i2c_set_freq(struct goke_i2c_dev *i2c)
+{
+ unsigned int max_freq, freq;
+ unsigned int clk_rate;
+ unsigned int val;
+
+ freq = i2c->freq;
+ clk_rate = clk_get_rate(i2c->clk);
+ max_freq = clk_rate >> 1;
+
+ if (freq > max_freq) {
+ i2c->freq = max_freq;
+ freq = i2c->freq;
+ }
+
+ if (!freq) {
+ pr_err("goke_i2c_set_freq:freq can't be zero!");
+ return;
+ }
+
+ if (freq <= 100000) {
+ /* in normal mode F_scl: freq
+ i2c_scl_hcnt = (F_i2c / F_scl) * 0.5
+ i2c_scl_hcnt = (F_i2c / F_scl) * 0.5
+ */
+ val = clk_rate / (freq * 2);
+ writel(val, i2c->base + GOKE_I2C_SCL_H);
+ writel(val, i2c->base + GOKE_I2C_SCL_L);
+ } else {
+ /* in fast mode F_scl: freq
+ i2c_scl_hcnt = (F_i2c / F_scl) * 0.36
+ i2c_scl_hcnt = (F_i2c / F_scl) * 0.64
+ */
+ val = ((clk_rate / 100) * 36) / freq;
+ writel(val, i2c->base + GOKE_I2C_SCL_H);
+ val = ((clk_rate / 100) * 64) / freq;
+ writel(val, i2c->base + GOKE_I2C_SCL_L);
+ }
+
+ val = readl(i2c->base + GOKE_I2C_GLB);
+ val &= ~GLB_SDA_HOLD_MASK;
+ val |= ((0xa << GLB_SDA_HOLD_SHIFT) & GLB_SDA_HOLD_MASK);
+ writel(val, i2c->base + GOKE_I2C_GLB);
+}
+
+/*
+ * set i2c controller TX and RX FIFO water
+ */
+static inline void goke_i2c_set_water(struct goke_i2c_dev *i2c)
+{
+ writel(I2C_TXF_WATER, i2c->base + GOKE_I2C_TX_WATER);
+ writel(I2C_RXF_WATER, i2c->base + GOKE_I2C_RX_WATER);
+}
+
+/*
+ * initialise the controller, set i2c bus interface freq
+ */
+static void goke_i2c_hw_init(struct goke_i2c_dev *i2c)
+{
+ goke_i2c_disable(i2c);
+ goke_i2c_disable_irq(i2c, INTR_ALL_MASK);
+ goke_i2c_set_freq(i2c);
+ goke_i2c_set_water(i2c);
+}
+
+/*
+ * goke_i2c_cfg_cmd - config i2c controller command sequence
+ *
+ * After all the timing command is configured,
+ * and then start the command, you can i2c communication,
+ * and then only need to read and write i2c fifo.
+ */
+static void goke_i2c_cfg_cmd(struct goke_i2c_dev *i2c)
+{
+ struct i2c_msg *msg = i2c->msg;
+ int offset = 0;
+
+ if (i2c->msg_idx == 0) {
+ goke_i2c_cmdreg_set(i2c, CMD_TX_S, &offset);
+ } else {
+ goke_i2c_cmdreg_set(i2c, CMD_TX_RS, &offset);
+ }
+
+ if (msg->flags & I2C_M_TEN) {
+ if (i2c->msg_idx == 0) {
+ goke_i2c_cmdreg_set(i2c, CMD_TX_D1_2, &offset);
+ goke_i2c_cmdreg_set(i2c, CMD_TX_D1_1, &offset);
+ } else {
+ goke_i2c_cmdreg_set(i2c, CMD_TX_D1_2, &offset);
+ }
+ } else {
+ goke_i2c_cmdreg_set(i2c, CMD_TX_D1_1, &offset);
+ }
+
+ if (msg->flags & I2C_M_IGNORE_NAK) {
+ goke_i2c_cmdreg_set(i2c, CMD_IGN_ACK, &offset);
+ } else {
+ goke_i2c_cmdreg_set(i2c, CMD_RX_ACK, &offset);
+ }
+
+ if (msg->flags & I2C_M_RD) {
+ if (msg->len >= 2) {
+ writel(offset, i2c->base + GOKE_I2C_DST1);
+ writel(msg->len - 2, i2c->base + GOKE_I2C_LOOP1);
+ goke_i2c_cmdreg_set(i2c, CMD_RX_FIFO, &offset);
+ goke_i2c_cmdreg_set(i2c, CMD_TX_ACK, &offset);
+ goke_i2c_cmdreg_set(i2c, CMD_JMP1, &offset);
+ }
+ goke_i2c_cmdreg_set(i2c, CMD_RX_FIFO, &offset);
+ goke_i2c_cmdreg_set(i2c, CMD_TX_NACK, &offset);
+ } else {
+ writel(offset, i2c->base + GOKE_I2C_DST1);
+ writel(msg->len - 1, i2c->base + GOKE_I2C_LOOP1);
+ goke_i2c_cmdreg_set(i2c, CMD_UP_TXF, &offset);
+ goke_i2c_cmdreg_set(i2c, CMD_TX_FIFO, &offset);
+
+ if (msg->flags & I2C_M_IGNORE_NAK) {
+ goke_i2c_cmdreg_set(i2c, CMD_IGN_ACK, &offset);
+ } else {
+ goke_i2c_cmdreg_set(i2c, CMD_RX_ACK, &offset);
+ }
+
+ goke_i2c_cmdreg_set(i2c, CMD_JMP1, &offset);
+ }
+
+ if ((i2c->msg_idx == (i2c->msg_num - 1)) || (msg->flags & I2C_M_STOP)) {
+ dev_dbg(i2c->dev, "run to %s %d...TX STOP\n",
+ __func__, __LINE__);
+ goke_i2c_cmdreg_set(i2c, CMD_TX_P, &offset);
+ }
+
+ goke_i2c_cmdreg_set(i2c, CMD_EXIT, &offset);
+}
+
+static int goke_i2c_polling_xfer_one_msg(struct goke_i2c_dev *i2c)
+{
+ int status;
+ unsigned int val;
+ struct i2c_msg *msg = i2c->msg;
+
+ dev_dbg(i2c->dev, "[%s,%d]msg->flags=0x%x, len=0x%x\n",
+ __func__, __LINE__, msg->flags, msg->len);
+
+ goke_i2c_enable(i2c);
+ goke_i2c_clr_irq(i2c);
+ goke_i2c_set_addr(i2c);
+ goke_i2c_cfg_cmd(i2c);
+ goke_i2c_start_cmd(i2c);
+
+ i2c->msg_buf_ptr = 0;
+
+ if (msg->flags & I2C_M_RD) {
+ while (i2c->msg_buf_ptr < msg->len) {
+ status = goke_i2c_wait_rx_noempty(i2c);
+ if (status) {
+ goto end;
+ }
+
+ val = readl(i2c->base + GOKE_I2C_RXF);
+ msg->buf[i2c->msg_buf_ptr] = val;
+ i2c->msg_buf_ptr++;
+
+ }
+ } else {
+ while (i2c->msg_buf_ptr < msg->len) {
+ status = goke_i2c_wait_tx_nofull(i2c);
+ if (status) {
+ goto end;
+ }
+
+ val = msg->buf[i2c->msg_buf_ptr];
+ writel(val, i2c->base + GOKE_I2C_TXF);
+ i2c->msg_buf_ptr++;
+ }
+ }
+
+ status = goke_i2c_wait_idle(i2c);
+end:
+ goke_i2c_disable(i2c);
+
+ return status;
+}
+
+static irqreturn_t goke_i2c_isr(int irq, void *dev_id)
+{
+ struct goke_i2c_dev *i2c = dev_id;
+ unsigned int irq_status;
+ struct i2c_msg *msg = i2c->msg;
+
+ spin_lock(&i2c->lock);
+
+ irq_status = goke_i2c_clr_irq(i2c);
+ dev_dbg(i2c->dev, "%s RIS: 0x%x\n", __func__, irq_status);
+
+ if (!irq_status) {
+ dev_dbg(i2c->dev, "no irq\n");
+ goto end;
+ }
+
+ if (irq_status & INTR_ABORT_MASK) {
+ dev_err(i2c->dev, "irq handle abort, RIS: 0x%x\n",
+ irq_status);
+ i2c->status = -EIO;
+ goke_i2c_disable_irq(i2c, INTR_ALL_MASK);
+
+ complete(&i2c->msg_complete);
+ goto end;
+ }
+
+ if (msg->flags & I2C_M_RD) {
+ while ((readl(i2c->base + GOKE_I2C_STAT) & STAT_RXF_NOE_MASK)
+ && (i2c->msg_buf_ptr < msg->len)) {
+ msg->buf[i2c->msg_buf_ptr] =
+ readl(i2c->base + GOKE_I2C_RXF);
+ i2c->msg_buf_ptr++;
+ }
+ } else {
+ while ((readl(i2c->base + GOKE_I2C_STAT) & STAT_TXF_NOF_MASK)
+ && (i2c->msg_buf_ptr < msg->len)) {
+ writel(msg->buf[i2c->msg_buf_ptr],
+ i2c->base + GOKE_I2C_TXF);
+ i2c->msg_buf_ptr++;
+ }
+ }
+
+ if (i2c->msg_buf_ptr >= msg->len) {
+ goke_i2c_disable_irq(i2c, INTR_TX_MASK | INTR_RX_MASK);
+ }
+
+ if (irq_status & INTR_CMD_DONE_MASK) {
+ dev_dbg(i2c->dev, "cmd done\n");
+ i2c->status = 0;
+ goke_i2c_disable_irq(i2c, INTR_ALL_MASK);
+
+ complete(&i2c->msg_complete);
+ }
+
+end:
+ spin_unlock(&i2c->lock);
+
+ return IRQ_HANDLED;
+}
+
+static int goke_i2c_interrupt_xfer_one_msg(struct goke_i2c_dev *i2c)
+{
+ int status;
+ struct i2c_msg *msg = i2c->msg;
+ unsigned long timeout;
+ unsigned long flags;
+
+ dev_dbg(i2c->dev, "[%s,%d]msg->flags=0x%x, len=0x%x\n",
+ __func__, __LINE__, msg->flags, msg->len);
+
+ reinit_completion(&i2c->msg_complete);
+ i2c->msg_buf_ptr = 0;
+ i2c->status = -EIO;
+
+ spin_lock_irqsave(&i2c->lock, flags);
+ goke_i2c_enable(i2c);
+ goke_i2c_clr_irq(i2c);
+ if (msg->flags & I2C_M_RD) {
+ goke_i2c_cfg_irq(i2c, INTR_USE_MASK & ~INTR_TX_MASK);
+ } else {
+ goke_i2c_cfg_irq(i2c, INTR_USE_MASK & ~INTR_RX_MASK);
+ }
+
+ goke_i2c_set_addr(i2c);
+ goke_i2c_cfg_cmd(i2c);
+ goke_i2c_start_cmd(i2c);
+ spin_unlock_irqrestore(&i2c->lock, flags);
+
+ timeout = wait_for_completion_timeout(&i2c->msg_complete,
+ I2C_IRQ_TIMEOUT);
+
+ spin_lock_irqsave(&i2c->lock, flags);
+ if (timeout == 0) {
+ goke_i2c_disable_irq(i2c, INTR_ALL_MASK);
+ status = -EIO;
+ dev_err(i2c->dev, "%s timeout\n",
+ msg->flags & I2C_M_RD ? "rx" : "tx");
+ } else {
+ status = i2c->status;
+ }
+
+ goke_i2c_disable(i2c);
+
+ spin_unlock_irqrestore(&i2c->lock, flags);
+ return status;
+}
+
+/*
+ * Master transfer function
+ */
+static int goke_i2c_xfer(struct i2c_adapter *adap,
+ struct i2c_msg *msgs, int num)
+{
+ struct goke_i2c_dev *i2c = i2c_get_adapdata(adap);
+ int status = -EINVAL;
+ unsigned long flags;
+
+ if (!msgs || (num <= 0)) {
+ dev_err(i2c->dev, "msgs == NULL || num <= 0, Invalid argument!\n");
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&i2c->lock, flags);
+
+ i2c->msg = msgs;
+ i2c->msg_num = num;
+ i2c->msg_idx = 0;
+
+ /* FIXME: The wait_for_completion_timeout in goke_i2c_interrupt_xfer_one_msg
+ * function can not be locked by spin_lock_irqsave. And actually I2C interrupt
+ * tranfer is rarely used, so we ignore the irq setting to limit the interrupt
+ * way. But we keep these codes below, reserve for future modifications */
+
+ while (i2c->msg_idx < i2c->msg_num) {
+ if (i2c->irq >= 0) {
+ spin_unlock_irqrestore(&i2c->lock, flags);
+ status = goke_i2c_interrupt_xfer_one_msg(i2c);
+ spin_lock_irqsave(&i2c->lock, flags);
+ if (status) {
+ break;
+ }
+ } else {
+ status = goke_i2c_polling_xfer_one_msg(i2c);
+ if (status) {
+ break;
+ }
+ }
+ i2c->msg++;
+ i2c->msg_idx++;
+ }
+
+ if (!status || i2c->msg_idx > 0) {
+ status = i2c->msg_idx;
+ }
+
+ spin_unlock_irqrestore(&i2c->lock, flags);
+ return status;
+}
+
+/* goke_i2c_break_polling_xfer
+ *
+ * I2c polling independent branch, Shielding interrupt interface
+ */
+static int goke_i2c_break_polling_xfer(struct i2c_adapter *adap,
+ struct i2c_msg *msgs, int num)
+{
+ struct goke_i2c_dev *i2c = i2c_get_adapdata(adap);
+ int status = -EINVAL;
+ unsigned long flags;
+ if (!msgs || (num <= 0)) {
+ dev_err(i2c->dev, "msgs == NULL || num <= 0, Invalid argument!\n");
+ return -EINVAL;
+ }
+ spin_lock_irqsave(&i2c->lock, flags);
+ i2c->msg = msgs;
+ i2c->msg_num = num;
+ i2c->msg_idx = 0;
+ while (i2c->msg_idx < i2c->msg_num) {
+ status = goke_i2c_polling_xfer_one_msg(i2c);
+ if (status) {
+ break;
+ }
+ i2c->msg++;
+ i2c->msg_idx++;
+ }
+ if (!status || i2c->msg_idx > 0) {
+ status = i2c->msg_idx;
+ }
+ spin_unlock_irqrestore(&i2c->lock, flags);
+ return status;
+}
+/*
+ * bsp_i2c_master_recv - issue a single I2C message in master receive mode
+ * @client: Handle to slave device
+ * @buf: Where to store data read from slave
+ * @count: How many bytes to read, must be less than 64k since msg.len is u16
+ *
+ * Returns negative errno, or else the number of bytes read.
+ */
+int gk_i2c_master_recv(const struct i2c_client *client, char *buf,
+ int count)
+{
+ printk("Wrong interface call."
+ "bsp_i2c_transfer is the only interface to i2c read!!!\n");
+
+ return -EIO;
+}
+EXPORT_SYMBOL(gk_i2c_master_recv);
+
+/*I2C WRITE*
+ * bsp_i2c_master_send - issue a single I2C message in master transmit mode
+ * @client: Handle to slave device
+ * @buf: Data that will be written to the slave
+ * @count: How many bytes to write, must be less than 64k since msg.len is u16
+ *
+ * Returns negative errno, or else the number of bytes written.
+ */
+int gk_i2c_master_send(const struct i2c_client *client,
+ const char *buf, int count)
+{
+ struct i2c_adapter *adap = client->adapter;
+ struct i2c_msg msg;
+ int msgs_count;
+
+ if ((client->addr > 0x3ff)
+ || (((client->flags & I2C_M_TEN) == 0) && (client->addr > 0x7f))) {
+ printk(KERN_ERR "dev address out of range\n");
+ return -EINVAL;
+ }
+
+ msg.addr = client->addr;
+ msg.flags = client->flags;
+ msg.len = count;
+
+ if ((!buf)||(count < 0)) {
+ printk(KERN_ERR "buf == NULL || count < 0, Invalid argument!\n");
+ return -EINVAL;
+ }
+ msg.buf = (__u8 *)buf;
+
+ msgs_count = goke_i2c_break_polling_xfer(adap, &msg, 1);
+
+ return (msgs_count == 1) ? count : -EIO;
+}
+EXPORT_SYMBOL(gk_i2c_master_send);
+
+/**
+ * bsp_i2c_transfer - execute a single or combined I2C message
+ * @adap: Handle to I2C bus
+ * @msgs: One or more messages to execute before STOP is issued to
+ * terminate the operation; each message begins with a START.
+ * @num: Number of messages to be executed.
+ *
+ * Returns negative errno, else the number of messages executed.
+ *
+ * Note that there is no requirement that each message be sent to
+ * the same slave address, although that is the most common model.
+ */
+int gk_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
+ int num)
+{
+ int msgs_count;
+
+ if((!adap)||(!msgs)) {
+ printk(KERN_ERR "adap == NULL || msgs == NULL, Invalid argument!\n");
+ return -EINVAL;
+ }
+
+ if ((msgs[0].addr > 0x3ff)
+ || (((msgs[0].flags & I2C_M_TEN) == 0) && (msgs[0].addr > 0x7f))) {
+ printk(KERN_ERR "msgs[0] dev address out of range\n");
+ return -EINVAL;
+ }
+
+ if ((msgs[1].addr > 0x3ff)
+ || (((msgs[1].flags & I2C_M_TEN) == 0) && (msgs[1].addr > 0x7f))) {
+ printk(KERN_ERR "msgs[1] dev address out of range\n");
+ return -EINVAL;
+ }
+
+ msgs_count = goke_i2c_xfer(adap, msgs, num);
+
+ return msgs_count;
+}
+EXPORT_SYMBOL(gk_i2c_transfer);
+
+static u32 goke_i2c_func(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR
+ | I2C_FUNC_PROTOCOL_MANGLING
+ | I2C_FUNC_SMBUS_WORD_DATA
+ | I2C_FUNC_SMBUS_BYTE_DATA
+ | I2C_FUNC_SMBUS_BYTE
+ | I2C_FUNC_SMBUS_I2C_BLOCK;
+}
+
+static const struct i2c_algorithm goke_i2c_algo = {
+ .master_xfer = goke_i2c_xfer,
+ .functionality = goke_i2c_func,
+};
+
+static int goke_i2c_probe(struct platform_device *pdev)
+{
+ int status;
+ struct goke_i2c_dev *i2c = NULL;
+ struct i2c_adapter *adap = NULL;
+ struct resource *res = NULL;
+
+ i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
+ if (!i2c) {
+ return -ENOMEM;
+ }
+
+ platform_set_drvdata(pdev, i2c);
+ i2c->dev = &pdev->dev;
+ spin_lock_init(&i2c->lock);
+ init_completion(&i2c->msg_complete);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(i2c->dev, "Invalid mem resource./n");
+ return -ENODEV;
+ }
+
+ i2c->phybase = res->start;
+ i2c->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(i2c->base)) {
+ dev_err(i2c->dev, "cannot ioremap resource\n");
+ return -ENOMEM;
+ }
+
+ i2c->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(i2c->clk)) {
+ dev_err(i2c->dev, "cannot get clock\n");
+ return -ENOENT;
+ }
+ clk_prepare_enable(i2c->clk);
+
+ if (of_property_read_u32(pdev->dev.of_node, "clock-frequency",
+ &i2c->freq)) {
+ dev_warn(i2c->dev, "setting default clock-frequency@%dHz\n",
+ I2C_DEFAULT_FREQUENCY);
+ i2c->freq = I2C_DEFAULT_FREQUENCY;
+ }
+
+ /* i2c controller initialization, disable interrupt */
+ goke_i2c_hw_init(i2c);
+
+ i2c->irq = platform_get_irq(pdev, 0);
+ status = devm_request_irq(&pdev->dev, i2c->irq, goke_i2c_isr,
+ IRQF_SHARED, dev_name(&pdev->dev), i2c);
+ if (status) {
+ dev_dbg(i2c->dev, "falling back to polling mode");
+ i2c->irq = -1;
+ }
+
+ adap = &i2c->adap;
+ i2c_set_adapdata(adap, i2c);
+ adap->owner = THIS_MODULE;
+ strlcpy(adap->name, "goke-i2c", sizeof(adap->name));
+ adap->dev.parent = &pdev->dev;
+ adap->dev.of_node = pdev->dev.of_node;
+ adap->algo = &goke_i2c_algo;
+
+ /* Add the i2c adapter */
+ status = i2c_add_adapter(adap);
+ if (status) {
+ dev_err(i2c->dev, "failed to add bus to i2c core\n");
+ goto err_add_adapter;
+ }
+
+ dev_info(i2c->dev, "%s%d@%dhz registered\n",
+ adap->name, adap->nr, i2c->freq);
+
+ return 0;
+
+err_add_adapter:
+ clk_disable_unprepare(i2c->clk);
+ return status;
+}
+
+static int goke_i2c_remove(struct platform_device *pdev)
+{
+ struct goke_i2c_dev *i2c = platform_get_drvdata(pdev);
+ if (i2c == NULL){
+ printk("i2c remove err!!!\n");
+ return 0;
+ }
+ clk_disable_unprepare(i2c->clk);
+ i2c_del_adapter(&i2c->adap);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int goke_i2c_suspend(struct device *dev)
+{
+ struct goke_i2c_dev *i2c = dev_get_drvdata(dev);
+
+ i2c_lock_adapter(&i2c->adap);
+ clk_disable_unprepare(i2c->clk);
+ i2c_unlock_adapter(&i2c->adap);
+
+ return 0;
+}
+
+static int goke_i2c_resume(struct device *dev)
+{
+ struct goke_i2c_dev *i2c = dev_get_drvdata(dev);
+
+ i2c_lock_adapter(&i2c->adap);
+ clk_prepare_enable(i2c->clk);
+ goke_i2c_hw_init(i2c);
+ i2c_unlock_adapter(&i2c->adap);
+
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(goke_i2c_dev_pm, goke_i2c_suspend,
+ goke_i2c_resume);
+
+static const struct of_device_id goke_i2c_match[] = {
+ { .compatible = "goke,goke-i2c"},
+ {},
+};
+MODULE_DEVICE_TABLE(of, goke_i2c_match);
+
+static struct platform_driver goke_i2c_driver = {
+ .driver = {
+ .name = "goke-i2c",
+ .of_match_table = goke_i2c_match,
+ .pm = &goke_i2c_dev_pm,
+ },
+ .probe = goke_i2c_probe,
+ .remove = goke_i2c_remove,
+};
+
+module_platform_driver(goke_i2c_driver);
+
+MODULE_AUTHOR("Goke");
+MODULE_DESCRIPTION("GOKE I2C Bus driver");
+MODULE_LICENSE("GPL v2");
diff -urN linux-4.9.37/drivers/i2c/busses/Kconfig linux-4.9.y/drivers/i2c/busses/Kconfig
--- linux-4.9.37/drivers/i2c/busses/Kconfig 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/i2c/busses/Kconfig 2021-06-07 13:01:33.000000000 +0300
@@ -555,6 +555,16 @@
This is a very simple bitbanging I2C driver utilizing the
arch-neutral GPIO API to control the SCL and SDA lines.
+config I2C_GOKE
+ tristate "Goke I2C Controller"
+ depends on ARCH_GOKE
+ help
+ Say Y here to include support for Goke I2C controller in the
+ Goke SoCs.
+
+ This driver can also be built as a module. If so, the module
+ will be called i2c.
+
config I2C_HIGHLANDER
tristate "Highlander FPGA SMBus interface"
depends on SH_HIGHLANDER
@@ -1214,4 +1224,20 @@
This driver can also be built as a module. If so, the module will be
called as i2c-opal.
+config DMA_MSG_MIN_LEN
+ int "Goke I2C support DMA minimum LEN"
+ depends on I2C_GOKE
+ range 1 4090
+ default 5
+ help
+ The i2c_msg minimum LEN of i2c support DMA,range from 1 to 4091
+
+config DMA_MSG_MAX_LEN
+ int "Goke I2C support DMA maximum LEN"
+ depends on I2C_GOKE
+ range DMA_MSG_MIN_LEN 4090
+ default 4090
+ help
+ The i2c_msg maximum LEN of i2c support DMA,range from i2c_msg minimum LEN to 4090,
+ because DMA for 0xFFC one-time largest data transfers;
endmenu
diff -urN linux-4.9.37/drivers/i2c/busses/Makefile linux-4.9.y/drivers/i2c/busses/Makefile
--- linux-4.9.37/drivers/i2c/busses/Makefile 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/i2c/busses/Makefile 2021-06-07 13:01:33.000000000 +0300
@@ -51,6 +51,7 @@
obj-$(CONFIG_I2C_EMEV2) += i2c-emev2.o
obj-$(CONFIG_I2C_EXYNOS5) += i2c-exynos5.o
obj-$(CONFIG_I2C_GPIO) += i2c-gpio.o
+obj-$(CONFIG_I2C_GOKE) += i2c-goke.o
obj-$(CONFIG_I2C_HIGHLANDER) += i2c-highlander.o
obj-$(CONFIG_I2C_HIX5HD2) += i2c-hix5hd2.o
obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o
diff -urN linux-4.9.37/drivers/i2c/i2c-dev.c linux-4.9.y/drivers/i2c/i2c-dev.c
--- linux-4.9.37/drivers/i2c/i2c-dev.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/i2c/i2c-dev.c 2021-06-07 13:01:33.000000000 +0300
@@ -170,6 +170,9 @@
if (count > 8192)
count = 8192;
+ if (count == 0)
+ return -EINVAL;
+
tmp = memdup_user(buf, count);
if (IS_ERR(tmp))
return PTR_ERR(tmp);
@@ -273,6 +276,11 @@
res = -EINVAL;
break;
}
+
+ if (rdwr_pa[i].len == 0) {
+ res = -EINVAL;
+ break;
+ }
data_ptrs[i] = (u8 __user *)rdwr_pa[i].buf;
rdwr_pa[i].buf = memdup_user(data_ptrs[i], rdwr_pa[i].len);
diff -urN linux-4.9.37/drivers/irqchip/irq-gic.c linux-4.9.y/drivers/irqchip/irq-gic.c
--- linux-4.9.37/drivers/irqchip/irq-gic.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/irqchip/irq-gic.c 2021-06-07 13:01:33.000000000 +0300
@@ -1069,7 +1069,9 @@
{
irq_hw_number_t hwirq_base;
int gic_irqs, irq_base, ret;
-
+ struct device_node *np;
+ void * sysctrl_reg_base;
+ int gic_dist_init_flag;
if (IS_ENABLED(CONFIG_GIC_NON_BANKED) && gic->percpu_offset) {
/* Frankein-GIC without banked registers... */
unsigned int cpu;
@@ -1149,7 +1151,21 @@
goto error;
}
- gic_dist_init(gic);
+#define GIC_DIST_INIT_FLAG 0x47444946
+#define GIC_DIST_INIT_FLAG_OFFSET 0x0130
+ /* 0x47444946('G''D''I''F') is abbreviation of GIC_DIST_INIT_FLAG. */
+
+ np = of_find_compatible_node(NULL, NULL, "goke,sysctrl");
+ sysctrl_reg_base = of_iomap(np, 0);
+ gic_dist_init_flag = readl(sysctrl_reg_base + GIC_DIST_INIT_FLAG_OFFSET);
+
+ if(gic_dist_init_flag != GIC_DIST_INIT_FLAG) {
+ printk("Gic dist init...\n");
+ gic_dist_init(gic);
+ writel_relaxed(GIC_DIST_INIT_FLAG, sysctrl_reg_base + GIC_DIST_INIT_FLAG_OFFSET);
+ } else
+ printk("Gic dist not init...\n");
+
ret = gic_cpu_init(gic);
if (ret)
goto error;
diff -urN linux-4.9.37/drivers/irqchip/irq-gic-v3.c linux-4.9.y/drivers/irqchip/irq-gic-v3.c
--- linux-4.9.37/drivers/irqchip/irq-gic-v3.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/irqchip/irq-gic-v3.c 2021-06-07 13:01:33.000000000 +0300
@@ -120,11 +120,10 @@
}
#ifdef CONFIG_ARM64
-static DEFINE_STATIC_KEY_FALSE(is_cavium_thunderx);
static u64 __maybe_unused gic_read_iar(void)
{
- if (static_branch_unlikely(&is_cavium_thunderx))
+ if (cpus_have_const_cap(ARM64_WORKAROUND_CAVIUM_23154))
return gic_read_iar_cavium_thunderx();
else
return gic_read_iar_common();
@@ -905,14 +904,6 @@
.select = gic_irq_domain_select,
};
-static void gicv3_enable_quirks(void)
-{
-#ifdef CONFIG_ARM64
- if (cpus_have_cap(ARM64_WORKAROUND_CAVIUM_23154))
- static_branch_enable(&is_cavium_thunderx);
-#endif
-}
-
static int __init gic_init_bases(void __iomem *dist_base,
struct redist_region *rdist_regs,
u32 nr_redist_regions,
@@ -935,8 +926,6 @@
gic_data.nr_redist_regions = nr_redist_regions;
gic_data.redist_stride = redist_stride;
- gicv3_enable_quirks();
-
/*
* Find out how many interrupts are supported.
* The GIC only supports up to 1020 interrupt sources (SGI+PPI+SPI)
diff -urN linux-4.9.37/drivers/Kconfig linux-4.9.y/drivers/Kconfig
--- linux-4.9.37/drivers/Kconfig 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/Kconfig 2021-06-07 13:01:33.000000000 +0300
@@ -202,4 +202,6 @@
source "drivers/fpga/Kconfig"
+source "drivers/goke/Kconfig"
+
endmenu
diff -urN linux-4.9.37/drivers/Makefile linux-4.9.y/drivers/Makefile
--- linux-4.9.37/drivers/Makefile 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/Makefile 2021-06-07 13:01:33.000000000 +0300
@@ -70,6 +70,7 @@
obj-$(CONFIG_LIBNVDIMM) += nvdimm/
obj-$(CONFIG_DEV_DAX) += dax/
obj-$(CONFIG_DMA_SHARED_BUFFER) += dma-buf/
+obj-$(CONFIG_SYNC_FILE) += fence/
obj-$(CONFIG_NUBUS) += nubus/
obj-y += macintosh/
obj-$(CONFIG_IDE) += ide/
@@ -174,3 +175,4 @@
obj-$(CONFIG_ANDROID) += android/
obj-$(CONFIG_NVMEM) += nvmem/
obj-$(CONFIG_FPGA) += fpga/
+obj-$(CONFIG_ARCH_GOKE) += goke/
diff -urN linux-4.9.37/drivers/media/usb/uvc/uvc_video.c linux-4.9.y/drivers/media/usb/uvc/uvc_video.c
--- linux-4.9.37/drivers/media/usb/uvc/uvc_video.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/media/usb/uvc/uvc_video.c 2021-06-07 13:01:33.000000000 +0300
@@ -1467,6 +1467,7 @@
struct usb_host_endpoint *ep)
{
u16 psize;
+ u16 mult;
switch (dev->speed) {
case USB_SPEED_SUPER:
@@ -1474,7 +1475,8 @@
return le16_to_cpu(ep->ss_ep_comp.wBytesPerInterval);
case USB_SPEED_HIGH:
psize = usb_endpoint_maxp(&ep->desc);
- return (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
+ mult = usb_endpoint_maxp_mult(&ep->desc);
+ return (psize & 0x07ff) * mult;
case USB_SPEED_WIRELESS:
psize = usb_endpoint_maxp(&ep->desc);
return psize;
diff -urN linux-4.9.37/drivers/media/v4l2-core/videobuf2-v4l2.c linux-4.9.y/drivers/media/v4l2-core/videobuf2-v4l2.c
--- linux-4.9.37/drivers/media/v4l2-core/videobuf2-v4l2.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/media/v4l2-core/videobuf2-v4l2.c 2021-06-07 13:01:33.000000000 +0300
@@ -146,7 +146,6 @@
return;
check_once = true;
- WARN_ON(1);
pr_warn("use of bytesused == 0 is deprecated and will be removed in the future,\n");
if (vb->vb2_queue->allow_zero_bytesused)
diff -urN linux-4.9.37/drivers/mfd/goke_fmc.c linux-4.9.y/drivers/mfd/goke_fmc.c
--- linux-4.9.37/drivers/mfd/goke_fmc.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/mfd/goke_fmc.c 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/goke_fmc.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+unsigned char fmc_cs_user[FMC_MAX_CHIP_NUM];
+
+DEFINE_MUTEX(fmc_switch_mutex);
+EXPORT_SYMBOL_GPL(fmc_switch_mutex);
+
+/* ------------------------------------------------------------------------ */
+static const struct mfd_cell bsp_fmc_devs[] = {
+ {
+ .name = "bsp_spi_nor",
+ .of_compatible = "goke,fmc-spi-nor",
+ },
+ {
+ .name = "bsp_spi_nand",
+ .of_compatible = "goke,fmc-spi-nand",
+ },
+};
+
+static int bsp_fmc_probe(struct platform_device *pdev)
+{
+ struct bsp_fmc *fmc;
+ struct resource *res;
+ struct device *dev = &pdev->dev;
+ int ret;
+
+ fmc = devm_kzalloc(dev, sizeof(*fmc), GFP_KERNEL);
+ if (!fmc) {
+ return -ENOMEM;
+ }
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "control");
+ fmc->regbase = devm_ioremap_resource(dev, res);
+ if (IS_ERR(fmc->regbase)) {
+ return PTR_ERR(fmc->regbase);
+ }
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "memory");
+ fmc->iobase = devm_ioremap_resource(dev, res);
+ if (IS_ERR(fmc->iobase)) {
+ return PTR_ERR(fmc->iobase);
+ }
+
+ fmc->clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(fmc->clk)) {
+ return PTR_ERR(fmc->clk);
+ }
+
+ if (of_property_read_u32(dev->of_node, "max-dma-size", &fmc->dma_len)) {
+ dev_err(dev, "Please set the suitable max-dma-size value !!!\n");
+ return -ENOMEM;
+ }
+
+ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
+ if (ret) {
+ dev_warn(dev, "Unable to set dma mask\n");
+ return ret;
+ }
+
+ fmc->buffer = dmam_alloc_coherent(dev, fmc->dma_len,
+ &fmc->dma_buffer, GFP_KERNEL);
+ if (IS_ERR(fmc->buffer)) {
+ return PTR_ERR(fmc->buffer);
+ }
+
+ mutex_init(&fmc->lock);
+
+ platform_set_drvdata(pdev, fmc);
+
+ ret = mfd_add_devices(dev, 0, bsp_fmc_devs,
+ ARRAY_SIZE(bsp_fmc_devs), NULL, 0, NULL);
+ if (ret) {
+ dev_err(dev, "add mfd devices failed: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int bsp_fmc_remove(struct platform_device *pdev)
+{
+ struct bsp_fmc *fmc = platform_get_drvdata(pdev);
+
+ dmam_free_coherent(&pdev->dev, fmc->dma_len,
+ fmc->buffer, fmc->dma_buffer);
+ mfd_remove_devices(&pdev->dev);
+ mutex_destroy(&fmc->lock);
+
+ return 0;
+}
+
+static const struct of_device_id bsp_fmc_of_match_tbl[] = {
+ { .compatible = "goke,fmc"},
+ { }
+};
+MODULE_DEVICE_TABLE(of, bsp_fmc_of_match_tbl);
+
+static struct platform_driver bsp_fmc_driver = {
+ .driver = {
+ .name = "fmc",
+ .of_match_table = bsp_fmc_of_match_tbl,
+ },
+ .probe = bsp_fmc_probe,
+ .remove = bsp_fmc_remove,
+};
+module_platform_driver(bsp_fmc_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Goke Flash Memory Controller Driver");
diff -urN linux-4.9.37/drivers/mfd/Kconfig linux-4.9.y/drivers/mfd/Kconfig
--- linux-4.9.37/drivers/mfd/Kconfig 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/mfd/Kconfig 2021-06-07 13:01:33.000000000 +0300
@@ -358,6 +358,16 @@
help
Select this option to enable Hisilicon hi655x series pmic driver.
+config MFD_GOKE_FMC
+ tristate "Goke Flash Memory Controller"
+ depends on OF
+ depends on ARCH_GOKE
+ select MFD_CORE
+ select REGMAP_MMIO
+ help
+ Select this option to enable the Goke Flash Memory
+ Controller(FMC) driver.
+
config HTC_PASIC3
tristate "HTC PASIC3 LED/DS1WM chip support"
select MFD_CORE
diff -urN linux-4.9.37/drivers/mfd/Makefile linux-4.9.y/drivers/mfd/Makefile
--- linux-4.9.37/drivers/mfd/Makefile 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/mfd/Makefile 2021-06-07 13:01:33.000000000 +0300
@@ -180,6 +180,7 @@
obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o
obj-$(CONFIG_MFD_ATMEL_FLEXCOM) += atmel-flexcom.o
obj-$(CONFIG_MFD_ATMEL_HLCDC) += atmel-hlcdc.o
+obj-$(CONFIG_MFD_GOKE_FMC) += goke_fmc.o
obj-$(CONFIG_MFD_INTEL_LPSS) += intel-lpss.o
obj-$(CONFIG_MFD_INTEL_LPSS_PCI) += intel-lpss-pci.o
obj-$(CONFIG_MFD_INTEL_LPSS_ACPI) += intel-lpss-acpi.o
diff -urN linux-4.9.37/drivers/mmc/card/block.c linux-4.9.y/drivers/mmc/card/block.c
--- linux-4.9.37/drivers/mmc/card/block.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/mmc/card/block.c 2021-06-07 13:01:33.000000000 +0300
@@ -63,6 +63,8 @@
#define MMC_BLK_TIMEOUT_MS (10 * 60 * 1000) /* 10 minute timeout */
#define MMC_SANITIZE_REQ_TIMEOUT 240000
#define MMC_EXTRACT_INDEX_FROM_ARG(x) ((x & 0x00FF0000) >> 16)
+#define MMC_CMDQ_STOP_TIMEOUT_MS 100
+#define MMC_QUIRK_CMDQ_DELAY_BEFORE_DCMD 6 /* microseconds */
#define mmc_req_rel_wr(req) ((req->cmd_flags & REQ_FUA) && \
(rq_data_dir(req) == WRITE))
@@ -103,6 +105,7 @@
#define MMC_BLK_CMD23 (1 << 0) /* Can do SET_BLOCK_COUNT for multiblock */
#define MMC_BLK_REL_WR (1 << 1) /* MMC Reliable write support */
#define MMC_BLK_PACKED_CMD (1 << 2) /* MMC packed command support */
+#define MMC_BLK_CMD_QUEUE (1 << 3) /* MMC command queue support */
unsigned int usage;
unsigned int read_only;
@@ -519,21 +522,40 @@
mrq.cmd = &cmd;
+ if (mmc_card_cmdq(card)) {
+ err = mmc_cmdq_halt_on_empty_queue(card->host);
+ if (err) {
+ pr_err("%s: halt failed while doing %s err (%d)\n",
+ mmc_hostname(card->host),
+ __func__, err);
+ return err;
+ }
+ }
+
+ if (mmc_card_doing_bkops(card)) {
+ err = mmc_stop_bkops(card);
+ if (err) {
+ dev_err(mmc_dev(card->host),
+ "%s: stop_bkops failed %d\n", __func__, err);
+ goto cmd_rel_host;
+ }
+ }
+
err = mmc_blk_part_switch(card, md);
if (err)
- return err;
+ goto cmd_rel_host;
if (idata->ic.is_acmd) {
err = mmc_app_cmd(card->host, card);
if (err)
- return err;
+ goto cmd_rel_host;
}
if (is_rpmb) {
err = mmc_set_blockcount(card, data.blocks,
idata->ic.write_flag & (1 << 31));
if (err)
- return err;
+ goto cmd_rel_host;
}
if ((MMC_EXTRACT_INDEX_FROM_ARG(cmd.arg) == EXT_CSD_SANITIZE_START) &&
@@ -544,7 +566,7 @@
pr_err("%s: ioctl_do_sanitize() failed. err = %d",
__func__, err);
- return err;
+ goto cmd_rel_host;
}
mmc_wait_for_req(card->host, &mrq);
@@ -552,12 +574,14 @@
if (cmd.error) {
dev_err(mmc_dev(card->host), "%s: cmd error %d\n",
__func__, cmd.error);
- return cmd.error;
+ err = cmd.error;
+ goto cmd_rel_host;
}
if (data.error) {
dev_err(mmc_dev(card->host), "%s: data error %d\n",
__func__, data.error);
- return data.error;
+ err = data.error;
+ goto cmd_rel_host;
}
/*
@@ -581,6 +605,13 @@
__func__, status, err);
}
+cmd_rel_host:
+ if (mmc_card_cmdq(card)) {
+ if (mmc_cmdq_halt(card->host, false))
+ pr_err("%s: %s: cmdq unhalt failed\n",
+ mmc_hostname(card->host), __func__);
+ }
+
return err;
}
@@ -746,13 +777,64 @@
#endif
};
+static int mmc_blk_cmdq_switch(struct mmc_card *card,
+ struct mmc_blk_data *md, bool enable)
+{
+ int ret = 0;
+ bool cmdq_mode = !!mmc_card_cmdq(card);
+ struct mmc_host *host = card->host;
+ struct mmc_cmdq_context_info *ctx = &host->cmdq_ctx;
+
+ if (!(card->host->caps2 & MMC_CAP2_CMD_QUEUE) ||
+ !card->ext_csd.cmdq_support ||
+ (enable && !(md->flags & MMC_BLK_CMD_QUEUE)) ||
+ (cmdq_mode == enable))
+ return 0;
+
+ if (enable) {
+ ret = mmc_set_blocklen(card, MMC_CARD_CMDQ_BLK_SIZE);
+ if (ret) {
+ pr_err("%s: failed (%d) to set block-size to %d\n",
+ __func__, ret, MMC_CARD_CMDQ_BLK_SIZE);
+ goto out;
+ }
+
+ } else {
+ if (!test_bit(CMDQ_STATE_HALT, &ctx->curr_state)) {
+ ret = mmc_cmdq_halt(host, true);
+ if (ret) {
+ pr_err("%s: halt: failed: %d\n",
+ mmc_hostname(host), ret);
+ goto out;
+ }
+ }
+ }
+
+ ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_CMDQ, enable,
+ card->ext_csd.generic_cmd6_time);
+ if (ret) {
+ pr_err("%s: cmdq mode %sable failed %d\n",
+ md->disk->disk_name, enable ? "en" : "dis", ret);
+ goto out;
+ }
+
+ if (enable)
+ mmc_card_set_cmdq(card);
+ else
+ mmc_card_clr_cmdq(card);
+out:
+ return ret;
+}
+
static inline int mmc_blk_part_switch(struct mmc_card *card,
struct mmc_blk_data *md)
{
int ret;
struct mmc_blk_data *main_md = dev_get_drvdata(&card->dev);
- if (main_md->part_curr == md->part_type)
+ if ((main_md->part_curr == md->part_type) &&
+ (card->part_curr == md->part_type))
return 0;
if (mmc_card_mmc(card)) {
@@ -761,6 +843,13 @@
if (md->part_type == EXT_CSD_PART_CONFIG_ACC_RPMB)
mmc_retune_pause(card->host);
+ if (md->part_type) {
+ /* disable CQ mode for non-user data partitions */
+ ret = mmc_blk_cmdq_switch(card, md, false);
+ if (ret)
+ return ret;
+ }
+
part_config &= ~EXT_CSD_PART_CONFIG_ACC_MASK;
part_config |= md->part_type;
@@ -774,6 +863,7 @@
}
card->ext_csd.part_config = part_config;
+ card->part_curr = md->part_type;
if (main_md->part_curr == EXT_CSD_PART_CONFIG_ACC_RPMB)
mmc_retune_unpause(card->host);
@@ -2210,6 +2300,813 @@
!(card->csd.cmdclass & CCC_BLOCK_WRITE);
}
+/* prepare for non-data commands */
+static struct mmc_cmdq_req *mmc_cmdq_prep_dcmd(
+ struct mmc_queue_req *mqrq, struct mmc_queue *mq)
+{
+ struct request *req = mqrq->req;
+ struct mmc_cmdq_req *cmdq_req = &mqrq->cmdq_req;
+
+ memset(&mqrq->cmdq_req, 0, sizeof(struct mmc_cmdq_req));
+
+ cmdq_req->mrq.data = NULL;
+ cmdq_req->cmd_flags = req->cmd_flags;
+ cmdq_req->mrq.req = mqrq->req;
+ req->special = mqrq;
+ cmdq_req->cmdq_req_flags |= DCMD;
+ cmdq_req->mrq.cmdq_req = cmdq_req;
+
+ return &mqrq->cmdq_req;
+}
+
+#define IS_RT_CLASS_REQ(x) \
+ (IOPRIO_PRIO_CLASS(req_get_ioprio(x)) == IOPRIO_CLASS_RT)
+
+static struct mmc_cmdq_req *mmc_blk_cmdq_rw_prep(
+ struct mmc_queue_req *mqrq, struct mmc_queue *mq)
+{
+ struct mmc_card *card = mq->card;
+ struct request *req = mqrq->req;
+ struct mmc_blk_data *md = mq->data;
+ bool do_rel_wr = mmc_req_rel_wr(req) && (md->flags & MMC_BLK_REL_WR);
+ bool do_data_tag;
+ bool read_dir = (rq_data_dir(req) == READ);
+ bool prio = IS_RT_CLASS_REQ(req);
+ struct mmc_cmdq_req *cmdq_rq = &mqrq->cmdq_req;
+
+ memset(&mqrq->cmdq_req, 0, sizeof(struct mmc_cmdq_req));
+
+ cmdq_rq->tag = req->tag;
+ if (read_dir) {
+ cmdq_rq->cmdq_req_flags |= DIR;
+ cmdq_rq->data.flags = MMC_DATA_READ;
+ } else {
+ cmdq_rq->data.flags = MMC_DATA_WRITE;
+ }
+ if (prio)
+ cmdq_rq->cmdq_req_flags |= PRIO;
+
+ if (do_rel_wr)
+ cmdq_rq->cmdq_req_flags |= REL_WR;
+
+ cmdq_rq->data.blocks = blk_rq_sectors(req);
+ cmdq_rq->blk_addr = blk_rq_pos(req);
+ cmdq_rq->data.blksz = MMC_CARD_CMDQ_BLK_SIZE;
+
+ mmc_set_data_timeout(&cmdq_rq->data, card);
+
+ do_data_tag = (card->ext_csd.data_tag_unit_size) &&
+ (req->cmd_flags & REQ_META) &&
+ (rq_data_dir(req) == WRITE) &&
+ ((cmdq_rq->data.blocks * cmdq_rq->data.blksz) >=
+ card->ext_csd.data_tag_unit_size);
+ if (do_data_tag)
+ cmdq_rq->cmdq_req_flags |= DAT_TAG;
+ cmdq_rq->data.sg = mqrq->sg;
+ cmdq_rq->data.sg_len = mmc_queue_map_sg(mq, mqrq);
+
+ /*
+ * Adjust the sg list so it is the same size as the
+ * request.
+ */
+ if (cmdq_rq->data.blocks > card->host->max_blk_count)
+ cmdq_rq->data.blocks = card->host->max_blk_count;
+
+ if (cmdq_rq->data.blocks != blk_rq_sectors(req)) {
+ int i, data_size = cmdq_rq->data.blocks << 9;
+ struct scatterlist *sg;
+
+ for_each_sg(cmdq_rq->data.sg, sg, cmdq_rq->data.sg_len, i) {
+ data_size -= sg->length;
+ if (data_size <= 0) {
+ sg->length += data_size;
+ i++;
+ break;
+ }
+ }
+ cmdq_rq->data.sg_len = i;
+ }
+
+ mqrq->cmdq_req.cmd_flags = req->cmd_flags;
+ mqrq->cmdq_req.mrq.req = mqrq->req;
+ mqrq->cmdq_req.mrq.cmdq_req = &mqrq->cmdq_req;
+ mqrq->cmdq_req.mrq.data = &mqrq->cmdq_req.data;
+ mqrq->req->special = mqrq;
+
+ pr_debug("%s: %s: mrq: 0x%p req: 0x%p mqrq: 0x%p bytes to xf: %d mmc_cmdq_req: 0x%p card-addr: 0x%08x dir(r-1/w-0): %d\n",
+ mmc_hostname(card->host), __func__, &mqrq->cmdq_req.mrq,
+ mqrq->req, mqrq, (cmdq_rq->data.blocks * cmdq_rq->data.blksz),
+ cmdq_rq, cmdq_rq->blk_addr,
+ (cmdq_rq->cmdq_req_flags & DIR) ? 1 : 0);
+
+ return &mqrq->cmdq_req;
+}
+
+/*
+ * Complete reqs from block layer softirq context
+ * Invoked in irq context
+ */
+void mmc_blk_cmdq_req_done(struct mmc_request *mrq)
+{
+ struct request *req = mrq->req;
+
+ blk_complete_request(req);
+}
+EXPORT_SYMBOL(mmc_blk_cmdq_req_done);
+
+static int mmc_blk_cmdq_start_req(struct mmc_host *host,
+ struct mmc_cmdq_req *cmdq_req)
+{
+ struct mmc_request *mrq = &cmdq_req->mrq;
+
+ mrq->done = mmc_blk_cmdq_req_done;
+ return mmc_cmdq_start_req(host, cmdq_req);
+}
+
+static int mmc_blk_cmdq_issue_rw_rq(struct mmc_queue *mq, struct request *req)
+{
+ struct mmc_queue_req *active_mqrq;
+ struct mmc_card *card = mq->card;
+ struct mmc_host *host = card->host;
+ struct mmc_cmdq_context_info *ctx = &host->cmdq_ctx;
+ struct mmc_cmdq_req *mc_rq;
+ u8 active_small_sector_read = 0;
+ int ret = 0;
+
+ BUG_ON((req->tag < 0) || (req->tag > card->ext_csd.cmdq_depth));
+ BUG_ON(test_and_set_bit(req->tag, &host->cmdq_ctx.data_active_reqs));
+ BUG_ON(test_and_set_bit(req->tag, &host->cmdq_ctx.active_reqs));
+
+ active_mqrq = &mq->mqrq_cmdq[req->tag];
+ active_mqrq->req = req;
+
+ mc_rq = mmc_blk_cmdq_rw_prep(active_mqrq, mq);
+
+ if (card->quirks & MMC_QUIRK_CMDQ_EMPTY_BEFORE_DCMD) {
+ unsigned int sectors = blk_rq_sectors(req);
+
+ if (((sectors > 0) && (sectors < 8))
+ && (rq_data_dir(req) == READ))
+ active_small_sector_read = 1;
+ }
+ ret = mmc_blk_cmdq_start_req(card->host, mc_rq);
+ if (!ret && active_small_sector_read)
+ host->cmdq_ctx.active_small_sector_read_reqs++;
+ /*
+ * When in SVS2 on low load scenario and there are lots of requests
+ * queued for CMDQ we need to wait till the queue is empty to scale
+ * back up to Nominal even if there is a sudden increase in load.
+ * This impacts performance where lots of IO get executed in SVS2
+ * frequency since the queue is full. As SVS2 is a low load use case
+ * we can serialize the requests and not queue them in parallel
+ * without impacting other use cases. This makes sure the queue gets
+ * empty faster and we will be able to scale up to Nominal frequency
+ * when needed.
+ */
+ if (!ret)
+ wait_event_interruptible(ctx->queue_empty_wq,
+ (!ctx->active_reqs));
+
+ return ret;
+}
+
+/*
+ * Issues a flush (dcmd) request
+ */
+int mmc_blk_cmdq_issue_flush_rq(struct mmc_queue *mq, struct request *req)
+{
+ int err;
+ struct mmc_queue_req *active_mqrq;
+ struct mmc_card *card = mq->card;
+ struct mmc_host *host;
+ struct mmc_cmdq_req *cmdq_req;
+ struct mmc_cmdq_context_info *ctx_info;
+
+ BUG_ON(!card);
+ host = card->host;
+ BUG_ON(!host);
+ BUG_ON(req->tag > card->ext_csd.cmdq_depth);
+ BUG_ON(test_and_set_bit(req->tag, &host->cmdq_ctx.active_reqs));
+
+ ctx_info = &host->cmdq_ctx;
+
+ set_bit(CMDQ_STATE_DCMD_ACTIVE, &ctx_info->curr_state);
+
+ active_mqrq = &mq->mqrq_cmdq[req->tag];
+ active_mqrq->req = req;
+
+ cmdq_req = mmc_cmdq_prep_dcmd(active_mqrq, mq);
+ cmdq_req->cmdq_req_flags |= QBR;
+ cmdq_req->mrq.cmd = &cmdq_req->cmd;
+ cmdq_req->tag = req->tag;
+
+ err = mmc_cmdq_prepare_flush(cmdq_req->mrq.cmd);
+ if (err) {
+ pr_err("%s: failed (%d) preparing flush req\n",
+ mmc_hostname(host), err);
+ return err;
+ }
+ err = mmc_blk_cmdq_start_req(card->host, cmdq_req);
+ return err;
+}
+EXPORT_SYMBOL(mmc_blk_cmdq_issue_flush_rq);
+
+static inline int mmc_blk_cmdq_part_switch(struct mmc_card *card,
+ struct mmc_blk_data *md)
+{
+ struct mmc_blk_data *main_md = dev_get_drvdata(&card->dev);
+ struct mmc_host *host = card->host;
+ struct mmc_cmdq_context_info *ctx = &host->cmdq_ctx;
+ u8 part_config = card->ext_csd.part_config;
+
+ if ((main_md->part_curr == md->part_type) &&
+ (card->part_curr == md->part_type))
+ return 0;
+
+ WARN_ON(!((card->host->caps2 & MMC_CAP2_CMD_QUEUE) &&
+ card->ext_csd.cmdq_support &&
+ (md->flags & MMC_BLK_CMD_QUEUE)));
+
+ if (!test_bit(CMDQ_STATE_HALT, &ctx->curr_state))
+ WARN_ON(mmc_cmdq_halt(host, true));
+
+ /* disable CQ mode in card */
+ if (mmc_card_cmdq(card)) {
+ WARN_ON(mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_CMDQ, 0,
+ card->ext_csd.generic_cmd6_time));
+ mmc_card_clr_cmdq(card);
+ }
+
+ part_config &= ~EXT_CSD_PART_CONFIG_ACC_MASK;
+ part_config |= md->part_type;
+
+ WARN_ON(mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_PART_CONFIG, part_config,
+ card->ext_csd.part_time));
+
+ card->ext_csd.part_config = part_config;
+ card->part_curr = md->part_type;
+
+ main_md->part_curr = md->part_type;
+
+ WARN_ON(mmc_blk_cmdq_switch(card, md, true));
+ WARN_ON(mmc_cmdq_halt(host, false));
+
+ return 0;
+}
+
+static struct mmc_cmdq_req *mmc_blk_cmdq_prep_discard_req(struct mmc_queue *mq,
+ struct request *req)
+{
+ struct mmc_blk_data *md = mq->data;
+ struct mmc_card *card = md->queue.card;
+ struct mmc_host *host = card->host;
+ struct mmc_cmdq_context_info *ctx_info = &host->cmdq_ctx;
+ struct mmc_cmdq_req *cmdq_req;
+ struct mmc_queue_req *active_mqrq;
+
+ BUG_ON(req->tag > card->ext_csd.cmdq_depth);
+ BUG_ON(test_and_set_bit(req->tag, &host->cmdq_ctx.active_reqs));
+
+ set_bit(CMDQ_STATE_DCMD_ACTIVE, &ctx_info->curr_state);
+
+ active_mqrq = &mq->mqrq_cmdq[req->tag];
+ active_mqrq->req = req;
+
+ cmdq_req = mmc_cmdq_prep_dcmd(active_mqrq, mq);
+ cmdq_req->cmdq_req_flags |= QBR;
+ cmdq_req->mrq.cmd = &cmdq_req->cmd;
+ cmdq_req->tag = req->tag;
+ return cmdq_req;
+}
+
+static int mmc_blk_cmdq_issue_discard_rq(struct mmc_queue *mq,
+ struct request *req)
+{
+ struct mmc_blk_data *md = mq->data;
+ struct mmc_card *card = md->queue.card;
+ struct mmc_cmdq_req *cmdq_req = NULL;
+ unsigned int from, nr, arg;
+ int err = 0;
+
+ if (!mmc_can_erase(card)) {
+ err = -EOPNOTSUPP;
+ blk_end_request(req, err, blk_rq_bytes(req));
+ goto out;
+ }
+
+ from = blk_rq_pos(req);
+ nr = blk_rq_sectors(req);
+
+ if (mmc_can_discard(card))
+ arg = MMC_DISCARD_ARG;
+ else if (mmc_can_trim(card))
+ arg = MMC_TRIM_ARG;
+ else
+ arg = MMC_ERASE_ARG;
+
+ cmdq_req = mmc_blk_cmdq_prep_discard_req(mq, req);
+ if (card->quirks & MMC_QUIRK_INAND_CMD38) {
+ __mmc_switch_cmdq_mode(cmdq_req->mrq.cmd,
+ EXT_CSD_CMD_SET_NORMAL,
+ INAND_CMD38_ARG_EXT_CSD,
+ arg == MMC_TRIM_ARG ?
+ INAND_CMD38_ARG_TRIM :
+ INAND_CMD38_ARG_ERASE,
+ 0, true, false);
+ err = mmc_cmdq_wait_for_dcmd(card->host, cmdq_req);
+ if (err)
+ goto clear_dcmd;
+ }
+ err = mmc_cmdq_erase(cmdq_req, card, from, nr, arg);
+clear_dcmd:
+ blk_complete_request(req);
+out:
+ return err ? 1 : 0;
+}
+
+static int mmc_blk_cmdq_issue_secdiscard_rq(struct mmc_queue *mq,
+ struct request *req)
+{
+ struct mmc_blk_data *md = mq->data;
+ struct mmc_card *card = md->queue.card;
+ struct mmc_cmdq_req *cmdq_req = NULL;
+ unsigned int from, nr, arg;
+ int err = 0;
+
+ if (!(mmc_can_secure_erase_trim(card))) {
+ err = -EOPNOTSUPP;
+ blk_end_request(req, err, blk_rq_bytes(req));
+ goto out;
+ }
+
+ from = blk_rq_pos(req);
+ nr = blk_rq_sectors(req);
+
+ if (mmc_can_trim(card) && !mmc_erase_group_aligned(card, from, nr))
+ arg = MMC_SECURE_TRIM1_ARG;
+ else
+ arg = MMC_SECURE_ERASE_ARG;
+
+ cmdq_req = mmc_blk_cmdq_prep_discard_req(mq, req);
+ if (card->quirks & MMC_QUIRK_INAND_CMD38) {
+ __mmc_switch_cmdq_mode(cmdq_req->mrq.cmd,
+ EXT_CSD_CMD_SET_NORMAL,
+ INAND_CMD38_ARG_EXT_CSD,
+ arg == MMC_SECURE_TRIM1_ARG ?
+ INAND_CMD38_ARG_SECTRIM1 :
+ INAND_CMD38_ARG_SECERASE,
+ 0, true, false);
+ err = mmc_cmdq_wait_for_dcmd(card->host, cmdq_req);
+ if (err)
+ goto clear_dcmd;
+ }
+
+ err = mmc_cmdq_erase(cmdq_req, card, from, nr, arg);
+ if (err)
+ goto clear_dcmd;
+
+ if (arg == MMC_SECURE_TRIM1_ARG) {
+ if (card->quirks & MMC_QUIRK_INAND_CMD38) {
+ __mmc_switch_cmdq_mode(cmdq_req->mrq.cmd,
+ EXT_CSD_CMD_SET_NORMAL,
+ INAND_CMD38_ARG_EXT_CSD,
+ INAND_CMD38_ARG_SECTRIM2,
+ 0, true, false);
+ err = mmc_cmdq_wait_for_dcmd(card->host, cmdq_req);
+ if (err)
+ goto clear_dcmd;
+ }
+
+ err = mmc_cmdq_erase(cmdq_req, card, from, nr,
+ MMC_SECURE_TRIM2_ARG);
+ }
+clear_dcmd:
+ blk_complete_request(req);
+out:
+ return err ? 1 : 0;
+}
+
+static int mmc_blk_cmdq_issue_rq(struct mmc_queue *mq, struct request *req)
+{
+ int ret;
+ struct mmc_blk_data *md = mq->data;
+ struct mmc_card *card = md->queue.card;
+
+ mmc_get_card(card);
+
+#ifdef CONFIG_MMC_BLOCK_DEFERRED_RESUME
+ if (mmc_bus_needs_resume(card->host))
+ mmc_resume_bus(card->host);
+#endif
+ if (!card->host->cmdq_ctx.active_reqs && mmc_card_doing_bkops(card)) {
+ ret = mmc_cmdq_halt(card->host, true);
+ if (ret)
+ goto out;
+ ret = mmc_stop_bkops(card);
+ if (ret) {
+ pr_err("%s: %s: mmc_stop_bkops failed %d\n",
+ md->disk->disk_name, __func__, ret);
+ goto out;
+ }
+ ret = mmc_cmdq_halt(card->host, false);
+ if (ret)
+ goto out;
+ }
+
+ ret = mmc_blk_cmdq_part_switch(card, md);
+ if (ret) {
+ pr_err("%s: %s: partition switch failed %d\n",
+ md->disk->disk_name, __func__, ret);
+ goto out;
+ }
+
+ if (req) {
+ struct mmc_host *host = card->host;
+ struct mmc_cmdq_context_info *ctx = &host->cmdq_ctx;
+
+ if ((req_op(req) == REQ_OP_FLUSH || req_op(req) == REQ_OP_DISCARD) &&
+ (card->quirks & MMC_QUIRK_CMDQ_EMPTY_BEFORE_DCMD) &&
+ ctx->active_small_sector_read_reqs) {
+ ret = wait_event_interruptible(ctx->queue_empty_wq,
+ !ctx->active_reqs);
+ if (ret) {
+ pr_err("%s: failed while waiting for the CMDQ to be empty %s err (%d)\n",
+ mmc_hostname(host),
+ __func__, ret);
+ BUG_ON(1);
+ }
+ /* clear the counter now */
+ ctx->active_small_sector_read_reqs = 0;
+ /*
+ * If there were small sector (less than 8 sectors) read
+ * operations in progress then we have to wait for the
+ * outstanding requests to finish and should also have
+ * atleast 6 microseconds delay before queuing the DCMD
+ * request.
+ */
+ udelay(MMC_QUIRK_CMDQ_DELAY_BEFORE_DCMD);
+ }
+
+ if (req_op(req) == REQ_OP_DISCARD) {
+ if (req_op(req) == REQ_OP_SECURE_ERASE &&
+ !(card->quirks & MMC_QUIRK_SEC_ERASE_TRIM_BROKEN))
+ ret = mmc_blk_cmdq_issue_secdiscard_rq(mq, req);
+ else
+ ret = mmc_blk_cmdq_issue_discard_rq(mq, req);
+ } else if (req_op(req) == REQ_OP_FLUSH) {
+ ret = mmc_blk_cmdq_issue_flush_rq(mq, req);
+ } else {
+ ret = mmc_blk_cmdq_issue_rw_rq(mq, req);
+ }
+ }
+
+ return ret;
+
+out:
+ if (req)
+ blk_end_request_all(req, ret);
+ mmc_put_card(card);
+
+ return ret;
+}
+
+static void mmc_blk_cmdq_reset(struct mmc_host *host, bool clear_all)
+{
+ int err = 0;
+
+ if (mmc_cmdq_halt(host, true)) {
+ pr_err("%s: halt failed\n", mmc_hostname(host));
+ goto reset;
+ }
+
+ if (clear_all)
+ mmc_cmdq_discard_queue(host, 0);
+reset:
+ host->cmdq_ops->disable(host, true);
+ err = mmc_cmdq_hw_reset(host);
+ if (err && err != -EOPNOTSUPP) {
+ pr_err("%s: failed to cmdq_hw_reset err = %d\n",
+ mmc_hostname(host), err);
+ host->cmdq_ops->enable(host);
+ mmc_cmdq_halt(host, false);
+ goto out;
+ }
+ /*
+ * CMDQ HW reset would have already made CQE
+ * in unhalted state, but reflect the same
+ * in software state of cmdq_ctx.
+ */
+ mmc_host_clr_halt(host);
+out:
+ return;
+}
+
+/**
+ * is_cmdq_dcmd_req - Checks if tag belongs to DCMD request.
+ * @q: request_queue pointer.
+ * @tag: tag number of request to check.
+ *
+ * This function checks if the request with tag number "tag"
+ * is a DCMD request or not based on cmdq_req_flags set.
+ *
+ * returns true if DCMD req, otherwise false.
+ */
+static bool is_cmdq_dcmd_req(struct request_queue *q, int tag)
+{
+ struct request *req;
+ struct mmc_queue_req *mq_rq;
+ struct mmc_cmdq_req *cmdq_req;
+
+ req = blk_queue_find_tag(q, tag);
+ if (WARN_ON(!req))
+ goto out;
+ mq_rq = req->special;
+ if (WARN_ON(!mq_rq))
+ goto out;
+ cmdq_req = &(mq_rq->cmdq_req);
+ return (cmdq_req->cmdq_req_flags & DCMD);
+out:
+ return -ENOENT;
+}
+
+/**
+ * mmc_blk_cmdq_reset_all - Reset everything for CMDQ block request.
+ * @host: mmc_host pointer.
+ * @err: error for which reset is performed.
+ *
+ * This function implements reset_all functionality for
+ * cmdq. It resets the controller, power cycle the card,
+ * and invalidate all busy tags(requeue all request back to
+ * elevator).
+ */
+static void mmc_blk_cmdq_reset_all(struct mmc_host *host, int err)
+{
+ struct mmc_request *mrq = host->err_mrq;
+ struct mmc_card *card = host->card;
+ struct mmc_cmdq_context_info *ctx_info = &host->cmdq_ctx;
+ struct request_queue *q;
+ int itag = 0;
+ int ret = 0;
+
+ if (WARN_ON(!mrq))
+ return;
+
+ q = mrq->req->q;
+ WARN_ON(!test_bit(CMDQ_STATE_ERR, &ctx_info->curr_state));
+
+ pr_debug("%s: %s: active_reqs = %lu\n",
+ mmc_hostname(host), __func__,
+ ctx_info->active_reqs);
+
+ mmc_blk_cmdq_reset(host, false);
+
+ for_each_set_bit(itag, &ctx_info->active_reqs,
+ host->num_cq_slots) {
+ ret = is_cmdq_dcmd_req(q, itag);
+ if (WARN_ON(ret == -ENOENT))
+ continue;
+ if (!ret) {
+ WARN_ON(!test_and_clear_bit(itag,
+ &ctx_info->data_active_reqs));
+ mmc_cmdq_post_req(host, itag, err);
+ } else {
+ clear_bit(CMDQ_STATE_DCMD_ACTIVE,
+ &ctx_info->curr_state);
+ }
+ WARN_ON(!test_and_clear_bit(itag,
+ &ctx_info->active_reqs));
+ mmc_put_card(card);
+ }
+
+ spin_lock_irq(q->queue_lock);
+ blk_queue_invalidate_tags(q);
+ spin_unlock_irq(q->queue_lock);
+}
+
+static void mmc_blk_cmdq_shutdown(struct mmc_queue *mq)
+{
+ int err;
+ struct mmc_card *card = mq->card;
+ struct mmc_host *host = card->host;
+
+ mmc_get_card(card);
+ err = mmc_cmdq_halt(host, true);
+ if (err) {
+ pr_err("%s: halt: failed: %d\n", __func__, err);
+ goto out;
+ }
+
+ /* disable CQ mode in card */
+ if (mmc_card_cmdq(card)) {
+ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_CMDQ, 0,
+ card->ext_csd.generic_cmd6_time);
+ if (err) {
+ pr_err("%s: failed to switch card to legacy mode: %d\n",
+ __func__, err);
+ goto out;
+ }
+ mmc_card_clr_cmdq(card);
+ }
+ host->cmdq_ops->disable(host, false);
+ host->card->cmdq_init = false;
+out:
+ mmc_put_card(card);
+}
+
+static enum blk_eh_timer_return mmc_blk_cmdq_req_timed_out(struct request *req)
+{
+ struct mmc_queue *mq = req->q->queuedata;
+ struct mmc_host *host = mq->card->host;
+ struct mmc_queue_req *mq_rq = req->special;
+ struct mmc_request *mrq;
+ struct mmc_cmdq_req *cmdq_req;
+ struct mmc_cmdq_context_info *ctx_info = &host->cmdq_ctx;
+
+ BUG_ON(!host);
+
+ /*
+ * The mmc_queue_req will be present only if the request
+ * is issued to the LLD. The request could be fetched from
+ * block layer queue but could be waiting to be issued
+ * (for e.g. clock scaling is waiting for an empty cmdq queue)
+ * Reset the timer in such cases to give LLD more time
+ */
+ if (!mq_rq) {
+ pr_warn("%s: restart timer for tag: %d\n", __func__, req->tag);
+ return BLK_EH_RESET_TIMER;
+ }
+
+ mrq = &mq_rq->cmdq_req.mrq;
+ cmdq_req = &mq_rq->cmdq_req;
+
+ BUG_ON(!mrq || !cmdq_req);
+
+ if (cmdq_req->cmdq_req_flags & DCMD)
+ mrq->cmd->error = -ETIMEDOUT;
+ else
+ mrq->data->error = -ETIMEDOUT;
+
+ if (mrq->cmd && mrq->cmd->error) {
+ if (!(req_op(req) == REQ_OP_FLUSH)) {
+ /*
+ * Notify completion for non flush commands like
+ * discard that wait for DCMD finish.
+ */
+ set_bit(CMDQ_STATE_REQ_TIMED_OUT,
+ &ctx_info->curr_state);
+ complete(&mrq->completion);
+ return BLK_EH_NOT_HANDLED;
+ }
+ }
+
+ if (test_bit(CMDQ_STATE_REQ_TIMED_OUT, &ctx_info->curr_state) ||
+ test_bit(CMDQ_STATE_ERR, &ctx_info->curr_state))
+ return BLK_EH_NOT_HANDLED;
+
+ set_bit(CMDQ_STATE_REQ_TIMED_OUT, &ctx_info->curr_state);
+ return BLK_EH_HANDLED;
+}
+
+/*
+ * mmc_blk_cmdq_err: error handling of cmdq error requests.
+ * Function should be called in context of error out request
+ * which has claim_host and rpm acquired.
+ * This may be called with CQ engine halted. Make sure to
+ * unhalt it after error recovery.
+ *
+ * TODO: Currently cmdq error handler does reset_all in case
+ * of any erorr. Need to optimize error handling.
+ */
+static void mmc_blk_cmdq_err(struct mmc_queue *mq)
+{
+ struct mmc_host *host = mq->card->host;
+ struct mmc_request *mrq = host->err_mrq;
+ struct mmc_cmdq_context_info *ctx_info = &host->cmdq_ctx;
+ struct request_queue *q;
+ int err;
+
+ host->cmdq_ops->dumpstate(host);
+
+ if (WARN_ON(!mrq))
+ return;
+
+ q = mrq->req->q;
+ err = mmc_cmdq_halt(host, true);
+ if (err) {
+ pr_err("halt: failed: %d\n", err);
+ goto reset;
+ }
+
+ /* RED error - Fatal: requires reset */
+ if (mrq->cmdq_req->resp_err) {
+ err = mrq->cmdq_req->resp_err;
+ pr_crit("%s: Response error detected: Device in bad state\n",
+ mmc_hostname(host));
+ goto reset;
+ }
+
+ /*
+ * In case of software request time-out, we schedule err work only for
+ * the first error out request and handles all other request in flight
+ * here.
+ */
+ if (test_bit(CMDQ_STATE_REQ_TIMED_OUT, &ctx_info->curr_state)) {
+ err = -ETIMEDOUT;
+ } else if (mrq->data && mrq->data->error) {
+ err = mrq->data->error;
+ } else if (mrq->cmd && mrq->cmd->error) {
+ /* DCMD commands */
+ err = mrq->cmd->error;
+ }
+
+reset:
+ mmc_blk_cmdq_reset_all(host, err);
+ if (mrq->cmdq_req->resp_err)
+ mrq->cmdq_req->resp_err = false;
+ mmc_cmdq_halt(host, false);
+
+ host->err_mrq = NULL;
+ clear_bit(CMDQ_STATE_REQ_TIMED_OUT, &ctx_info->curr_state);
+ WARN_ON(!test_and_clear_bit(CMDQ_STATE_ERR, &ctx_info->curr_state));
+ wake_up(&ctx_info->wait);
+}
+
+/* invoked by block layer in softirq context */
+void mmc_blk_cmdq_complete_rq(struct request *rq)
+{
+ struct mmc_queue_req *mq_rq = rq->special;
+ struct mmc_request *mrq = &mq_rq->cmdq_req.mrq;
+ struct mmc_host *host = mrq->host;
+ struct mmc_cmdq_context_info *ctx_info = &host->cmdq_ctx;
+ struct mmc_cmdq_req *cmdq_req = &mq_rq->cmdq_req;
+ struct mmc_queue *mq = (struct mmc_queue *)rq->q->queuedata;
+ int err = 0;
+ bool is_dcmd = false;
+
+ if (mrq->cmd && mrq->cmd->error)
+ err = mrq->cmd->error;
+ else if (mrq->data && mrq->data->error)
+ err = mrq->data->error;
+
+ if (err || cmdq_req->resp_err) {
+ pr_err("%s: %s: txfr error(%d)/resp_err(%d)\n",
+ mmc_hostname(mrq->host), __func__, err,
+ cmdq_req->resp_err);
+ if (test_bit(CMDQ_STATE_ERR, &ctx_info->curr_state)) {
+ pr_err("%s: CQ in error state, ending current req: %d\n",
+ __func__, err);
+ } else {
+ set_bit(CMDQ_STATE_ERR, &ctx_info->curr_state);
+ BUG_ON(host->err_mrq != NULL);
+ host->err_mrq = mrq;
+ schedule_work(&mq->cmdq_err_work);
+ }
+ goto out;
+ }
+ /*
+ * In case of error CMDQ is expected to be either in halted
+ * or disable state so cannot receive any completion of
+ * other requests.
+ */
+ BUG_ON(test_bit(CMDQ_STATE_ERR, &ctx_info->curr_state));
+
+ /* clear pending request */
+ BUG_ON(!test_and_clear_bit(cmdq_req->tag,
+ &ctx_info->active_reqs));
+ if (cmdq_req->cmdq_req_flags & DCMD)
+ is_dcmd = true;
+ else
+ BUG_ON(!test_and_clear_bit(cmdq_req->tag,
+ &ctx_info->data_active_reqs));
+ if (!is_dcmd)
+ mmc_cmdq_post_req(host, cmdq_req->tag, err);
+ if (cmdq_req->cmdq_req_flags & DCMD) {
+ clear_bit(CMDQ_STATE_DCMD_ACTIVE, &ctx_info->curr_state);
+ blk_end_request_all(rq, err);
+ goto out;
+ }
+
+ blk_end_request(rq, err, cmdq_req->data.bytes_xfered);
+
+out:
+
+ if (!test_bit(CMDQ_STATE_ERR, &ctx_info->curr_state)) {
+ wake_up(&ctx_info->wait);
+ mmc_put_card(host->card);
+ }
+
+ if (!ctx_info->active_reqs)
+ wake_up_interruptible(&host->cmdq_ctx.queue_empty_wq);
+
+ if (blk_queue_stopped(mq->queue) && !ctx_info->active_reqs)
+ complete(&mq->cmdq_shutdown_complete);
+
+ return;
+}
+
static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
struct device *parent,
sector_t size,
@@ -2262,7 +3159,7 @@
INIT_LIST_HEAD(&md->part);
md->usage = 1;
- ret = mmc_init_queue(&md->queue, card, &md->lock, subname);
+ ret = mmc_init_queue(&md->queue, card, &md->lock, subname, area_type);
if (ret)
goto err_putdisk;
@@ -2318,7 +3215,16 @@
blk_queue_write_cache(md->queue.queue, true, true);
}
- if (mmc_card_mmc(card) &&
+ if (card->cmdq_init) {
+ md->flags |= MMC_BLK_CMD_QUEUE;
+ md->queue.cmdq_complete_fn = mmc_blk_cmdq_complete_rq;
+ md->queue.cmdq_issue_fn = mmc_blk_cmdq_issue_rq;
+ md->queue.cmdq_error_fn = mmc_blk_cmdq_err;
+ md->queue.cmdq_req_timed_out = mmc_blk_cmdq_req_timed_out;
+ md->queue.cmdq_shutdown = mmc_blk_cmdq_shutdown;
+ }
+
+ if (mmc_card_mmc(card) && !card->cmdq_init &&
(area_type == MMC_BLK_DATA_AREA_MAIN) &&
(md->flags & MMC_BLK_CMD23) &&
card->ext_csd.packed_event_en) {
@@ -2431,6 +3337,8 @@
mmc_cleanup_queue(&md->queue);
if (md->flags & MMC_BLK_PACKED_CMD)
mmc_packed_clean(&md->queue);
+ if (md->flags & MMC_BLK_CMD_QUEUE)
+ mmc_cmdq_clean(&md->queue, card);
if (md->disk->flags & GENHD_FL_UP) {
device_remove_file(disk_to_dev(md->disk), &md->force_ro);
if ((md->area_type & MMC_BLK_DATA_AREA_BOOT) &&
@@ -2648,23 +3556,36 @@
dev_set_drvdata(&card->dev, NULL);
}
-static int _mmc_blk_suspend(struct mmc_card *card)
+static int _mmc_blk_suspend(struct mmc_card *card, bool wait)
{
struct mmc_blk_data *part_md;
struct mmc_blk_data *md = dev_get_drvdata(&card->dev);
+ int rc = 0;
if (md) {
- mmc_queue_suspend(&md->queue);
+ rc = mmc_queue_suspend(&md->queue, wait);
+ if (rc)
+ goto out;
list_for_each_entry(part_md, &md->part, part) {
- mmc_queue_suspend(&part_md->queue);
+ rc = mmc_queue_suspend(&part_md->queue, wait);
+ if (rc)
+ goto out_resume;
}
}
- return 0;
+ goto out;
+
+ out_resume:
+ mmc_queue_resume(&md->queue);
+ list_for_each_entry(part_md, &md->part, part) {
+ mmc_queue_resume(&part_md->queue);
+ }
+ out:
+ return rc;
}
static void mmc_blk_shutdown(struct mmc_card *card)
{
- _mmc_blk_suspend(card);
+ _mmc_blk_suspend(card, 1);
}
#ifdef CONFIG_PM_SLEEP
@@ -2672,7 +3593,7 @@
{
struct mmc_card *card = mmc_dev_to_card(dev);
- return _mmc_blk_suspend(card);
+ return _mmc_blk_suspend(card, 0);
}
static int mmc_blk_resume(struct device *dev)
diff -urN linux-4.9.37/drivers/mmc/card/queue.c linux-4.9.y/drivers/mmc/card/queue.c
--- linux-4.9.37/drivers/mmc/card/queue.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/mmc/card/queue.c 2021-06-07 13:01:33.000000000 +0300
@@ -179,6 +179,122 @@
queue_flag_set_unlocked(QUEUE_FLAG_SECERASE, q);
}
+static struct request *mmc_peek_request(struct mmc_queue *mq)
+{
+ struct request_queue *q = mq->queue;
+ mq->cmdq_req_peeked = NULL;
+
+ spin_lock_irq(q->queue_lock);
+ if (!blk_queue_stopped(q))
+ mq->cmdq_req_peeked = blk_peek_request(q);
+ spin_unlock_irq(q->queue_lock);
+
+ return mq->cmdq_req_peeked;
+}
+
+static bool mmc_check_blk_queue_start_tag(struct request_queue *q,
+ struct request *req)
+{
+ int ret;
+
+ spin_lock_irq(q->queue_lock);
+ ret = blk_queue_start_tag(q, req);
+ spin_unlock_irq(q->queue_lock);
+
+ return !!ret;
+}
+
+static inline void mmc_cmdq_ready_wait(struct mmc_host *host,
+ struct mmc_queue *mq)
+{
+ struct mmc_cmdq_context_info *ctx = &host->cmdq_ctx;
+ struct request_queue *q = mq->queue;
+
+ /*
+ * Wait until all of the following conditions are true:
+ * 1. There is a request pending in the block layer queue
+ * to be processed.
+ * 2. If the peeked request is flush/discard then there shouldn't
+ * be any other direct command active.
+ * 3. cmdq state should be unhalted.
+ * 4. cmdq state shouldn't be in error state.
+ * 5. free tag available to process the new request.
+ */
+ wait_event(ctx->wait, kthread_should_stop()
+ || (mmc_peek_request(mq) &&
+ !((mq->cmdq_req_peeked->cmd_flags & (REQ_OP_FLUSH | REQ_OP_DISCARD))
+ && test_bit(CMDQ_STATE_DCMD_ACTIVE, &ctx->curr_state))
+ && !(!host->card->part_curr && !mmc_card_suspended(host->card)
+ && mmc_host_halt(host))
+ && !(!host->card->part_curr && mmc_host_cq_disable(host) &&
+ !mmc_card_suspended(host->card))
+ && !test_bit(CMDQ_STATE_ERR, &ctx->curr_state)
+ && !mmc_check_blk_queue_start_tag(q, mq->cmdq_req_peeked)));
+}
+
+static int mmc_cmdq_thread(void *d)
+{
+ struct mmc_queue *mq = d;
+ struct mmc_card *card = mq->card;
+ struct mmc_host *host = card->host;
+
+ current->flags |= PF_MEMALLOC;
+
+ while (1) {
+ int ret = 0;
+
+ mmc_cmdq_ready_wait(host, mq);
+ if (kthread_should_stop())
+ break;
+
+ ret = mq->cmdq_issue_fn(mq, mq->cmdq_req_peeked);
+ /*
+ * Don't requeue if issue_fn fails, just bug on.
+ * We don't expect failure here and there is no recovery other
+ * than fixing the actual issue if there is any.
+ * Also we end the request if there is a partition switch error,
+ * so we should not requeue the request here.
+ */
+ if (ret)
+ BUG_ON(1);
+ } /* loop */
+
+ return 0;
+}
+
+static void mmc_cmdq_dispatch_req(struct request_queue *q)
+{
+ struct mmc_queue *mq = q->queuedata;
+
+ wake_up(&mq->card->host->cmdq_ctx.wait);
+}
+
+/**
+ * mmc_blk_cmdq_setup_queue
+ * @mq: mmc queue
+ * @card: card to attach to this queue
+ *
+ * Setup queue for CMDQ supporting MMC card
+ */
+void mmc_cmdq_setup_queue(struct mmc_queue *mq, struct mmc_card *card)
+{
+ u64 limit = BLK_BOUNCE_HIGH;
+ struct mmc_host *host = card->host;
+
+ if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask)
+ limit = *mmc_dev(host)->dma_mask;
+
+ queue_flag_set_unlocked(QUEUE_FLAG_NONROT, mq->queue);
+ if (mmc_can_erase(card))
+ mmc_queue_setup_discard(mq->queue, card);
+
+ blk_queue_bounce_limit(mq->queue, limit);
+ blk_queue_max_hw_sectors(mq->queue, min(host->max_blk_count,
+ host->max_req_size / 512));
+ blk_queue_max_segment_size(mq->queue, host->max_seg_size);
+ blk_queue_max_segments(mq->queue, host->max_segs);
+}
+
/**
* mmc_init_queue - initialise a queue structure.
* @mq: mmc queue
@@ -189,7 +305,7 @@
* Initialise a MMC card request queue.
*/
int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
- spinlock_t *lock, const char *subname)
+ spinlock_t *lock, const char *subname, int area_type)
{
struct mmc_host *host = card->host;
u64 limit = BLK_BOUNCE_HIGH;
@@ -201,6 +317,37 @@
limit = (u64)dma_max_pfn(mmc_dev(host)) << PAGE_SHIFT;
mq->card = card;
+ if (card->ext_csd.cmdq_support &&
+ (area_type == MMC_BLK_DATA_AREA_MAIN)) {
+ mq->queue = blk_init_queue(mmc_cmdq_dispatch_req, lock);
+ if (!mq->queue)
+ return -ENOMEM;
+ mmc_cmdq_setup_queue(mq, card);
+ ret = mmc_cmdq_init(mq, card);
+ if (ret) {
+ pr_err("%s: %d: cmdq: unable to set-up\n",
+ mmc_hostname(card->host), ret);
+ blk_cleanup_queue(mq->queue);
+ } else {
+ sema_init(&mq->thread_sem, 1);
+ /* hook for pm qos cmdq init */
+ if (card->host->cmdq_ops->init)
+ card->host->cmdq_ops->init(card->host);
+ mq->queue->queuedata = mq;
+ mq->thread = kthread_run(mmc_cmdq_thread, mq,
+ "mmc-cmdqd/%d%s",
+ host->index,
+ subname ? subname : "");
+ if (IS_ERR(mq->thread)) {
+ pr_err("%s: %d: cmdq: failed to start mmc-cmdqd thread\n",
+ mmc_hostname(card->host), ret);
+ ret = PTR_ERR(mq->thread);
+ }
+
+ return ret;
+ }
+ }
+
mq->queue = blk_init_queue(mmc_request_fn, lock);
if (!mq->queue)
return -ENOMEM;
@@ -413,20 +560,76 @@
* complete any outstanding requests. This ensures that we
* won't suspend while a request is being processed.
*/
-void mmc_queue_suspend(struct mmc_queue *mq)
+int mmc_queue_suspend(struct mmc_queue *mq, int wait)
{
struct request_queue *q = mq->queue;
unsigned long flags;
+ int rc = 0;
+ struct mmc_card *card = mq->card;
+ struct request *req;
if (!(mq->flags & MMC_QUEUE_SUSPENDED)) {
mq->flags |= MMC_QUEUE_SUSPENDED;
- spin_lock_irqsave(q->queue_lock, flags);
- blk_stop_queue(q);
- spin_unlock_irqrestore(q->queue_lock, flags);
+ if (card->cmdq_init && blk_queue_tagged(q)) {
+ struct mmc_host *host = card->host;
- down(&mq->thread_sem);
+ if (wait) {
+ /*
+ * After blk_stop_queue is called, wait for all
+ * active_reqs to complete.
+ * Then wait for cmdq thread to exit before calling
+ * cmdq shutdown to avoid race between issuing
+ * requests and shutdown of cmdq.
+ */
+ spin_lock_irqsave(q->queue_lock, flags);
+ blk_stop_queue(q);
+ spin_unlock_irqrestore(q->queue_lock, flags);
+
+ if (host->cmdq_ctx.active_reqs)
+ wait_for_completion(
+ &mq->cmdq_shutdown_complete);
+ kthread_stop(mq->thread);
+ mq->cmdq_shutdown(mq);
+ } else {
+ spin_lock_irqsave(q->queue_lock, flags);
+ blk_stop_queue(q);
+ wake_up(&host->cmdq_ctx.wait);
+ req = blk_peek_request(q);
+ if (req || mq->cmdq_req_peeked ||
+ host->cmdq_ctx.active_reqs) {
+ mq->flags &= ~MMC_QUEUE_SUSPENDED;
+ blk_start_queue(q);
+ rc = -EBUSY;
+ }
+ spin_unlock_irqrestore(q->queue_lock, flags);
+ }
+
+ goto out;
+ } else {
+ spin_lock_irqsave(q->queue_lock, flags);
+ blk_stop_queue(q);
+ spin_unlock_irqrestore(q->queue_lock, flags);
+
+ rc = down_trylock(&mq->thread_sem);
+ if (rc && !wait) {
+ /*
+ * Failed to take the lock so better to abort the
+ * suspend because mmcqd thread is processing requests.
+ */
+ mq->flags &= ~MMC_QUEUE_SUSPENDED;
+ spin_lock_irqsave(q->queue_lock, flags);
+ blk_start_queue(q);
+ spin_unlock_irqrestore(q->queue_lock, flags);
+ rc = -EBUSY;
+ } else if (rc && wait) {
+ down(&mq->thread_sem);
+ rc = 0;
+ }
+ }
}
+out:
+ return rc;
}
/**
@@ -555,3 +758,105 @@
sg_copy_from_buffer(mqrq->bounce_sg, mqrq->bounce_sg_len,
mqrq->bounce_buf, mqrq->sg[0].length);
}
+
+static void mmc_cmdq_softirq_done(struct request *rq)
+{
+ struct mmc_queue *mq = rq->q->queuedata;
+ mq->cmdq_complete_fn(rq);
+}
+
+static void mmc_cmdq_error_work(struct work_struct *work)
+{
+ struct mmc_queue *mq = container_of(work, struct mmc_queue,
+ cmdq_err_work);
+
+ mq->cmdq_error_fn(mq);
+}
+
+enum blk_eh_timer_return mmc_cmdq_rq_timed_out(struct request *req)
+{
+ struct mmc_queue *mq = req->q->queuedata;
+
+ pr_err("%s: request with tag: %d flags: 0x%llx timed out\n",
+ mmc_hostname(mq->card->host), req->tag, req->cmd_flags);
+
+ return mq->cmdq_req_timed_out(req);
+}
+
+int mmc_cmdq_init(struct mmc_queue *mq, struct mmc_card *card)
+{
+ int i, ret = 0;
+ /* one slot is reserved for dcmd requests */
+ int q_depth = card->ext_csd.cmdq_depth - 1;
+
+ card->cmdq_init = false;
+ if (!(card->host->caps2 & MMC_CAP2_CMD_QUEUE)) {
+ ret = -ENOTSUPP;
+ goto out;
+ }
+
+ init_waitqueue_head(&card->host->cmdq_ctx.queue_empty_wq);
+ init_waitqueue_head(&card->host->cmdq_ctx.wait);
+
+ mq->mqrq_cmdq = kzalloc(
+ sizeof(struct mmc_queue_req) * q_depth, GFP_KERNEL);
+ if (!mq->mqrq_cmdq) {
+ pr_warn("%s: unable to allocate mqrq's for q_depth %d\n",
+ mmc_card_name(card), q_depth);
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* sg is allocated for data request slots only */
+ for (i = 0; i < q_depth; i++) {
+ mq->mqrq_cmdq[i].sg = mmc_alloc_sg(card->host->max_segs, &ret);
+ if (ret) {
+ pr_warn("%s: unable to allocate cmdq sg of size %d\n",
+ mmc_card_name(card),
+ card->host->max_segs);
+ goto free_mqrq_sg;
+ }
+ }
+
+ ret = blk_queue_init_tags(mq->queue, q_depth, NULL, BLK_TAG_ALLOC_FIFO);
+ if (ret) {
+ pr_warn("%s: unable to allocate cmdq tags %d\n",
+ mmc_card_name(card), q_depth);
+ goto free_mqrq_sg;
+ }
+
+ blk_queue_softirq_done(mq->queue, mmc_cmdq_softirq_done);
+ INIT_WORK(&mq->cmdq_err_work, mmc_cmdq_error_work);
+ init_completion(&mq->cmdq_shutdown_complete);
+ init_completion(&mq->cmdq_pending_req_done);
+
+ blk_queue_rq_timed_out(mq->queue, mmc_cmdq_rq_timed_out);
+ blk_queue_rq_timeout(mq->queue, 120 * HZ);
+ card->cmdq_init = true;
+
+ goto out;
+
+free_mqrq_sg:
+ for (i = 0; i < q_depth; i++)
+ kfree(mq->mqrq_cmdq[i].sg);
+ kfree(mq->mqrq_cmdq);
+ mq->mqrq_cmdq = NULL;
+out:
+ return ret;
+}
+
+void mmc_cmdq_clean(struct mmc_queue *mq, struct mmc_card *card)
+{
+ int i;
+ int q_depth = card->ext_csd.cmdq_depth - 1;
+
+ blk_free_tags(mq->queue->queue_tags);
+ mq->queue->queue_tags = NULL;
+ blk_queue_free_tags(mq->queue);
+
+ for (i = 0; i < q_depth; i++)
+ kfree(mq->mqrq_cmdq[i].sg);
+ kfree(mq->mqrq_cmdq);
+ mq->mqrq_cmdq = NULL;
+}
+
diff -urN linux-4.9.37/drivers/mmc/card/queue.h linux-4.9.y/drivers/mmc/card/queue.h
--- linux-4.9.37/drivers/mmc/card/queue.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/mmc/card/queue.h 2021-06-07 13:01:33.000000000 +0300
@@ -48,6 +48,7 @@
struct mmc_async_req mmc_active;
enum mmc_packed_type cmd_type;
struct mmc_packed *packed;
+ struct mmc_cmdq_req cmdq_req;
};
struct mmc_queue {
@@ -62,12 +63,25 @@
struct mmc_queue_req mqrq[2];
struct mmc_queue_req *mqrq_cur;
struct mmc_queue_req *mqrq_prev;
+ struct mmc_queue_req *mqrq_cmdq;
+ struct work_struct cmdq_err_work;
+
+ struct completion cmdq_pending_req_done;
+ struct completion cmdq_shutdown_complete;
+ struct request *cmdq_req_peeked;
+
+ int (*cmdq_issue_fn)(struct mmc_queue *,
+ struct request *);
+ void (*cmdq_complete_fn)(struct request *);
+ void (*cmdq_error_fn)(struct mmc_queue *);
+ enum blk_eh_timer_return (*cmdq_req_timed_out)(struct request *);
+ void (*cmdq_shutdown)(struct mmc_queue *);
};
extern int mmc_init_queue(struct mmc_queue *, struct mmc_card *, spinlock_t *,
- const char *);
+ const char *, int);
extern void mmc_cleanup_queue(struct mmc_queue *);
-extern void mmc_queue_suspend(struct mmc_queue *);
+extern int mmc_queue_suspend(struct mmc_queue *, int);
extern void mmc_queue_resume(struct mmc_queue *);
extern unsigned int mmc_queue_map_sg(struct mmc_queue *,
@@ -79,5 +93,6 @@
extern void mmc_packed_clean(struct mmc_queue *);
extern int mmc_access_rpmb(struct mmc_queue *);
-
+extern int mmc_cmdq_init(struct mmc_queue *mq, struct mmc_card *card);
+extern void mmc_cmdq_clean(struct mmc_queue *mq, struct mmc_card *card);
#endif
diff -urN linux-4.9.37/drivers/mmc/core/core.c linux-4.9.y/drivers/mmc/core/core.c
--- linux-4.9.37/drivers/mmc/core/core.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/mmc/core/core.c 2021-06-07 13:01:33.000000000 +0300
@@ -569,7 +569,12 @@
mmc_hostname(host), __func__);
}
}
- if (!cmd->error || !cmd->retries ||
+
+ /*
+ * If the return code is EACCES, exit the loop. This solves the problem
+ * that the system suspends for a long time when the protected card is accessed.
+ */
+ if ((cmd->error == -EACCES) || !cmd->error || !cmd->retries ||
mmc_card_removed(host->card))
break;
@@ -641,6 +646,179 @@
host->ops->post_req(host, mrq, err);
}
+int mmc_cmdq_halt_on_empty_queue(struct mmc_host *host)
+{
+ int err = 0;
+
+ err = wait_event_interruptible(host->cmdq_ctx.queue_empty_wq,
+ (!host->cmdq_ctx.active_reqs));
+ if (host->cmdq_ctx.active_reqs) {
+ pr_err("%s: %s: unexpected active requests (%lu)\n",
+ mmc_hostname(host), __func__,
+ host->cmdq_ctx.active_reqs);
+ return -EPERM;
+ }
+
+ err = mmc_cmdq_halt(host, true);
+ if (err) {
+ pr_err("%s: %s: mmc_cmdq_halt failed (%d)\n",
+ mmc_hostname(host), __func__, err);
+ goto out;
+ }
+
+out:
+ return err;
+}
+EXPORT_SYMBOL(mmc_cmdq_halt_on_empty_queue);
+
+/**
+ * mmc_cmdq_discard_card_queue - discard the task[s] in the device
+ * @host: host instance
+ * @tasks: mask of tasks to be knocked off
+ * 0: remove all queued tasks
+ */
+int mmc_cmdq_discard_queue(struct mmc_host *host, u32 tasks)
+{
+ return mmc_discard_queue(host, tasks);
+}
+EXPORT_SYMBOL(mmc_cmdq_discard_queue);
+
+
+/**
+ * mmc_cmdq_post_req - post process of a completed request
+ * @host: host instance
+ * @tag: the request tag.
+ * @err: non-zero is error, success otherwise
+ */
+void mmc_cmdq_post_req(struct mmc_host *host, int tag, int err)
+{
+ if (likely(host->cmdq_ops->post_req))
+ host->cmdq_ops->post_req(host, tag, err);
+}
+EXPORT_SYMBOL(mmc_cmdq_post_req);
+
+/**
+ * mmc_cmdq_halt - halt/un-halt the command queue engine
+ * @host: host instance
+ * @halt: true - halt, un-halt otherwise
+ *
+ * Host halts the command queue engine. It should complete
+ * the ongoing transfer and release the bus.
+ * All legacy commands can be sent upon successful
+ * completion of this function.
+ * Returns 0 on success, negative otherwise
+ */
+int mmc_cmdq_halt(struct mmc_host *host, bool halt)
+{
+ int err = 0;
+
+ if ((halt && mmc_host_halt(host)) ||
+ (!halt && !mmc_host_halt(host))) {
+ pr_debug("%s: %s: CQE is already %s\n", mmc_hostname(host),
+ __func__, halt ? "halted" : "un-halted");
+ return 0;
+ }
+
+ if (host->cmdq_ops->halt) {
+ err = host->cmdq_ops->halt(host, halt);
+ if (!err && host->ops->notify_halt)
+ host->ops->notify_halt(host, halt);
+ if (!err && halt)
+ mmc_host_set_halt(host);
+ else if (!err && !halt) {
+ mmc_host_clr_halt(host);
+ wake_up(&host->cmdq_ctx.wait);
+ }
+ } else {
+ err = -ENOSYS;
+ }
+ return err;
+}
+EXPORT_SYMBOL(mmc_cmdq_halt);
+
+static void mmc_start_cmdq_request(struct mmc_host *host,
+ struct mmc_request *mrq)
+{
+ if (mrq->data) {
+ pr_debug("%s: blksz %d blocks %d flags %08x tsac %lu ms nsac %d\n",
+ mmc_hostname(host), mrq->data->blksz,
+ mrq->data->blocks, mrq->data->flags,
+ mrq->data->timeout_ns / NSEC_PER_MSEC,
+ mrq->data->timeout_clks);
+
+ BUG_ON(mrq->data->blksz > host->max_blk_size);
+ BUG_ON(mrq->data->blocks > host->max_blk_count);
+ BUG_ON(mrq->data->blocks * mrq->data->blksz >
+ host->max_req_size);
+ mrq->data->error = 0;
+ mrq->data->mrq = mrq;
+ }
+
+ if (mrq->cmd) {
+ mrq->cmd->error = 0;
+ mrq->cmd->mrq = mrq;
+ }
+
+ if (likely(host->cmdq_ops->request))
+ host->cmdq_ops->request(host, mrq);
+ else
+ pr_err("%s: %s: issue request failed\n", mmc_hostname(host),
+ __func__);
+}
+
+int mmc_cmdq_start_req(struct mmc_host *host, struct mmc_cmdq_req *cmdq_req)
+{
+ struct mmc_request *mrq = &cmdq_req->mrq;
+
+ mrq->host = host;
+ if (mmc_card_removed(host->card)) {
+ mrq->cmd->error = -ENOMEDIUM;
+ return -ENOMEDIUM;
+ }
+ mmc_start_cmdq_request(host, mrq);
+ return 0;
+}
+EXPORT_SYMBOL(mmc_cmdq_start_req);
+
+static void mmc_cmdq_dcmd_req_done(struct mmc_request *mrq)
+{
+ complete(&mrq->completion);
+}
+
+int mmc_cmdq_wait_for_dcmd(struct mmc_host *host,
+ struct mmc_cmdq_req *cmdq_req)
+{
+ struct mmc_request *mrq = &cmdq_req->mrq;
+ struct mmc_command *cmd = mrq->cmd;
+ int err = 0;
+
+ init_completion(&mrq->completion);
+ mrq->done = mmc_cmdq_dcmd_req_done;
+ err = mmc_cmdq_start_req(host, cmdq_req);
+ if (err)
+ return err;
+
+ wait_for_completion_io(&mrq->completion);
+ if (cmd->error) {
+ pr_err("%s: DCMD %d failed with err %d\n",
+ mmc_hostname(host), cmd->opcode,
+ cmd->error);
+ err = cmd->error;
+ if (host->cmdq_ops->dumpstate)
+ host->cmdq_ops->dumpstate(host);
+ }
+ return err;
+}
+EXPORT_SYMBOL(mmc_cmdq_wait_for_dcmd);
+
+int mmc_cmdq_prepare_flush(struct mmc_command *cmd)
+{
+ return __mmc_switch_cmdq_mode(cmd, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_FLUSH_CACHE, 1,
+ 0, true, true);
+}
+EXPORT_SYMBOL(mmc_cmdq_prepare_flush);
+
/**
* mmc_start_req - start a non-blocking request
* @host: MMC host to start command
@@ -1873,6 +2051,9 @@
void mmc_power_cycle(struct mmc_host *host, u32 ocr)
{
+ if(host->type == MMC_HOST_TYPE_MMC)
+ return;
+
mmc_power_off(host);
/* Wait at least 1 ms according to SD spec */
mmc_delay(1);
@@ -2149,6 +2330,125 @@
return mmc_mmc_erase_timeout(card, arg, qty);
}
+static u32 mmc_get_erase_qty(struct mmc_card *card, u32 from, u32 to)
+{
+ u32 qty = 0;
+ /*
+ * qty is used to calculate the erase timeout which depends on how many
+ * erase groups (or allocation units in SD terminology) are affected.
+ * We count erasing part of an erase group as one erase group.
+ * For SD, the allocation units are always a power of 2. For MMC, the
+ * erase group size is almost certainly also power of 2, but it does not
+ * seem to insist on that in the JEDEC standard, so we fall back to
+ * division in that case. SD may not specify an allocation unit size,
+ * in which case the timeout is based on the number of write blocks.
+ *
+ * Note that the timeout for secure trim 2 will only be correct if the
+ * number of erase groups specified is the same as the total of all
+ * preceding secure trim 1 commands. Since the power may have been
+ * lost since the secure trim 1 commands occurred, it is generally
+ * impossible to calculate the secure trim 2 timeout correctly.
+ */
+ if (card->erase_shift)
+ qty += ((to >> card->erase_shift) -
+ (from >> card->erase_shift)) + 1;
+ else if (mmc_card_sd(card))
+ qty += to - from + 1;
+ else
+ qty += ((to / card->erase_size) -
+ (from / card->erase_size)) + 1;
+ return qty;
+}
+
+static int mmc_cmdq_send_erase_cmd(struct mmc_cmdq_req *cmdq_req,
+ struct mmc_card *card, u32 opcode, u32 arg, u32 qty)
+{
+ struct mmc_command *cmd = cmdq_req->mrq.cmd;
+ int err;
+
+ memset(cmd, 0, sizeof(struct mmc_command));
+
+ cmd->opcode = opcode;
+ cmd->arg = arg;
+ if (cmd->opcode == MMC_ERASE) {
+ cmd->flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
+ cmd->busy_timeout = mmc_erase_timeout(card, arg, qty);
+ } else {
+ cmd->flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
+ }
+
+ err = mmc_cmdq_wait_for_dcmd(card->host, cmdq_req);
+ if (err) {
+ pr_err("mmc_erase: group start error %d, status %#x\n",
+ err, cmd->resp[0]);
+ return -EIO;
+ }
+ return 0;
+}
+
+static int mmc_cmdq_do_erase(struct mmc_cmdq_req *cmdq_req,
+ struct mmc_card *card, unsigned int from,
+ unsigned int to, unsigned int arg)
+{
+ struct mmc_command *cmd = cmdq_req->mrq.cmd;
+ unsigned int qty = 0;
+ unsigned long timeout;
+ int err;
+
+ mmc_retune_hold(card->host);
+
+ qty = mmc_get_erase_qty(card, from, to);
+
+ if (!mmc_card_blockaddr(card)) {
+ from <<= 9;
+ to <<= 9;
+ }
+
+ err = mmc_cmdq_send_erase_cmd(cmdq_req, card, MMC_ERASE_GROUP_START,
+ from, qty);
+ if (err)
+ goto out;
+
+ err = mmc_cmdq_send_erase_cmd(cmdq_req, card, MMC_ERASE_GROUP_END,
+ to, qty);
+ if (err)
+ goto out;
+
+ err = mmc_cmdq_send_erase_cmd(cmdq_req, card, MMC_ERASE,
+ arg, qty);
+ if (err)
+ goto out;
+
+ timeout = jiffies + msecs_to_jiffies(MMC_CORE_TIMEOUT_MS);
+ do {
+ memset(cmd, 0, sizeof(struct mmc_command));
+ cmd->opcode = MMC_SEND_STATUS;
+ cmd->arg = card->rca << 16;
+ cmd->flags = MMC_RSP_R1 | MMC_CMD_AC;
+ /* Do not retry else we can't see errors */
+ err = mmc_cmdq_wait_for_dcmd(card->host, cmdq_req);
+ if (err || (cmd->resp[0] & 0xFDF92000)) {
+ pr_err("error %d requesting status %#x\n",
+ err, cmd->resp[0]);
+ err = -EIO;
+ goto out;
+ }
+ /* Timeout if the device never becomes ready for data and
+ * never leaves the program state.
+ */
+ if (time_after(jiffies, timeout)) {
+ pr_err("%s: Card stuck in programming state! %s\n",
+ mmc_hostname(card->host), __func__);
+ err = -EIO;
+ goto out;
+ }
+ } while (!(cmd->resp[0] & R1_READY_FOR_DATA) ||
+ (R1_CURRENT_STATE(cmd->resp[0]) == R1_STATE_PRG));
+out:
+ mmc_retune_release(card->host);
+ return err;
+}
+
static int mmc_do_erase(struct mmc_card *card, unsigned int from,
unsigned int to, unsigned int arg)
{
@@ -2336,21 +2636,9 @@
return nr_new;
}
-/**
- * mmc_erase - erase sectors.
- * @card: card to erase
- * @from: first sector to erase
- * @nr: number of sectors to erase
- * @arg: erase command argument (SD supports only %MMC_ERASE_ARG)
- *
- * Caller must claim host before calling this function.
- */
-int mmc_erase(struct mmc_card *card, unsigned int from, unsigned int nr,
- unsigned int arg)
+static int mmc_erase_sanity_check(struct mmc_card *card, unsigned int from,
+ unsigned int nr, unsigned int arg)
{
- unsigned int rem, to = from + nr;
- int err;
-
if (!(card->host->caps & MMC_CAP_ERASE) ||
!(card->csd.cmdclass & CCC_ERASE))
return -EOPNOTSUPP;
@@ -2373,6 +2661,70 @@
if (from % card->erase_size || nr % card->erase_size)
return -EINVAL;
}
+ return 0;
+}
+
+int mmc_cmdq_erase(struct mmc_cmdq_req *cmdq_req,
+ struct mmc_card *card, unsigned int from, unsigned int nr,
+ unsigned int arg)
+{
+ unsigned int rem, to = from + nr;
+ int err;
+
+ err = mmc_erase_sanity_check(card, from, nr, arg);
+ if (err)
+ return err;
+
+ if (arg == MMC_ERASE_ARG)
+ nr = mmc_align_erase_size(card, &from, &to, nr);
+
+ if (nr == 0)
+ return 0;
+
+ if (to <= from)
+ return -EINVAL;
+
+ /* 'from' and 'to' are inclusive */
+ to -= 1;
+
+ /*
+ * Special case where only one erase-group fits in the timeout budget:
+ * If the region crosses an erase-group boundary on this particular
+ * case, we will be trimming more than one erase-group which, does not
+ * fit in the timeout budget of the controller, so we need to split it
+ * and call mmc_do_erase() twice if necessary. This special case is
+ * identified by the card->eg_boundary flag.
+ */
+ rem = card->erase_size - (from % card->erase_size);
+ if ((arg & MMC_TRIM_ARGS) && (card->eg_boundary) && (nr > rem)) {
+ err = mmc_cmdq_do_erase(cmdq_req, card, from, from + rem - 1, arg);
+ from += rem;
+ if ((err) || (to <= from))
+ return err;
+ }
+
+ return mmc_cmdq_do_erase(cmdq_req, card, from, to, arg);
+}
+EXPORT_SYMBOL(mmc_cmdq_erase);
+
+/**
+ * mmc_erase - erase sectors.
+ * @card: card to erase
+ * @from: first sector to erase
+ * @nr: number of sectors to erase
+ * @arg: erase command argument (SD supports only %MMC_ERASE_ARG)
+ *
+ * Caller must claim host before calling this function.
+ */
+int mmc_erase(struct mmc_card *card, unsigned int from, unsigned int nr,
+ unsigned int arg)
+{
+ unsigned int rem, to = from + nr;
+ int err;
+
+ err = mmc_erase_sanity_check(card, from, nr, arg);
+ if (err)
+ return err;
if (arg == MMC_ERASE_ARG)
nr = mmc_align_erase_size(card, &from, &to, nr);
@@ -2631,6 +2983,22 @@
return ret;
}
EXPORT_SYMBOL(mmc_hw_reset);
+/*
+ * mmc_cmdq_hw_reset: Helper API for doing
+ * reset_all of host and reinitializing card.
+ * This must be called with mmc_claim_host
+ * acquired by the caller.
+ */
+int mmc_cmdq_hw_reset(struct mmc_host *host)
+{
+ if (!host->bus_ops->power_restore)
+ return -EOPNOTSUPP;
+
+ mmc_power_cycle(host, host->ocr_avail);
+ mmc_select_voltage(host, host->card->ocr);
+ return host->bus_ops->power_restore(host);
+}
+EXPORT_SYMBOL(mmc_cmdq_hw_reset);
static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq)
{
@@ -2798,16 +3166,27 @@
mmc_bus_put(host);
mmc_claim_host(host);
+ host->card_status = MMC_CARD_UNINIT;
if (mmc_card_is_removable(host) && host->ops->get_cd &&
host->ops->get_cd(host) == 0) {
mmc_power_off(host);
+ if (host->ops->card_info_save)
+ host->ops->card_info_save(host);
mmc_release_host(host);
goto out;
}
for (i = 0; i < ARRAY_SIZE(freqs); i++) {
- if (!mmc_rescan_try_freq(host, max(freqs[i], host->f_min)))
+ if (!mmc_rescan_try_freq(host, max(freqs[i], host->f_min))) {
+ host->card_status = MMC_CARD_INIT;
+ if (host->ops->card_info_save)
+ host->ops->card_info_save(host);
break;
+ } else if ((i == (ARRAY_SIZE(freqs) - 1)) ||
+ (freqs[i] <= host->f_min)) {
+ host->card_status = MMC_CARD_INIT_FAIL;
+ }
+
if (freqs[i] <= host->f_min)
break;
}
diff -urN linux-4.9.37/drivers/mmc/core/mmc.c linux-4.9.y/drivers/mmc/core/mmc.c
--- linux-4.9.37/drivers/mmc/core/mmc.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/mmc/core/mmc.c 2021-06-07 13:01:33.000000000 +0300
@@ -528,6 +528,9 @@
card->ext_csd.man_bkops_en =
(ext_csd[EXT_CSD_BKOPS_EN] &
EXT_CSD_MANUAL_BKOPS_MASK);
+ card->ext_csd.auto_bkops_en =
+ (ext_csd[EXT_CSD_BKOPS_EN] &
+ EXT_CSD_AUTO_BKOPS_MASK) ? 1 : 0;
card->ext_csd.raw_bkops_status =
ext_csd[EXT_CSD_BKOPS_STATUS];
if (!card->ext_csd.man_bkops_en)
@@ -617,6 +620,21 @@
card->ext_csd.ffu_capable =
(ext_csd[EXT_CSD_SUPPORTED_MODE] & 0x1) &&
!(ext_csd[EXT_CSD_FW_CONFIG] & 0x1);
+ card->ext_csd.cmdq_support = ext_csd[EXT_CSD_CMDQ_SUPPORT];
+ if (card->ext_csd.cmdq_support) {
+ /*
+ * Queue Depth = N + 1,
+ * see JEDEC JESD84-B51 section 7.4.19
+ */
+ card->ext_csd.cmdq_depth =
+ ext_csd[EXT_CSD_CMDQ_DEPTH] + 1;
+ pr_info("%s: CMDQ supported: depth: %d\n",
+ mmc_hostname(card->host),
+ card->ext_csd.cmdq_depth);
+ }
+ } else {
+ card->ext_csd.cmdq_support = 0;
+ card->ext_csd.cmdq_depth = 0;
}
out:
return err;
@@ -1318,6 +1336,9 @@
/* Set host controller to HS400 timing and frequency */
mmc_set_timing(host, MMC_TIMING_MMC_HS400);
+#if defined(CONFIG_MMC_SDHCI_GOKE) || (defined(MODULE) && defined(CONFIG_MMC_SDHCI_GOKE_MODULE))
+ mmc_set_bus_speed(card);
+#endif
/* Controller enable enhanced strobe function */
host->ios.enhanced_strobe = true;
@@ -1466,6 +1487,41 @@
return mmc_execute_tuning(card);
}
+static int mmc_select_cmdq(struct mmc_card *card)
+{
+ struct mmc_host *host = card->host;
+ int ret = 0;
+
+ if (!host->cmdq_ops) {
+ pr_err("%s: host controller doesn't support CMDQ\n",
+ mmc_hostname(host));
+ return 0;
+ }
+
+ ret = mmc_set_blocklen(card, MMC_CARD_CMDQ_BLK_SIZE);
+ if (ret)
+ goto out;
+
+ ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_CMDQ, 1,
+ card->ext_csd.generic_cmd6_time);
+ if (ret)
+ goto out;
+
+ mmc_card_set_cmdq(card);
+ ret = host->cmdq_ops->enable(card->host);
+ if (ret) {
+ pr_err("%s: failed (%d) enabling CMDQ on host\n",
+ mmc_hostname(host), ret);
+ mmc_card_clr_cmdq(card);
+ ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_CMDQ, 0,
+ card->ext_csd.generic_cmd6_time);
+ goto out;
+ }
+
+ pr_info_once("%s: CMDQ enabled on card\n", mmc_hostname(host));
+out:
+ return ret;
+}
/*
* Handle the detection and initialisation of a card.
*
@@ -1690,7 +1746,7 @@
err = mmc_select_hs400(card);
if (err)
goto free_card;
- } else {
+ } else if (!mmc_card_hs400es(card)) {
/* Select the desired bus width optionally */
err = mmc_select_bus_width(card);
if (err > 0 && mmc_card_hs(card)) {
@@ -1773,6 +1829,18 @@
if (!oldcard)
host->card = card;
+ if (card->ext_csd.cmdq_support && (card->host->caps2 &
+ MMC_CAP2_CMD_QUEUE)) {
+ err = mmc_select_cmdq(card);
+ if (err) {
+ pr_err("%s: selecting CMDQ mode: failed: %d\n",
+ mmc_hostname(card->host), err);
+ card->ext_csd.cmdq_support = 0;
+ oldcard = card;
+ goto err;
+ }
+ }
+
return 0;
free_card:
@@ -1928,6 +1996,17 @@
if (mmc_card_suspended(host->card))
goto out;
+ if (host->card->cmdq_init) {
+ BUG_ON(host->cmdq_ctx.active_reqs);
+
+ err = mmc_cmdq_halt(host, true);
+ if (err) {
+ pr_err("%s: halt: failed: %d\n", __func__, err);
+ goto out;
+ }
+ host->cmdq_ops->disable(host, true);
+ }
+
if (mmc_card_doing_bkops(host->card)) {
err = mmc_stop_bkops(host->card);
if (err)
@@ -1951,6 +2030,10 @@
mmc_card_set_suspended(host->card);
}
out:
+ /* Kick CMDQ thread to process any requests came in while suspending */
+ if (host->card->cmdq_init)
+ wake_up(&host->cmdq_ctx.wait);
+
mmc_release_host(host);
return err;
}
@@ -2125,6 +2208,7 @@
if (err)
return err;
+ host->type = MMC_HOST_TYPE_MMC;
mmc_attach_bus(host, &mmc_ops);
if (host->ocr_avail_mmc)
host->ocr_avail = host->ocr_avail_mmc;
diff -urN linux-4.9.37/drivers/mmc/core/mmc_ops.c linux-4.9.y/drivers/mmc/core/mmc_ops.c
--- linux-4.9.37/drivers/mmc/core/mmc_ops.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/mmc/core/mmc_ops.c 2021-06-07 13:01:33.000000000 +0300
@@ -456,6 +456,45 @@
}
/**
+ * mmc_prepare_switch - helper; prepare to modify EXT_CSD register
+ * @card: the MMC card associated with the data transfer
+ * @set: cmd set values
+ * @index: EXT_CSD register index
+ * @value: value to program into EXT_CSD register
+ * @tout_ms: timeout (ms) for operation performed by register write,
+ * timeout of zero implies maximum possible timeout
+ * @use_busy_signal: use the busy signal as response type
+ *
+ * Helper to prepare to modify EXT_CSD register for selected card.
+ */
+
+static inline void mmc_prepare_switch(struct mmc_command *cmd, u8 index,
+ u8 value, u8 set, unsigned int tout_ms,
+ bool use_busy_signal)
+{
+ cmd->opcode = MMC_SWITCH;
+ cmd->arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
+ (index << 16) |
+ (value << 8) |
+ set;
+ cmd->flags = MMC_CMD_AC;
+ cmd->busy_timeout = tout_ms;
+ if (use_busy_signal)
+ cmd->flags |= MMC_RSP_SPI_R1B | MMC_RSP_R1B;
+ else
+ cmd->flags |= MMC_RSP_SPI_R1 | MMC_RSP_R1;
+}
+
+int __mmc_switch_cmdq_mode(struct mmc_command *cmd, u8 set, u8 index, u8 value,
+ unsigned int timeout_ms, bool use_busy_signal,
+ bool ignore_timeout)
+{
+ mmc_prepare_switch(cmd, index, value, set, timeout_ms, use_busy_signal);
+ return 0;
+}
+EXPORT_SYMBOL(__mmc_switch_cmdq_mode);
+
+/**
* __mmc_switch - modify EXT_CSD register
* @card: the MMC card associated with the data transfer
* @set: cmd set values
@@ -797,3 +836,21 @@
{
return (card && card->csd.mmca_vsn > CSD_SPEC_VER_3);
}
+
+int mmc_discard_queue(struct mmc_host *host, u32 tasks)
+{
+ struct mmc_command cmd = {0};
+
+ cmd.opcode = MMC_CMDQ_TASK_MGMT;
+ if (tasks) {
+ cmd.arg = DISCARD_TASK;
+ cmd.arg |= (tasks << 16);
+ } else {
+ cmd.arg = DISCARD_QUEUE;
+ }
+
+ cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
+
+ return mmc_wait_for_cmd(host, &cmd, 0);
+}
+EXPORT_SYMBOL(mmc_discard_queue);
diff -urN linux-4.9.37/drivers/mmc/core/mmc_ops.h linux-4.9.y/drivers/mmc/core/mmc_ops.h
--- linux-4.9.37/drivers/mmc/core/mmc_ops.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/mmc/core/mmc_ops.h 2021-06-07 13:01:33.000000000 +0300
@@ -27,6 +27,7 @@
int mmc_bus_test(struct mmc_card *card, u8 bus_width);
int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status);
int mmc_can_ext_csd(struct mmc_card *card);
+int mmc_discard_queue(struct mmc_host *host, u32 tasks);
int mmc_switch_status_error(struct mmc_host *host, u32 status);
int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
unsigned int timeout_ms, bool use_busy_signal, bool send_status,
diff -urN linux-4.9.37/drivers/mmc/core/sd.c linux-4.9.y/drivers/mmc/core/sd.c
--- linux-4.9.37/drivers/mmc/core/sd.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/mmc/core/sd.c 2021-06-07 13:01:33.000000000 +0300
@@ -1236,6 +1236,7 @@
if (err)
return err;
+ host->type = MMC_HOST_TYPE_SD;
mmc_attach_bus(host, &mmc_sd_ops);
if (host->ocr_avail_sd)
host->ocr_avail = host->ocr_avail_sd;
diff -urN linux-4.9.37/drivers/mmc/core/sdio.c linux-4.9.y/drivers/mmc/core/sdio.c
--- linux-4.9.37/drivers/mmc/core/sdio.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/mmc/core/sdio.c 2021-06-07 13:01:33.000000000 +0300
@@ -28,6 +28,10 @@
#include "sdio_ops.h"
#include "sdio_cis.h"
+#ifdef CONFIG_ARCH_GOKE
+#include "host.h"
+#endif
+
static int sdio_read_fbr(struct sdio_func *func)
{
int ret;
@@ -158,15 +162,19 @@
if (mmc_host_uhs(card->host)) {
if (data & SDIO_UHS_DDR50)
card->sw_caps.sd3_bus_mode
- |= SD_MODE_UHS_DDR50;
+ |= SD_MODE_UHS_DDR50 | SD_MODE_UHS_SDR50 |
+ SD_MODE_UHS_SDR25 | SD_MODE_UHS_SDR12;
if (data & SDIO_UHS_SDR50)
card->sw_caps.sd3_bus_mode
- |= SD_MODE_UHS_SDR50;
+ |= SD_MODE_UHS_SDR50 | SD_MODE_UHS_SDR25 |
+ SD_MODE_UHS_SDR12;
if (data & SDIO_UHS_SDR104)
card->sw_caps.sd3_bus_mode
- |= SD_MODE_UHS_SDR104;
+ |= SD_MODE_UHS_SDR104 | SD_MODE_UHS_DDR50 |
+ SD_MODE_UHS_SDR50 | SD_MODE_UHS_SDR25 |
+ SD_MODE_UHS_SDR12;
}
ret = mmc_io_rw_direct(card, 0, 0,
@@ -1070,6 +1078,7 @@
if (err)
return err;
+ host->type = MMC_HOST_TYPE_SDIO;
mmc_attach_bus(host, &mmc_sdio_ops);
if (host->ocr_avail_sdio)
host->ocr_avail = host->ocr_avail_sdio;
@@ -1173,3 +1182,40 @@
return err;
}
+#ifdef CONFIG_ARCH_GOKE
+/* sdio_reset_comm has been fixed in latest kernel/msm.git for Linux
+ * 2.6.27. The implementation prior to that buggy, and needs broadcom's
+ * patch for it*/
+int sdio_reset_comm(struct mmc_card *card)
+{
+ struct mmc_host *host = card->host;
+ u32 ocr;
+ u32 rocr;
+ int err;
+
+ mmc_claim_host(host);
+ mmc_retune_disable(host);
+ mmc_go_idle(host);
+ mmc_set_clock(host, host->f_min);
+ err = mmc_send_io_op_cond(host, 0, &ocr);
+ if (err)
+ goto err;
+ rocr = mmc_select_voltage(host, ocr);
+ if (!rocr) {
+ err = -EINVAL;
+ goto err;
+ }
+ err = mmc_sdio_init_card(host, rocr, card, 0);
+ if (err)
+ goto err;
+ mmc_release_host(host);
+ return 0;
+err:
+ printk("%s: Error resetting SDIO communications (%d)\n",
+ mmc_hostname(host), err);
+ mmc_release_host(host);
+ return err;
+}
+EXPORT_SYMBOL(sdio_reset_comm);
+#endif
+
diff -urN linux-4.9.37/drivers/mmc/host/Kconfig linux-4.9.y/drivers/mmc/host/Kconfig
--- linux-4.9.37/drivers/mmc/host/Kconfig 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/mmc/host/Kconfig 2021-06-07 13:01:33.000000000 +0300
@@ -176,6 +176,15 @@
If unsure, say N.
+config MMC_SDHCI_GOKE
+ tristate "SDHCI support on the Goke SoC"
+ depends on ARCH_GK7205V200 || ARCH_GK7205V300 || ARCH_GK7202V300 || ARCH_GK7605V100
+ depends on MMC_SDHCI_PLTFM
+ help
+ This selects the SDHCI support for Goke System-on-Chip devices.
+ If you have a controller with this interface, say Y or M here.
+ If unsure, say N.
+
config MMC_SDHCI_ESDHC_IMX
tristate "SDHCI support for the Freescale eSDHC/uSDHC i.MX controller"
depends on ARCH_MXC
@@ -798,3 +807,17 @@
Broadcom STB SoCs.
If unsure, say Y.
+
+config MMC_CQ_HCI
+ tristate "Command Queue Support"
+ depends on HAS_DMA
+ help
+ This selects the Command Queue Host Controller Interface (CQHCI)
+ support present in host controllers of Qualcomm Technologies, Inc
+ amongst others.
+ This controller supports eMMC devices with command queue support.
+
+ If you have a controller with this interface, say Y or M here.
+
+ If unsure, say N.
+
diff -urN linux-4.9.37/drivers/mmc/host/Makefile linux-4.9.y/drivers/mmc/host/Makefile
--- linux-4.9.37/drivers/mmc/host/Makefile 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/mmc/host/Makefile 2021-06-07 13:01:33.000000000 +0300
@@ -70,6 +70,12 @@
obj-$(CONFIG_MMC_SDHCI_OF_AT91) += sdhci-of-at91.o
obj-$(CONFIG_MMC_SDHCI_OF_ESDHC) += sdhci-of-esdhc.o
obj-$(CONFIG_MMC_SDHCI_OF_HLWD) += sdhci-of-hlwd.o
+obj-$(CONFIG_MMC_SDHCI_GOKE) += sdhci-proc.o
+obj-$(CONFIG_MMC_CQ_HCI) += sdhci-cmdq.o
+obj-$(CONFIG_ARCH_GK7205V200) += sdhci-gk7205v200.o
+obj-$(CONFIG_ARCH_GK7205V300) += sdhci-gk7205v300.o
+obj-$(CONFIG_ARCH_GK7202V300) += sdhci-gk7202v300.o
+obj-$(CONFIG_ARCH_GK7605V100) += sdhci-gk7605v100.o
obj-$(CONFIG_MMC_SDHCI_BCM_KONA) += sdhci-bcm-kona.o
obj-$(CONFIG_MMC_SDHCI_IPROC) += sdhci-iproc.o
obj-$(CONFIG_MMC_SDHCI_MSM) += sdhci-msm.o
diff -urN linux-4.9.37/drivers/mmc/host/sdhci.c linux-4.9.y/drivers/mmc/host/sdhci.c
--- linux-4.9.37/drivers/mmc/host/sdhci.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/mmc/host/sdhci.c 2021-06-07 13:01:33.000000000 +0300
@@ -32,6 +32,7 @@
#include <linux/mmc/slot-gpio.h>
#include "sdhci.h"
+#include "sdhci-cmdq.h"
#define DRIVER_NAME "sdhci"
@@ -76,8 +77,8 @@
pr_err(DRIVER_NAME ": Int enab: 0x%08x | Sig enab: 0x%08x\n",
sdhci_readl(host, SDHCI_INT_ENABLE),
sdhci_readl(host, SDHCI_SIGNAL_ENABLE));
- pr_err(DRIVER_NAME ": AC12 err: 0x%08x | Slot int: 0x%08x\n",
- sdhci_readw(host, SDHCI_ACMD12_ERR),
+ pr_err(DRIVER_NAME ": ACMD err: 0x%08x | Slot int: 0x%08x\n",
+ sdhci_readw(host, SDHCI_AUTO_CMD_ERR),
sdhci_readw(host, SDHCI_SLOT_INT_STATUS));
pr_err(DRIVER_NAME ": Caps: 0x%08x | Caps_1: 0x%08x\n",
sdhci_readl(host, SDHCI_CAPABILITIES),
@@ -227,7 +228,7 @@
SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT |
SDHCI_INT_INDEX | SDHCI_INT_END_BIT | SDHCI_INT_CRC |
SDHCI_INT_TIMEOUT | SDHCI_INT_DATA_END |
- SDHCI_INT_RESPONSE;
+ SDHCI_INT_RESPONSE | SDHCI_INT_ACMD_ERR;
if (host->tuning_mode == SDHCI_TUNING_MODE_2 ||
host->tuning_mode == SDHCI_TUNING_MODE_3)
@@ -240,11 +241,17 @@
/* force clock reconfiguration */
host->clock = 0;
mmc->ops->set_ios(mmc, &mmc->ios);
+ } else {
+ if (host->ops->extra_init)
+ host->ops->extra_init(host);
}
}
static void sdhci_reinit(struct sdhci_host *host)
{
+ if (host->ops->pre_init)
+ host->ops->pre_init(host);
+
sdhci_init(host, 0);
sdhci_enable_card_detection(host);
}
@@ -522,6 +529,60 @@
dma_desc->addr_hi = cpu_to_le32((u64)addr >> 32);
}
+static void sdhci_write_cmd_table(u8 *desc, u32 reg, u32 attr)
+{
+ __le32 *reg_addr = (__le32 __force *)(desc + 4);
+ __le32 *attr_addr = (__le32 __force *)desc;
+
+ attr_addr[0] = cpu_to_le32(attr);
+ reg_addr[0] = cpu_to_le32(reg);
+}
+
+static void sdhci_write_adma3_desc(struct sdhci_host *host, u8 *desc,
+ dma_addr_t addr, unsigned int attr)
+{
+ __le32 *attr_addr = (__le32 __force *)desc;
+
+ attr_addr[0] = cpu_to_le32(attr);
+
+ if (host->flags & SDHCI_USE_64_BIT_DMA) {
+ __le64 *cmd_ddr = (__le64 __force *)(desc + 4);
+ cmd_ddr[0] = cpu_to_le64(addr);
+ } else {
+ __le32 *cmd_ddr = (__le32 __force *)(desc + 4);
+ cmd_ddr[0] = cpu_to_le32(addr);
+ }
+}
+
+static void sdhci_prep_adma3_desc(struct sdhci_host *host,
+ struct mmc_command *cmd, int flags)
+{
+ struct mmc_data *data = cmd->data;
+ unsigned int ctrl_2, cmd_xfer, blksz;
+ u16 mode;
+
+ blksz = SDHCI_MAKE_BLKSZ(0, data->blksz);
+ mode = sdhci_readw(host, SDHCI_TRANSFER_MODE);
+ cmd_xfer = (SDHCI_MAKE_CMD(cmd->opcode, flags) << 16) | mode;
+
+ sdhci_write_cmd_table(host->cmd_table, data->blocks, ADMA3_CMD_VALID);
+ sdhci_write_cmd_table(host->cmd_table + 0x8, blksz, ADMA3_CMD_VALID);
+ sdhci_write_cmd_table(host->cmd_table + 0x10,
+ cmd->arg, ADMA3_CMD_VALID);
+ sdhci_write_cmd_table(host->cmd_table + 0x18,
+ cmd_xfer, ADMA3_CMD_VALID);
+ sdhci_adma_write_desc(host, host->cmd_table + 0x20,
+ host->adma_addr, 0x0, ADMA2_LINK_VALID);
+ sdhci_write_adma3_desc(host, host->adma3_table,
+ host->cmd_addr, ADMA3_END);
+
+ ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+ ctrl_2 |= SDHCI_CTRL_HOST_VER4_ENABLE;
+ if (host->flags & SDHCI_USE_64_BIT_DMA)
+ ctrl_2 |= SDHCI_CTRL_ADDRESSING_64BIT;
+ sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
+}
+
static void sdhci_adma_mark_end(void *desc)
{
struct sdhci_adma2_64_desc *dma_desc = desc;
@@ -589,6 +650,17 @@
BUG_ON(len > 65536);
if (len) {
+ /* work around for buffer across 128M boundary, split the buffer */
+ if (((addr & (SDHCI_DMA_BOUNDARY_SIZE - 1)) + len) >
+ SDHCI_DMA_BOUNDARY_SIZE) {
+ offset = SDHCI_DMA_BOUNDARY_SIZE -
+ (addr & (SDHCI_DMA_BOUNDARY_SIZE - 1));
+ sdhci_adma_write_desc(host, desc, addr, offset,
+ ADMA2_TRAN_VALID);
+ desc += host->desc_sz;
+ addr += offset;
+ len -= offset;
+ }
/* tran, valid */
sdhci_adma_write_desc(host, desc, addr, len,
ADMA2_TRAN_VALID);
@@ -855,10 +927,14 @@
ctrl &= ~SDHCI_CTRL_DMA_MASK;
if ((host->flags & SDHCI_REQ_USE_DMA) &&
(host->flags & SDHCI_USE_ADMA)) {
- if (host->flags & SDHCI_USE_64_BIT_DMA)
- ctrl |= SDHCI_CTRL_ADMA64;
- else
- ctrl |= SDHCI_CTRL_ADMA32;
+ if (host->flags & SDHCI_USE_ADMA3) {
+ ctrl |= SDHCI_CTRL_ADMA3;
+ } else {
+ if (host->flags & SDHCI_USE_64_BIT_DMA)
+ ctrl |= SDHCI_CTRL_ADMA64;
+ else
+ ctrl |= SDHCI_CTRL_ADMA32;
+ }
} else {
ctrl |= SDHCI_CTRL_SDMA;
}
@@ -1121,7 +1197,8 @@
sdhci_prepare_data(host, cmd);
- sdhci_writel(host, cmd->arg, SDHCI_ARGUMENT);
+ if (!(host->flags & SDHCI_USE_ADMA3) || !cmd->data)
+ sdhci_writel(host, cmd->arg, SDHCI_ARGUMENT);
sdhci_set_transfer_mode(host, cmd);
@@ -1152,10 +1229,29 @@
cmd->opcode == MMC_SEND_TUNING_BLOCK_HS200)
flags |= SDHCI_CMD_DATA;
- sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND);
+ if (host->flags & SDHCI_USE_ADMA3 && cmd->data) {
+ sdhci_prep_adma3_desc(host, cmd, flags);
+
+ sdhci_writel(host, (u32)host->adma3_addr,
+ SDHCI_ADMA3_ID_ADDR_LOW);
+ if (host->flags & SDHCI_USE_64_BIT_DMA)
+ sdhci_writel(host, (u32)((u64)host->adma3_addr >> 32),
+ SDHCI_ADMA3_ID_ADDR_HI);
+ } else {
+ sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags),
+ SDHCI_COMMAND);
+ }
}
EXPORT_SYMBOL_GPL(sdhci_send_command);
+#define CMD_ERRORS \
+ (R1_OUT_OF_RANGE | /* Command argument out of range */ \
+ R1_ADDRESS_ERROR | /* Misaligned address */ \
+ R1_BLOCK_LEN_ERROR | /* Transferred block length incorrect */\
+ R1_WP_VIOLATION | /* Tried to write to protected block */ \
+ R1_CC_ERROR | /* Card controller error */ \
+ R1_ERROR) /* General/unknown error */
+
static void sdhci_finish_command(struct sdhci_host *host)
{
struct mmc_command *cmd = host->cmd;
@@ -1177,6 +1273,15 @@
} else {
cmd->resp[0] = sdhci_readl(host, SDHCI_RESPONSE);
}
+
+ if (((cmd->flags & MMC_RSP_R1) == MMC_RSP_R1) &&
+ ((cmd->flags & MMC_CMD_MASK) != MMC_CMD_BCR)) {
+ if ((cmd->resp[0] & CMD_ERRORS) && !host->is_tuning) {
+ host->error_count++;
+ cmd->mrq->cmd->error = -EACCES;
+ pr_err("The status of the card is abnormal, cmd->resp[0]: %x", cmd->resp[0]);
+ }
+ }
}
if (cmd->mrq->cap_cmd_during_tfr && cmd == cmd->mrq->cmd)
@@ -1430,6 +1535,12 @@
sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
if (host->quirks2 & SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON)
sdhci_runtime_pm_bus_off(host);
+ /*
+ * Controllers need an extra 100ms delay to ensure power off
+ * completely
+ */
+ msleep(100);
+
} else {
/*
* Spec says that we should clear the power reg before setting
@@ -1568,13 +1679,9 @@
static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
{
struct sdhci_host *host = mmc_priv(mmc);
- unsigned long flags;
u8 ctrl;
- spin_lock_irqsave(&host->lock, flags);
-
if (host->flags & SDHCI_DEVICE_DEAD) {
- spin_unlock_irqrestore(&host->lock, flags);
if (!IS_ERR(mmc->supply.vmmc) &&
ios->power_mode == MMC_POWER_OFF)
mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0);
@@ -1710,7 +1817,9 @@
}
/* Re-enable SD Clock */
- host->ops->set_clock(host, host->clock);
+ clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+ clk |= SDHCI_CLOCK_CARD_EN;
+ sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
} else
sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
@@ -1723,7 +1832,6 @@
sdhci_do_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
mmiowb();
- spin_unlock_irqrestore(&host->lock, flags);
}
static int sdhci_get_cd(struct mmc_host *mmc)
@@ -1846,6 +1954,9 @@
u16 ctrl;
int ret;
+ if (host->ops->start_signal_voltage_switch)
+ return host->ops->start_signal_voltage_switch(host, ios);
+
/*
* Signal Voltage Switching is only applicable for Host Controllers
* v3.00 and above.
@@ -2281,6 +2392,33 @@
spin_unlock_irqrestore(&host->lock, flags);
}
+static int sdhci_card_info_save(struct mmc_host *mmc)
+{
+ struct mmc_card *card = mmc->card;
+ struct sdhci_host *host= mmc_priv(mmc);
+ struct card_info *c_info = &host->c_info;
+
+ if (!card) {
+ memset(c_info,0,sizeof(struct card_info));
+ c_info->card_connect = CARD_DISCONNECT;
+ goto out;
+ }
+
+ c_info->card_type = card->type;
+ c_info->card_state = card->state;
+
+ c_info->timing = mmc->ios.timing;
+ c_info->card_support_clock = mmc->ios.clock;
+
+ c_info->sd_bus_speed = card->sd_bus_speed;
+
+ memcpy(c_info->ssr, card->raw_ssr, ARRAY_SIZE(c_info->ssr));
+
+ c_info->card_connect = CARD_CONNECT;
+out:
+ return 0;
+}
+
static const struct mmc_host_ops sdhci_ops = {
.request = sdhci_request,
.post_req = sdhci_post_req,
@@ -2296,6 +2434,7 @@
.select_drive_strength = sdhci_select_drive_strength,
.card_event = sdhci_card_event,
.card_busy = sdhci_card_busy,
+ .card_info_save = sdhci_card_info_save,
};
/*****************************************************************************\
@@ -2370,6 +2509,9 @@
host->pending_reset = false;
}
+ if (mrq->data && mrq->data->error && !host->is_tuning)
+ host->error_count++;
+
if (!sdhci_has_requests(host))
sdhci_led_deactivate(host);
@@ -2460,17 +2602,32 @@
*/
if (host->pending_reset)
return;
- pr_err("%s: Got command interrupt 0x%08x even though no command operation was in progress.\n",
+
+ /*pr_err("%s: Got command interrupt 0x%08x even though no command operation was in progress.\n",
mmc_hostname(host->mmc), (unsigned)intmask);
- sdhci_dumpregs(host);
+ sdhci_dumpregs(host);*/
+
return;
}
if (intmask & (SDHCI_INT_TIMEOUT | SDHCI_INT_CRC |
- SDHCI_INT_END_BIT | SDHCI_INT_INDEX)) {
+ SDHCI_INT_END_BIT | SDHCI_INT_INDEX |
+ SDHCI_INT_ACMD_ERR)) {
if (intmask & SDHCI_INT_TIMEOUT)
host->cmd->error = -ETIMEDOUT;
- else
+ else if (intmask & SDHCI_INT_ACMD_ERR) {
+ u16 acmd_stat = sdhci_readw(host, SDHCI_AUTO_CMD_ERR);
+
+ if (acmd_stat & (SDHCI_AUTO_CMD12_NOT_EXEC |
+ SDHCI_AUTO_CMD_INDEX_ERR |
+ SDHCI_AUTO_CMD12_NOT_ISSUED))
+ host->cmd->error = -EIO;
+ else if (acmd_stat & SDHCI_AUTO_CMD_TIMEOUT_ERR)
+ host->cmd->error = -ETIMEDOUT;
+ else
+ host->cmd->error = -EILSEQ;
+
+ } else
host->cmd->error = -EILSEQ;
/*
@@ -2533,6 +2690,8 @@
static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
{
+
+#ifndef SDHCI_GOKE_EDGE_TUNING
u32 command;
/* CMD19 generates _only_ Buffer Read Ready interrupt */
@@ -2545,6 +2704,7 @@
return;
}
}
+#endif
if (!host->data) {
struct mmc_command *data_cmd = host->data_cmd;
@@ -2584,6 +2744,9 @@
if (host->pending_reset)
return;
+ if (host->is_tuning)
+ return;
+
pr_err("%s: Got data interrupt 0x%08x even though no data operation was in progress.\n",
mmc_hostname(host->mmc), (unsigned)intmask);
sdhci_dumpregs(host);
@@ -2655,6 +2818,58 @@
}
}
+#ifdef CONFIG_MMC_CQ_HCI
+static int sdhci_get_cmd_err(u32 intmask)
+{
+ if (intmask & SDHCI_INT_TIMEOUT)
+ return -ETIMEDOUT;
+ else if (intmask & (SDHCI_INT_CRC | SDHCI_INT_END_BIT |
+ SDHCI_INT_INDEX))
+ return -EILSEQ;
+ return 0;
+}
+
+static int sdhci_get_data_err(u32 intmask)
+{
+ if (intmask & SDHCI_INT_DATA_TIMEOUT)
+ return -ETIMEDOUT;
+ else if (intmask & (SDHCI_INT_DATA_END_BIT | SDHCI_INT_DATA_CRC))
+ return -EILSEQ;
+ else if (intmask & SDHCI_INT_ADMA_ERROR)
+ return -EIO;
+ return 0;
+}
+
+static irqreturn_t sdhci_cmdq_irq(struct sdhci_host *host, u32 intmask)
+{
+ int err = 0;
+ u32 mask = 0;
+ irqreturn_t ret;
+
+ if (intmask & SDHCI_INT_CMD_MASK)
+ err = sdhci_get_cmd_err(intmask);
+ else if (intmask & SDHCI_INT_DATA_MASK)
+ err = sdhci_get_data_err(intmask);
+
+ ret = cmdq_irq(host->mmc, err);
+ if (err) {
+ /* Clear the error interrupts */
+ mask = intmask & SDHCI_INT_ERROR_MASK;
+ sdhci_writel(host, mask, SDHCI_INT_STATUS);
+ }
+ return ret;
+
+}
+
+#else
+static irqreturn_t sdhci_cmdq_irq(struct sdhci_host *host, u32 intmask)
+{
+ pr_err("%s: Received cmdq-irq when disabled !!!!\n",
+ mmc_hostname(host->mmc));
+ return IRQ_NONE;
+}
+#endif
+
static irqreturn_t sdhci_irq(int irq, void *dev_id)
{
irqreturn_t result = IRQ_NONE;
@@ -2676,6 +2891,19 @@
}
do {
+ if (host->mmc->card && mmc_card_cmdq(host->mmc->card) &&
+ !mmc_host_halt(host->mmc) && !mmc_host_cq_disable(host->mmc)) {
+ DBG("*** %s: cmdq intr: 0x%08x\n",
+ mmc_hostname(host->mmc),
+ intmask);
+ result = sdhci_cmdq_irq(host, intmask);
+ if (result == IRQ_HANDLED) {
+ mask = intmask & SDHCI_INT_CQE;
+ sdhci_writel(host, mask, SDHCI_INT_STATUS);
+ goto out;
+ }
+ }
+
/* Clear selected interrupts. */
mask = intmask & (SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK |
SDHCI_INT_BUS_POWER);
@@ -3093,7 +3321,7 @@
override_timeout_clk = host->timeout_clk;
- if (host->version > SDHCI_SPEC_300) {
+ if (host->version > SDHCI_SPEC_420) {
pr_err("%s: Unknown controller version (%d). You may experience problems.\n",
mmc_hostname(mmc), host->version);
}
@@ -3121,6 +3349,15 @@
host->flags &= ~SDHCI_USE_ADMA;
}
+ if ((host->version >= SDHCI_SPEC_400) &&
+ (host->caps1 & SDHCI_CAN_DO_ADMA3))
+ host->flags |= SDHCI_USE_ADMA3 | SDHCI_HOST_VER4_ENABLE;
+
+ if ((host->quirks2 & SDHCI_QUIRK2_BROKEN_ADMA3) &&
+ (host->flags & SDHCI_USE_ADMA3)) {
+ DBG("Disabling ADMA3 as it is marked broken\n");
+ host->flags &= ~(SDHCI_USE_ADMA3 | SDHCI_HOST_VER4_ENABLE);
+ }
/*
* It is assumed that a 64-bit capable device has set a 64-bit DMA mask
* and *must* do 64-bit DMA. A driver has the opportunity to change
@@ -3161,14 +3398,14 @@
* all multipled by the descriptor size.
*/
if (host->flags & SDHCI_USE_64_BIT_DMA) {
- host->adma_table_sz = (SDHCI_MAX_SEGS * 2 + 1) *
- SDHCI_ADMA2_64_DESC_SZ;
- host->desc_sz = SDHCI_ADMA2_64_DESC_SZ;
- } else {
- host->adma_table_sz = (SDHCI_MAX_SEGS * 2 + 1) *
- SDHCI_ADMA2_32_DESC_SZ;
+ if (host->flags & SDHCI_HOST_VER4_ENABLE)
+ host->desc_sz = 16;
+ else
+ host->desc_sz = SDHCI_ADMA2_64_DESC_SZ;
+ } else
host->desc_sz = SDHCI_ADMA2_32_DESC_SZ;
- }
+
+ host->adma_table_sz = (SDHCI_MAX_SEGS * 2 + 1) * host->desc_sz;
host->align_buffer_sz = SDHCI_MAX_SEGS * SDHCI_ADMA2_ALIGN;
buf = dma_alloc_coherent(mmc_dev(mmc), host->align_buffer_sz +
@@ -3191,6 +3428,36 @@
host->adma_table = buf + host->align_buffer_sz;
host->adma_addr = dma + host->align_buffer_sz;
}
+
+ if (!(host->flags & SDHCI_USE_ADMA))
+ host->flags &= ~SDHCI_USE_ADMA3;
+
+ if (host->flags & SDHCI_USE_ADMA3) {
+#define MAX_CMD_NUM 32
+#define SDHCI_CMD_DESC_SZ 16
+ if (host->flags & SDHCI_USE_64_BIT_DMA)
+ host->adma3_desc_sz = SDHCI_ADMA3_64_DESC_SZ;
+ else
+ host->adma3_desc_sz = SDHCI_ADMA3_32_DESC_SZ;
+
+ host->adma3_table_sz = MAX_CMD_NUM * host->adma3_desc_sz;
+ host->cmd_table_sz = MAX_CMD_NUM *
+ (SDHCI_CMD_DESC_SZ + 16);
+ buf = dma_alloc_coherent(mmc_dev(mmc), host->adma3_table_sz +
+ host->cmd_table_sz, &dma, GFP_KERNEL);
+ if (!buf) {
+ pr_warn("%s: Unable to allocate ADMA3 buffers - falling back to standard DMA\n",
+ mmc_hostname(mmc));
+ host->flags &= ~SDHCI_USE_ADMA3;
+ } else {
+ host->adma3_table = buf;
+ host->adma3_addr = dma;
+
+ host->cmd_table = buf + host->adma3_desc_sz;
+ host->cmd_addr = dma + host->adma3_desc_sz;
+ }
+ }
+
}
/*
@@ -3557,10 +3824,165 @@
host->adma_table = NULL;
host->align_buffer = NULL;
+ if (host->adma3_table)
+ dma_free_coherent(mmc_dev(mmc), host->adma3_table_sz +
+ host->cmd_table_sz, host->adma3_table,
+ host->adma3_addr);
+
+ host->adma3_table = NULL;
+ host->cmd_table = NULL;
+
return ret;
}
EXPORT_SYMBOL_GPL(sdhci_setup_host);
+#ifdef CONFIG_MMC_CQ_HCI
+static void sdhci_cmdq_set_transfer_params(struct mmc_host *mmc)
+{
+ struct sdhci_host *host = mmc_priv(mmc);
+ u8 ctrl;
+ u16 mode, ctrl2;
+
+ if (host->version >= SDHCI_SPEC_200) {
+
+ ctrl2 = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+ ctrl2 |= SDHCI_CLOCK_PLL_EN;
+ sdhci_writew(host, ctrl2, SDHCI_CLOCK_CONTROL);
+
+ ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+ ctrl2 |= SDHCI_CTRL_ADDRESSING_64BIT;
+ ctrl2 |= SDHCI_CTRL_HOST_VER4_ENABLE;
+ sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2);
+
+ ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
+ ctrl &= ~SDHCI_CTRL_DMA_MASK;
+ if (host->flags & SDHCI_USE_64_BIT_DMA)
+ ctrl |= SDHCI_CTRL_ADMA64;
+ else
+ ctrl |= SDHCI_CTRL_ADMA32;
+ sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
+
+ mode = sdhci_readw(host, SDHCI_TRANSFER_MODE);
+ sdhci_writew(host, mode | SDHCI_TRNS_MULTI, SDHCI_TRANSFER_MODE);
+ }
+}
+
+static void sdhci_cmdq_clear_set_irqs(struct mmc_host *mmc, bool clear)
+{
+ struct sdhci_host *host = mmc_priv(mmc);
+ u32 ier = 0;
+
+ ier &= ~SDHCI_INT_ALL_MASK;
+
+ if (clear) {
+ ier = SDHCI_INT_CQE | SDHCI_INT_ERROR_MASK;
+ sdhci_writel(host, ier, SDHCI_INT_ENABLE);
+ sdhci_writel(host, ier, SDHCI_SIGNAL_ENABLE);
+ } else {
+ ier = SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT |
+ SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT |
+ SDHCI_INT_INDEX | SDHCI_INT_END_BIT |
+ SDHCI_INT_CRC | SDHCI_INT_TIMEOUT |
+ SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE |
+ SDHCI_INT_ACMD_ERR;
+ sdhci_writel(host, ier, SDHCI_INT_ENABLE);
+ sdhci_writel(host, ier, SDHCI_SIGNAL_ENABLE);
+ }
+}
+
+static void sdhci_cmdq_set_data_timeout(struct mmc_host *mmc, u32 val)
+{
+ struct sdhci_host *host = mmc_priv(mmc);
+
+ val = 0xe;
+ sdhci_writeb(host, val, SDHCI_TIMEOUT_CONTROL);
+}
+
+static void sdhci_cmdq_dump_goke_regs(struct mmc_host *mmc)
+{
+ struct sdhci_host *host = mmc_priv(mmc);
+
+ sdhci_dumpregs(host);
+}
+
+static int sdhci_cmdq_init(struct sdhci_host *host, struct mmc_host *mmc,
+ bool dma64)
+{
+ struct cmdq_host *cq_host;
+
+ cq_host = kzalloc(sizeof(*cq_host), GFP_KERNEL);
+ if (!cq_host) {
+ pr_err("failed to allocate memory for CMDQ\n");
+ host->cq_host = NULL;
+ return -ENOMEM;
+ } else {
+ cq_host->mmio = host->ioaddr + 0x180;
+ host->cq_host = cq_host;
+ }
+
+ return cmdq_init(host->cq_host, mmc, dma64);
+}
+
+static void sdhci_cmdq_set_block_size(struct mmc_host *mmc)
+{
+ struct sdhci_host *host = mmc_priv(mmc);
+
+ sdhci_writew(host, SDHCI_MAKE_BLKSZ(0, 512), SDHCI_BLOCK_SIZE);
+}
+
+static void sdhci_cmdq_post_cqe_halt(struct mmc_host *mmc)
+{
+ struct sdhci_host *host = mmc_priv(mmc);
+
+ sdhci_writel(host, sdhci_readl(host, SDHCI_INT_ENABLE) |
+ SDHCI_INT_RESPONSE, SDHCI_INT_ENABLE);
+ sdhci_writel(host, SDHCI_INT_RESPONSE, SDHCI_INT_STATUS);
+}
+#else
+static void sdhci_cmdq_set_transfer_params(struct mmc_host *mmc)
+{
+
+}
+static void sdhci_cmdq_clear_set_irqs(struct mmc_host *mmc, bool clear)
+{
+
+}
+
+static void sdhci_cmdq_set_data_timeout(struct mmc_host *mmc, u32 val)
+{
+
+}
+
+static void sdhci_cmdq_dump_goke_regs(struct mmc_host *mmc)
+{
+
+}
+
+static int sdhci_cmdq_init(struct sdhci_host *host, struct mmc_host *mmc,
+ bool dma64)
+{
+ return -ENOSYS;
+}
+
+static void sdhci_cmdq_set_block_size(struct mmc_host *mmc)
+{
+
+}
+
+static void sdhci_cmdq_post_cqe_halt(struct mmc_host *mmc)
+{
+}
+#endif
+
+static const struct cmdq_host_ops sdhci_cmdq_ops = {
+ .clear_set_irqs = sdhci_cmdq_clear_set_irqs,
+ .set_data_timeout = sdhci_cmdq_set_data_timeout,
+ .dump_goke_regs = sdhci_cmdq_dump_goke_regs,
+ .set_block_size = sdhci_cmdq_set_block_size,
+ .post_cqe_halt = sdhci_cmdq_post_cqe_halt,
+ .set_transfer_params = sdhci_cmdq_set_transfer_params,
+};
+
int __sdhci_add_host(struct sdhci_host *host)
{
struct mmc_host *mmc = host->mmc;
@@ -3605,11 +4027,25 @@
if (ret)
goto unled;
- pr_info("%s: SDHCI controller on %s [%s] using %s\n",
+ if (mmc->caps2 & MMC_CAP2_CMD_QUEUE) {
+ bool dma64 = (host->flags & SDHCI_USE_64_BIT_DMA) ?
+ true : false;
+ ret = sdhci_cmdq_init(host, mmc, dma64);
+ if (ret)
+ pr_err("%s: CMDQ init: failed (%d)\n",
+ mmc_hostname(host->mmc), ret);
+ else
+ host->cq_host->ops = &sdhci_cmdq_ops;
+ }
+
+ pr_info("%s: SDHCI controller on %s [%s] using %s in %s mode\n",
mmc_hostname(mmc), host->hw_name, dev_name(mmc_dev(mmc)),
+ (host->flags & SDHCI_USE_ADMA3) ? "ADMA3" :
(host->flags & SDHCI_USE_ADMA) ?
(host->flags & SDHCI_USE_64_BIT_DMA) ? "ADMA 64-bit" : "ADMA" :
- (host->flags & SDHCI_USE_SDMA) ? "DMA" : "PIO");
+ ((host->flags & SDHCI_USE_SDMA) ? "DMA" : "PIO"),
+ ((mmc->caps2 & MMC_CAP2_CMD_QUEUE) && !ret) ?
+ "CMDQ" : "legacy");
sdhci_enable_card_detection(host);
@@ -3635,6 +4071,14 @@
host->adma_table = NULL;
host->align_buffer = NULL;
+ if (host->adma3_table)
+ dma_free_coherent(mmc_dev(mmc), host->adma3_table_sz +
+ host->cmd_table_sz, host->adma3_table,
+ host->adma3_addr);
+
+ host->adma3_table = NULL;
+ host->cmd_table = NULL;
+
return ret;
}
EXPORT_SYMBOL_GPL(__sdhci_add_host);
@@ -3672,6 +4116,8 @@
sdhci_disable_card_detection(host);
+ free_irq(host->irq, host);
+
mmc_remove_host(mmc);
sdhci_led_unregister(host);
@@ -3681,7 +4127,6 @@
sdhci_writel(host, 0, SDHCI_INT_ENABLE);
sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE);
- free_irq(host->irq, host);
del_timer_sync(&host->timer);
del_timer_sync(&host->data_timer);
@@ -3698,6 +4143,14 @@
host->adma_table = NULL;
host->align_buffer = NULL;
+
+ if (host->adma3_table)
+ dma_free_coherent(mmc_dev(mmc), host->adma3_table_sz +
+ host->cmd_table_sz, host->adma3_table,
+ host->adma3_addr);
+
+ host->adma3_table = NULL;
+ host->cmd_table = NULL;
}
EXPORT_SYMBOL_GPL(sdhci_remove_host);
diff -urN linux-4.9.37/drivers/mmc/host/sdhci-cmdq.c linux-4.9.y/drivers/mmc/host/sdhci-cmdq.c
--- linux-4.9.37/drivers/mmc/host/sdhci-cmdq.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/mmc/host/sdhci-cmdq.c 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,1108 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#include <linux/delay.h>
+#include <linux/highmem.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/scatterlist.h>
+#include <linux/platform_device.h>
+#include <linux/blkdev.h>
+
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
+#include <linux/pm_runtime.h>
+//#include <linux/mmc/sdhci.h>
+#include <linux/workqueue.h>
+
+#include "sdhci-cmdq.h"
+#include "sdhci.h"
+
+#define DCMD_SLOT 31
+#define NUM_SLOTS 32
+
+/* 1 sec */
+#define HALT_TIMEOUT_MS 1000
+
+static int cmdq_halt_poll(struct mmc_host *mmc, bool halt);
+static int cmdq_halt(struct mmc_host *mmc, bool halt);
+
+#ifdef CONFIG_PM_RUNTIME
+static int cmdq_runtime_pm_get(struct cmdq_host *host)
+{
+ return pm_runtime_get_sync(host->mmc->parent);
+}
+static int cmdq_runtime_pm_put(struct cmdq_host *host)
+{
+ pm_runtime_mark_last_busy(host->mmc->parent);
+ return pm_runtime_put_autosuspend(host->mmc->parent);
+}
+#else
+static inline int cmdq_runtime_pm_get(struct cmdq_host *host)
+{
+ return 0;
+}
+static inline int cmdq_runtime_pm_put(struct cmdq_host *host)
+{
+ return 0;
+}
+#endif
+static inline struct mmc_request *get_req_by_tag(struct cmdq_host *cq_host,
+ unsigned int tag)
+{
+ return cq_host->mrq_slot[tag];
+}
+
+static inline u8 *get_desc(struct cmdq_host *cq_host, u8 tag)
+{
+ return cq_host->desc_base + (tag * cq_host->slot_sz);
+}
+
+static inline u8 *get_link_desc(struct cmdq_host *cq_host, u8 tag)
+{
+ u8 *desc = get_desc(cq_host, tag);
+
+ return desc + cq_host->task_desc_len;
+}
+
+static inline dma_addr_t get_trans_desc_dma(struct cmdq_host *cq_host, u8 tag)
+{
+ return cq_host->trans_desc_dma_base +
+ (cq_host->slot_desc_sz * tag);
+}
+
+static inline u8 *get_trans_desc(struct cmdq_host *cq_host, u8 tag)
+{
+ return cq_host->trans_desc_base +
+ (cq_host->slot_desc_sz * tag);
+}
+
+static void setup_trans_desc(struct cmdq_host *cq_host, u8 tag)
+{
+ u8 *link_temp;
+ dma_addr_t trans_temp;
+
+ link_temp = get_link_desc(cq_host, tag);
+ trans_temp = get_trans_desc_dma(cq_host, tag);
+
+ memset(link_temp, 0, cq_host->link_desc_len);
+ if (cq_host->link_desc_len > 8)
+ *(link_temp + 8) = 0;
+
+ if (tag == DCMD_SLOT) {
+ *link_temp = VALID(0) | ACT(0) | END(1);
+ return;
+ }
+
+ *link_temp = VALID(1) | ACT(0x6) | END(0);
+
+ if (cq_host->dma64) {
+ __le64 *data_addr = (__le64 __force *)(link_temp + 4);
+ data_addr[0] = cpu_to_le64(trans_temp);
+ } else {
+ __le32 *data_addr = (__le32 __force *)(link_temp + 4);
+ data_addr[0] = cpu_to_le32(trans_temp);
+ }
+}
+
+static void cmdq_set_halt_irq(struct cmdq_host *cq_host, bool enable)
+{
+ u32 ier;
+
+ ier = cmdq_readl(cq_host, CQISTE);
+ if (enable) {
+ cmdq_writel(cq_host, ier | HALT, CQISTE);
+ cmdq_writel(cq_host, ier | HALT, CQISGE);
+ } else {
+ cmdq_writel(cq_host, ier & ~HALT, CQISTE);
+ cmdq_writel(cq_host, ier & ~HALT, CQISGE);
+ }
+}
+
+static void cmdq_clear_set_irqs(struct cmdq_host *cq_host, u32 clear, u32 set)
+{
+ u32 ier;
+
+ ier = cmdq_readl(cq_host, CQISTE);
+ ier &= ~clear;
+ ier |= set;
+ cmdq_writel(cq_host, ier, CQISTE);
+ cmdq_writel(cq_host, ier, CQISGE);
+ /* ensure the writes are done */
+ mb();
+}
+
+
+#define DRV_NAME "cmdq-host"
+
+static void cmdq_dump_task_history(struct cmdq_host *cq_host)
+{
+ int i;
+
+ if (likely(!cq_host->mmc->cmdq_thist_enabled))
+ return;
+
+ if (!cq_host->thist) {
+ pr_err("%s: %s: CMDQ task history buffer not allocated\n",
+ mmc_hostname(cq_host->mmc), __func__);
+ return;
+ }
+
+ pr_err("---- Circular Task History ----\n");
+ pr_err(DRV_NAME ": Last entry index: %d", cq_host->thist_idx - 1);
+
+ for (i = 0; i < cq_host->num_slots; i++) {
+ pr_err(DRV_NAME ": [%02d]%s Task: 0x%08x | Args: 0x%08x\n", i,
+ (cq_host->thist[i].is_dcmd) ? "DCMD" : "DATA",
+ lower_32_bits(cq_host->thist[i].task),
+ upper_32_bits(cq_host->thist[i].task));
+ }
+ pr_err("-------------------------\n");
+}
+
+static void cmdq_dump_adma_mem(struct cmdq_host *cq_host)
+{
+ struct mmc_host *mmc = cq_host->mmc;
+ dma_addr_t desc_dma;
+ int tag = 0;
+ unsigned long data_active_reqs =
+ mmc->cmdq_ctx.data_active_reqs;
+ unsigned long desc_size = cq_host->slot_desc_sz;
+
+ for_each_set_bit(tag, &data_active_reqs, cq_host->num_slots) {
+ desc_dma = get_trans_desc_dma(cq_host, tag);
+ pr_err("%s: %s: tag = %d, trans_dma(phys) = %pad, trans_desc(virt) = 0x%p\n",
+ mmc_hostname(mmc), __func__, tag,
+ &desc_dma, get_trans_desc(cq_host, tag));
+ print_hex_dump(KERN_ERR, "cmdq-adma:", DUMP_PREFIX_ADDRESS,
+ 32, 8, get_trans_desc(cq_host, tag),
+ (desc_size), false);
+ }
+}
+
+static void cmdq_dumpregs(struct cmdq_host *cq_host)
+{
+ struct mmc_host *mmc = cq_host->mmc;
+
+ pr_err(DRV_NAME ": ========== REGISTER DUMP (%s)==========\n",
+ mmc_hostname(mmc));
+
+ pr_err(DRV_NAME ": Caps: 0x%08x | Version: 0x%08x\n",
+ cmdq_readl(cq_host, CQCAP),
+ cmdq_readl(cq_host, CQVER));
+ pr_err(DRV_NAME ": Queing config: 0x%08x | Queue Ctrl: 0x%08x\n",
+ cmdq_readl(cq_host, CQCFG),
+ cmdq_readl(cq_host, CQCTL));
+ pr_err(DRV_NAME ": Int stat: 0x%08x | Int enab: 0x%08x\n",
+ cmdq_readl(cq_host, CQIS),
+ cmdq_readl(cq_host, CQISTE));
+ pr_err(DRV_NAME ": Int sig: 0x%08x | Int Coal: 0x%08x\n",
+ cmdq_readl(cq_host, CQISGE),
+ cmdq_readl(cq_host, CQIC));
+ pr_err(DRV_NAME ": TDL base: 0x%08x | TDL up32: 0x%08x\n",
+ cmdq_readl(cq_host, CQTDLBA),
+ cmdq_readl(cq_host, CQTDLBAU));
+ pr_err(DRV_NAME ": Doorbell: 0x%08x | Comp Notif: 0x%08x\n",
+ cmdq_readl(cq_host, CQTDBR),
+ cmdq_readl(cq_host, CQTCN));
+ pr_err(DRV_NAME ": Dev queue: 0x%08x | Dev Pend: 0x%08x\n",
+ cmdq_readl(cq_host, CQDQS),
+ cmdq_readl(cq_host, CQDPT));
+ pr_err(DRV_NAME ": Task clr: 0x%08x | Send stat 1: 0x%08x\n",
+ cmdq_readl(cq_host, CQTCLR),
+ cmdq_readl(cq_host, CQSSC1));
+ pr_err(DRV_NAME ": Send stat 2: 0x%08x | DCMD resp: 0x%08x\n",
+ cmdq_readl(cq_host, CQSSC2),
+ cmdq_readl(cq_host, CQCRDCT));
+ pr_err(DRV_NAME ": Resp err mask: 0x%08x | Task err: 0x%08x\n",
+ cmdq_readl(cq_host, CQRMEM),
+ cmdq_readl(cq_host, CQTERRI));
+ pr_err(DRV_NAME ": Resp idx 0x%08x | Resp arg: 0x%08x\n",
+ cmdq_readl(cq_host, CQCRI),
+ cmdq_readl(cq_host, CQCRA));
+ pr_err(DRV_NAME": Goke cfg 0x%08x\n",
+ cmdq_readl(cq_host, CQ_GOKE_CFG));
+ pr_err(DRV_NAME ": ===========================================\n");
+
+ cmdq_dump_task_history(cq_host);
+ if (cq_host->ops->dump_goke_regs)
+ cq_host->ops->dump_goke_regs(mmc);
+}
+
+/**
+ * The allocated descriptor table for task, link & transfer descritors
+ * looks like:
+ * |----------|
+ * |task desc | |->|----------|
+ * |----------| | |trans desc|
+ * |link desc-|->| |----------|
+ * |----------| .
+ * . .
+ * no. of slots max-segs
+ * . |----------|
+ * |----------|
+ * The idea here is to create the [task+trans] table and mark & point the
+ * link desc to the transfer desc table on a per slot basis.
+ */
+static int cmdq_host_alloc_tdl(struct cmdq_host *cq_host)
+{
+
+ size_t desc_size;
+ size_t data_size;
+ int i = 0;
+
+ /* task descriptor can be 64/128 bit irrespective of arch */
+ if (cq_host->caps & CMDQ_TASK_DESC_SZ_128) {
+ cmdq_writel(cq_host, cmdq_readl(cq_host, CQCFG) |
+ CQ_TASK_DESC_SZ, CQCFG);
+ cq_host->task_desc_len = 16;
+ } else {
+ cq_host->task_desc_len = 8;
+ }
+
+ /*
+ * 96 bits length of transfer desc instead of 128 bits which means
+ * ADMA would expect next valid descriptor at the 96th bit
+ * or 128th bit
+ */
+ if (cq_host->dma64) {
+ if (cq_host->quirks & CMDQ_QUIRK_SHORT_TXFR_DESC_SZ)
+ cq_host->trans_desc_len = 12;
+ else
+ cq_host->trans_desc_len = 16;
+ cq_host->link_desc_len = 16;
+ } else {
+ cq_host->trans_desc_len = 8;
+ cq_host->link_desc_len = 8;
+ }
+
+ /* total size of a slot: 1 task & 1 transfer (link) */
+ cq_host->slot_sz = cq_host->task_desc_len + cq_host->link_desc_len;
+
+ desc_size = cq_host->slot_sz * cq_host->num_slots;
+
+ cq_host->slot_desc_sz = cq_host->trans_desc_len *
+ cq_host->mmc->max_segs * 2;
+ data_size = cq_host->slot_desc_sz * (cq_host->num_slots - 1);
+
+ pr_debug("%s: desc_size: %d data_sz: %d slot-sz: %d\n", __func__,
+ (int)desc_size, (int)data_size, cq_host->slot_sz);
+
+ /*
+ * allocate a dma-mapped chunk of memory for the descriptors
+ * allocate a dma-mapped chunk of memory for link descriptors
+ * setup each link-desc memory offset per slot-number to
+ * the descriptor table.
+ */
+ cq_host->desc_base = dmam_alloc_coherent(mmc_dev(cq_host->mmc),
+ desc_size,
+ &cq_host->desc_dma_base,
+ GFP_KERNEL);
+ cq_host->trans_desc_base = dmam_alloc_coherent(mmc_dev(cq_host->mmc),
+ data_size,
+ &cq_host->trans_desc_dma_base,
+ GFP_KERNEL);
+ cq_host->thist = devm_kzalloc(mmc_dev(cq_host->mmc),
+ (sizeof(*cq_host->thist) *
+ cq_host->num_slots),
+ GFP_KERNEL);
+ if (!cq_host->desc_base || !cq_host->trans_desc_base)
+ return -ENOMEM;
+
+ pr_debug("desc-base: 0x%p trans-base: 0x%p\ndesc_dma 0x%llx trans_dma: 0x%llx\n",
+ cq_host->desc_base, cq_host->trans_desc_base,
+ (unsigned long long)cq_host->desc_dma_base,
+ (unsigned long long) cq_host->trans_desc_dma_base);
+
+ for (; i < (cq_host->num_slots); i++)
+ setup_trans_desc(cq_host, i);
+
+ return 0;
+}
+
+static int cmdq_enable(struct mmc_host *mmc)
+{
+ int err = 0;
+ u32 cqcfg;
+ bool dcmd_enable = false;
+ struct cmdq_host *cq_host = mmc_cmdq_private(mmc);
+
+ if (!cq_host || !mmc->card || !mmc_card_cmdq(mmc->card)) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ if (cq_host->enabled)
+ goto out;
+
+ cmdq_runtime_pm_get(cq_host);
+ cqcfg = cmdq_readl(cq_host, CQCFG);
+ if (cqcfg & 0x1) {
+ pr_info("%s: %s: cq_host is already enabled\n",
+ mmc_hostname(mmc), __func__);
+ WARN_ON(1);
+ goto pm_ref_count;
+ }
+
+ if (cq_host->quirks & CMDQ_QUIRK_NO_DCMD)
+ dcmd_enable = false;
+ else
+ dcmd_enable = true;
+
+ cqcfg = ((cq_host->caps & CMDQ_TASK_DESC_SZ_128 ? CQ_TASK_DESC_SZ : 0) |
+ (dcmd_enable ? CQ_DCMD : 0));
+
+ cmdq_writel(cq_host, cqcfg, CQCFG);
+ /* enable CQ_HOST */
+ cmdq_writel(cq_host, cmdq_readl(cq_host, CQCFG) | CQ_ENABLE,
+ CQCFG);
+
+ if (!cq_host->desc_base ||
+ !cq_host->trans_desc_base) {
+ err = cmdq_host_alloc_tdl(cq_host);
+ if (err)
+ goto pm_ref_count;
+ }
+
+ cmdq_writel(cq_host, lower_32_bits(cq_host->desc_dma_base), CQTDLBA);
+ cmdq_writel(cq_host, upper_32_bits(cq_host->desc_dma_base), CQTDLBAU);
+
+ /*
+ * disable all goke interrupts
+ * enable CMDQ interrupts
+ * enable the goke error interrupts
+ */
+ if (cq_host->ops->clear_set_irqs)
+ cq_host->ops->clear_set_irqs(mmc, true);
+
+ cmdq_clear_set_irqs(cq_host, 0x0, CQ_INT_ALL);
+
+ /* cq_host would use this rca to address the card */
+ cmdq_writel(cq_host, mmc->card->rca, CQSSC2);
+
+ /* send QSR at lesser intervals than the default */
+ cmdq_writel(cq_host, SEND_QSR_INTERVAL, CQSSC1);
+
+ /* enable bkops exception indication */
+ if (mmc_card_configured_manual_bkops(mmc->card) &&
+ !mmc_card_configured_auto_bkops(mmc->card))
+ cmdq_writel(cq_host, cmdq_readl(cq_host, CQRMEM) | CQ_EXCEPTION,
+ CQRMEM);
+
+ /* ensure the writes are done before enabling CQE */
+ mb();
+
+ cq_host->enabled = true;
+ mmc_host_clr_cq_disable(mmc);
+
+ if (cq_host->ops->set_transfer_params)
+ cq_host->ops->set_transfer_params(mmc);
+
+ if (cq_host->ops->set_block_size)
+ cq_host->ops->set_block_size(cq_host->mmc);
+
+ if (cq_host->ops->set_data_timeout)
+ cq_host->ops->set_data_timeout(mmc, 0xf);
+
+ if (cq_host->ops->clear_set_dumpregs)
+ cq_host->ops->clear_set_dumpregs(mmc, 1);
+
+ if (cq_host->ops->enhanced_strobe_mask)
+ cq_host->ops->enhanced_strobe_mask(mmc, true);
+
+pm_ref_count:
+ cmdq_runtime_pm_put(cq_host);
+out:
+ return err;
+}
+
+static void cmdq_disable_nosync(struct mmc_host *mmc, bool soft)
+{
+ struct cmdq_host *cq_host = (struct cmdq_host *)mmc_cmdq_private(mmc);
+
+ if (soft) {
+ cmdq_writel(cq_host, cmdq_readl(
+ cq_host, CQCFG) & ~(CQ_ENABLE),
+ CQCFG);
+ }
+ if (cq_host->ops->enhanced_strobe_mask)
+ cq_host->ops->enhanced_strobe_mask(mmc, false);
+
+ cq_host->enabled = false;
+ mmc_host_set_cq_disable(mmc);
+}
+
+static void cmdq_disable(struct mmc_host *mmc, bool soft)
+{
+ struct cmdq_host *cq_host = (struct cmdq_host *)mmc_cmdq_private(mmc);
+
+ cmdq_runtime_pm_get(cq_host);
+ cmdq_disable_nosync(mmc, soft);
+ cmdq_runtime_pm_put(cq_host);
+}
+
+static void cmdq_reset(struct mmc_host *mmc, bool soft)
+{
+ struct cmdq_host *cq_host = (struct cmdq_host *)mmc_cmdq_private(mmc);
+ unsigned int cqcfg;
+ unsigned int tdlba;
+ unsigned int tdlbau;
+ unsigned int rca;
+ int ret;
+
+ cmdq_runtime_pm_get(cq_host);
+ cqcfg = cmdq_readl(cq_host, CQCFG);
+ tdlba = cmdq_readl(cq_host, CQTDLBA);
+ tdlbau = cmdq_readl(cq_host, CQTDLBAU);
+ rca = cmdq_readl(cq_host, CQSSC2);
+
+ cmdq_disable(mmc, true);
+
+ if (cq_host->ops->reset) {
+ ret = cq_host->ops->reset(mmc);
+ if (ret) {
+ pr_crit("%s: reset CMDQ controller: failed\n",
+ mmc_hostname(mmc));
+ BUG();
+ }
+ }
+
+ cmdq_writel(cq_host, tdlba, CQTDLBA);
+ cmdq_writel(cq_host, tdlbau, CQTDLBAU);
+
+ if (cq_host->ops->clear_set_irqs)
+ cq_host->ops->clear_set_irqs(mmc, true);
+
+ cmdq_clear_set_irqs(cq_host, 0x0, CQ_INT_ALL);
+
+ /* cq_host would use this rca to address the card */
+ cmdq_writel(cq_host, rca, CQSSC2);
+
+ /* ensure the writes are done before enabling CQE */
+ mb();
+
+ cmdq_writel(cq_host, cqcfg, CQCFG);
+ cmdq_runtime_pm_put(cq_host);
+ cq_host->enabled = true;
+ mmc_host_clr_cq_disable(mmc);
+}
+
+static void cmdq_prep_task_desc(struct mmc_request *mrq,
+ u64 *data, bool intr, bool qbr)
+{
+ struct mmc_cmdq_req *cmdq_req = mrq->cmdq_req;
+ u32 req_flags = cmdq_req->cmdq_req_flags;
+
+ pr_debug("%s: %s: data-tag: 0x%08x - dir: %d - prio: %d - cnt: 0x%08x - addr: 0x%llx\n",
+ mmc_hostname(mrq->host), __func__,
+ !!(req_flags & DAT_TAG), !!(req_flags & DIR),
+ !!(req_flags & PRIO), cmdq_req->data.blocks,
+ (u64)mrq->cmdq_req->blk_addr);
+
+ *data = VALID(1) |
+ END(1) |
+ INT(intr) |
+ ACT(0x5) |
+ FORCED_PROG(!!(req_flags & FORCED_PRG)) |
+ CONTEXT(mrq->cmdq_req->ctx_id) |
+ DATA_TAG(!!(req_flags & DAT_TAG)) |
+ DATA_DIR(!!(req_flags & DIR)) |
+ PRIORITY(!!(req_flags & PRIO)) |
+ QBAR(qbr) |
+ REL_WRITE(!!(req_flags & REL_WR)) |
+ BLK_COUNT(mrq->cmdq_req->data.blocks) |
+ BLK_ADDR((u64)mrq->cmdq_req->blk_addr);
+}
+
+static int cmdq_dma_map(struct mmc_host *host, struct mmc_request *mrq)
+{
+ int sg_count;
+ struct mmc_data *data = mrq->data;
+
+ if (!data)
+ return -EINVAL;
+
+ sg_count = dma_map_sg(mmc_dev(host), data->sg,
+ data->sg_len,
+ (data->flags & MMC_DATA_WRITE) ?
+ DMA_TO_DEVICE : DMA_FROM_DEVICE);
+ if (!sg_count) {
+ pr_err("%s: sg-len: %d\n", __func__, data->sg_len);
+ return -ENOMEM;
+ }
+
+ return sg_count;
+}
+
+static void cmdq_set_tran_desc(u8 *desc, dma_addr_t addr, int len,
+ bool end, bool is_dma64)
+{
+ __le32 *attr = (__le32 __force *)desc;
+
+ *attr = (VALID(1) |
+ END(end ? 1 : 0) |
+ INT(0) |
+ ACT(0x4) |
+ DAT_LENGTH(len));
+
+ if (is_dma64) {
+ __le64 *dataddr = (__le64 __force *)(desc + 4);
+
+ dataddr[0] = cpu_to_le64(addr);
+ } else {
+ __le32 *dataddr = (__le32 __force *)(desc + 4);
+
+ dataddr[0] = cpu_to_le32(addr);
+ }
+}
+
+static int cmdq_prep_tran_desc(struct mmc_request *mrq,
+ struct cmdq_host *cq_host, int tag)
+{
+ struct mmc_data *data = mrq->data;
+ int i, sg_count, len;
+ bool end = false;
+ dma_addr_t addr;
+ u8 *desc = NULL;
+ struct scatterlist *sg = NULL;
+
+ sg_count = cmdq_dma_map(mrq->host, mrq);
+ if (sg_count < 0) {
+ pr_err("%s: %s: unable to map sg lists, %d\n",
+ mmc_hostname(mrq->host), __func__, sg_count);
+ return sg_count;
+ }
+
+ desc = get_trans_desc(cq_host, tag);
+ memset(desc, 0, cq_host->slot_desc_sz);
+
+ for_each_sg(data->sg, sg, sg_count, i) {
+ addr = sg_dma_address(sg);
+ len = sg_dma_len(sg);
+
+ if ((i+1) == sg_count)
+ end = true;
+ /* work around for buffer across 128M boundary, split the buffer */
+ if (((addr & (SDHCI_DMA_BOUNDARY_SIZE - 1)) + len) >
+ SDHCI_DMA_BOUNDARY_SIZE) {
+ int offset;
+
+ offset = SDHCI_DMA_BOUNDARY_SIZE -
+ (addr & (SDHCI_DMA_BOUNDARY_SIZE - 1));
+ cmdq_set_tran_desc(desc, addr, offset, false, cq_host->dma64);
+ desc += cq_host->trans_desc_len;
+ addr += offset;
+ len -= offset;
+ }
+ cmdq_set_tran_desc(desc, addr, len, end, cq_host->dma64);
+ desc += cq_host->trans_desc_len;
+ }
+
+ pr_debug("%s: req: 0x%p tag: %d calc_trans_des: 0x%p sg-cnt: %d\n",
+ __func__, mrq->req, tag, desc, sg_count);
+
+ return 0;
+}
+
+static void cmdq_log_task_desc_history(struct cmdq_host *cq_host, u64 task,
+ bool is_dcmd)
+{
+ if (likely(!cq_host->mmc->cmdq_thist_enabled))
+ return;
+
+ if (!cq_host->thist) {
+ pr_err("%s: %s: CMDQ task history buffer not allocated\n",
+ mmc_hostname(cq_host->mmc), __func__);
+ return;
+ }
+
+ if (cq_host->thist_idx >= cq_host->num_slots)
+ cq_host->thist_idx = 0;
+
+ cq_host->thist[cq_host->thist_idx].is_dcmd = is_dcmd;
+ memcpy(&cq_host->thist[cq_host->thist_idx++].task,
+ &task, cq_host->task_desc_len);
+}
+
+static void cmdq_prep_dcmd_desc(struct mmc_host *mmc,
+ struct mmc_request *mrq)
+{
+ u64 *task_desc = NULL;
+ u64 data = 0;
+ u8 resp_type;
+ u8 *desc;
+ __le64 *dataddr == NULL;
+ struct cmdq_host *cq_host = mmc_cmdq_private(mmc);
+ u8 timing;
+
+ if (!(mrq->cmd->flags & MMC_RSP_PRESENT)) {
+ resp_type = 0x0;
+ timing = 0x1;
+ } else {
+ if (mrq->cmd->flags & MMC_RSP_BUSY) {
+ resp_type = 0x3;
+ timing = 0x0;
+ } else {
+ resp_type = 0x2;
+ timing = 0x1;
+ }
+ }
+
+ task_desc = (__le64 __force *)get_desc(cq_host, cq_host->dcmd_slot);
+ memset(task_desc, 0, cq_host->task_desc_len);
+ data |= (VALID(1) |
+ END(1) |
+ INT(1) |
+ QBAR(1) |
+ ACT(0x5) |
+ CMD_INDEX(mrq->cmd->opcode) |
+ CMD_TIMING(timing) | RESP_TYPE(resp_type));
+ *task_desc |= data;
+ desc = (u8 *)task_desc;
+ pr_debug("cmdq: dcmd: cmd: %d timing: %d resp: %d\n",
+ mrq->cmd->opcode, timing, resp_type);
+ dataddr = (__le64 __force *)(desc + 4);
+ dataddr[0] = cpu_to_le64((u64)mrq->cmd->arg);
+ cmdq_log_task_desc_history(cq_host, *task_desc, true);
+}
+
+static int cmdq_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+ int err = 0;
+ u64 data = 0;
+ u64 *task_desc = NULL;
+ u32 tag = mrq->cmdq_req->tag;
+ struct cmdq_host *cq_host = (struct cmdq_host *)mmc_cmdq_private(mmc);
+
+ if (!cq_host->enabled) {
+ pr_err("%s: CMDQ host not enabled yet !!!\n",
+ mmc_hostname(mmc));
+ err = -EINVAL;
+ goto out;
+ }
+
+ cmdq_runtime_pm_get(cq_host);
+
+ if (mrq->cmdq_req->cmdq_req_flags & DCMD) {
+ cmdq_prep_dcmd_desc(mmc, mrq);
+ cq_host->mrq_slot[DCMD_SLOT] = mrq;
+ /* DCMD's are always issued on a fixed slot */
+ tag = DCMD_SLOT;
+ goto ring_doorbell;
+ }
+
+ if (cq_host->ops->crypto_cfg) {
+ err = cq_host->ops->crypto_cfg(mmc, mrq, tag);
+ if (err) {
+ pr_err("%s: failed to configure crypto: err %d tag %d\n",
+ mmc_hostname(mmc), err, tag);
+ goto out;
+ }
+ }
+
+ task_desc = (__le64 __force *)get_desc(cq_host, tag);
+
+ cmdq_prep_task_desc(mrq, &data, 1,
+ (mrq->cmdq_req->cmdq_req_flags & QBR));
+ *task_desc = cpu_to_le64(data);
+ cmdq_log_task_desc_history(cq_host, *task_desc, false);
+
+ err = cmdq_prep_tran_desc(mrq, cq_host, tag);
+ if (err) {
+ pr_err("%s: %s: failed to setup tx desc: %d\n",
+ mmc_hostname(mmc), __func__, err);
+ goto out;
+ }
+
+ cq_host->mrq_slot[tag] = mrq;
+
+ring_doorbell:
+ /* Ensure the task descriptor list is flushed before ringing doorbell */
+ wmb();
+ if (cmdq_readl(cq_host, CQTDBR) & (1 << tag)) {
+ cmdq_dumpregs(cq_host);
+ BUG_ON(1);
+ }
+ cmdq_writel(cq_host, 1 << tag, CQTDBR);
+ /* Commit the doorbell write immediately */
+ wmb();
+
+out:
+ return err;
+}
+
+static void cmdq_finish_data(struct mmc_host *mmc, unsigned int tag)
+{
+ struct mmc_request *mrq;
+ struct cmdq_host *cq_host = (struct cmdq_host *)mmc_cmdq_private(mmc);
+
+ mrq = get_req_by_tag(cq_host, tag);
+ if (tag == cq_host->dcmd_slot)
+ mrq->cmd->resp[0] = cmdq_readl(cq_host, CQCRDCT);
+
+ if (mrq->cmdq_req->cmdq_req_flags & DCMD)
+ cmdq_writel(cq_host, cmdq_readl(cq_host, CQ_GOKE_CFG) |
+ CMDQ_SEND_STATUS_TRIGGER, CQ_GOKE_CFG);
+
+ cmdq_runtime_pm_put(cq_host);
+ if (cq_host->ops->crypto_cfg_reset)
+ cq_host->ops->crypto_cfg_reset(mmc, tag);
+ mrq->done(mrq);
+}
+
+irqreturn_t cmdq_irq(struct mmc_host *mmc, int err)
+{
+ u32 status;
+ unsigned long tag = 0, comp_status;
+ struct cmdq_host *cq_host = (struct cmdq_host *)mmc_cmdq_private(mmc);
+ unsigned long err_info = 0;
+ struct mmc_request *mrq = NULL;
+ int ret;
+ u32 dbr_set = 0;
+
+ status = cmdq_readl(cq_host, CQIS);
+ cmdq_writel(cq_host, status, CQIS);
+
+ if (!status && !err)
+ return IRQ_NONE;
+
+ if (err || (status & CQIS_RED)) {
+ err_info = cmdq_readl(cq_host, CQTERRI);
+ pr_err("%s: err: %d status: 0x%08x task-err-info (0x%08lx)\n",
+ mmc_hostname(mmc), err, status, err_info);
+
+ /*
+ * Need to halt CQE in case of error in interrupt context itself
+ * otherwise CQE may proceed with sending CMD to device even if
+ * CQE/card is in error state.
+ * CMDQ error handling will make sure that it is unhalted after
+ * handling all the errors.
+ */
+ ret = cmdq_halt_poll(mmc, true);
+ if (ret)
+ pr_err("%s: %s: halt failed ret=%d\n",
+ mmc_hostname(mmc), __func__, ret);
+ cmdq_dumpregs(cq_host);
+
+ if (!err_info) {
+ /*
+ * It may so happen sometimes for few errors(like ADMA)
+ * that HW cannot give CQTERRI info.
+ * Thus below is a HW WA for recovering from such
+ * scenario.
+ * - To halt/disable CQE and do reset_all.
+ * Since there is no way to know which tag would
+ * have caused such error, so check for any first
+ * bit set in doorbell and proceed with an error.
+ */
+ dbr_set = cmdq_readl(cq_host, CQTDBR);
+ if (!dbr_set) {
+ pr_err("%s: spurious/force error interrupt\n",
+ mmc_hostname(mmc));
+ cmdq_halt_poll(mmc, false);
+ mmc_host_clr_halt(mmc);
+ return IRQ_HANDLED;
+ }
+
+ tag = ffs(dbr_set) - 1;
+ pr_err("%s: error tag selected: tag = %lu\n",
+ mmc_hostname(mmc), tag);
+ mrq = get_req_by_tag(cq_host, tag);
+ if (mrq->data)
+ mrq->data->error = err;
+ else
+ mrq->cmd->error = err;
+ /*
+ * Get ADMA descriptor memory in case of ADMA
+ * error for debug.
+ */
+ if (err == -EIO)
+ cmdq_dump_adma_mem(cq_host);
+ goto skip_cqterri;
+ }
+
+ if (err_info & CQ_RMEFV) {
+ tag = GET_CMD_ERR_TAG(err_info);
+ pr_err("%s: CMD err tag: %lu\n", __func__, tag);
+
+ mrq = get_req_by_tag(cq_host, tag);
+ /* CMD44/45/46/47 will not have a valid cmd */
+ if (mrq->cmd)
+ mrq->cmd->error = err;
+ else
+ mrq->data->error = err;
+ } else if (err_info & CQ_DTEFV) {
+ tag = GET_DAT_ERR_TAG(err_info);
+ pr_err("%s: Dat err tag: %lu\n", __func__, tag);
+ mrq = get_req_by_tag(cq_host, tag);
+ mrq->data->error = err;
+ }
+
+skip_cqterri:
+ /*
+ * If CQE halt fails then, disable CQE
+ * from processing any further requests
+ */
+ if (ret) {
+ cmdq_disable_nosync(mmc, true);
+ /*
+ * Enable legacy interrupts as CQE halt has failed.
+ * This is needed to send legacy commands like status
+ * cmd as part of error handling work.
+ */
+ if (cq_host->ops->clear_set_irqs)
+ cq_host->ops->clear_set_irqs(mmc, false);
+ }
+
+ /*
+ * CQE detected a reponse error from device
+ * In most cases, this would require a reset.
+ */
+ if (status & CQIS_RED) {
+ /*
+ * will check if the RED error is due to a bkops
+ * exception once the queue is empty
+ */
+ BUG_ON(!mmc->card);
+ /*if (mmc_card_configured_manual_bkops(mmc->card) ||
+ mmc_card_configured_auto_bkops(mmc->card))
+ mmc->card->bkops.needs_check = true;*/
+
+ mrq->cmdq_req->resp_err = true;
+ pr_err("%s: Response error (0x%08x) from card !!!",
+ mmc_hostname(mmc), status);
+ } else {
+ mrq->cmdq_req->resp_idx = cmdq_readl(cq_host, CQCRI);
+ mrq->cmdq_req->resp_arg = cmdq_readl(cq_host, CQCRA);
+ }
+
+ cmdq_finish_data(mmc, tag);
+ }
+
+ if (status & CQIS_TCC) {
+ /* read CQTCN and complete the request */
+ comp_status = cmdq_readl(cq_host, CQTCN);
+ if (!comp_status)
+ goto out;
+ /*
+ * The CQTCN must be cleared before notifying req completion
+ * to upper layers to avoid missing completion notification
+ * of new requests with the same tag.
+ */
+ cmdq_writel(cq_host, comp_status, CQTCN);
+ /*
+ * A write memory barrier is necessary to guarantee that CQTCN
+ * gets cleared first before next doorbell for the same tag is
+ * set but that is already achieved by the barrier present
+ * before setting doorbell, hence one is not needed here.
+ */
+ for_each_set_bit(tag, &comp_status, cq_host->num_slots) {
+ /* complete the corresponding mrq */
+ pr_debug("%s: completing tag -> %lu\n",
+ mmc_hostname(mmc), tag);
+ cmdq_finish_data(mmc, tag);
+ }
+ }
+
+ if (status & CQIS_HAC) {
+ if (cq_host->ops->post_cqe_halt)
+ cq_host->ops->post_cqe_halt(mmc);
+ /* halt is completed, wakeup waiting thread */
+ complete(&cq_host->halt_comp);
+ }
+
+out:
+ return IRQ_HANDLED;
+}
+EXPORT_SYMBOL(cmdq_irq);
+
+/* cmdq_halt_poll - Halting CQE using polling method.
+ * @mmc: struct mmc_host
+ * @halt: bool halt
+ * This is used mainly from interrupt context to halt/unhalt
+ * CQE engine.
+ */
+static int cmdq_halt_poll(struct mmc_host *mmc, bool halt)
+{
+ struct cmdq_host *cq_host = (struct cmdq_host *)mmc_cmdq_private(mmc);
+ int retries = 100;
+
+ if (!halt) {
+ if (cq_host->ops->set_data_timeout)
+ cq_host->ops->set_data_timeout(mmc, 0xf);
+ if (cq_host->ops->clear_set_irqs)
+ cq_host->ops->clear_set_irqs(mmc, true);
+ cmdq_writel(cq_host, cmdq_readl(cq_host, CQCTL) & ~HALT,
+ CQCTL);
+ return 0;
+ }
+
+ cmdq_set_halt_irq(cq_host, false);
+ cmdq_writel(cq_host, cmdq_readl(cq_host, CQCTL) | HALT, CQCTL);
+ while (retries) {
+ if (!(cmdq_readl(cq_host, CQCTL) & HALT)) {
+ udelay(5);
+ retries--;
+ continue;
+ } else {
+ if (cq_host->ops->post_cqe_halt)
+ cq_host->ops->post_cqe_halt(mmc);
+ /* halt done: re-enable legacy interrupts */
+ if (cq_host->ops->clear_set_irqs)
+ cq_host->ops->clear_set_irqs(mmc,
+ false);
+ mmc_host_set_halt(mmc);
+ break;
+ }
+ }
+ cmdq_set_halt_irq(cq_host, true);
+ return retries ? 0 : -ETIMEDOUT;
+}
+
+/* May sleep */
+static int cmdq_halt(struct mmc_host *mmc, bool halt)
+{
+ struct cmdq_host *cq_host = (struct cmdq_host *)mmc_cmdq_private(mmc);
+ u32 ret = 0;
+ int retries = 3;
+
+ cmdq_runtime_pm_get(cq_host);
+ if (halt) {
+ while (retries) {
+ cmdq_writel(cq_host, cmdq_readl(cq_host, CQCTL) | HALT,
+ CQCTL);
+ ret = wait_for_completion_timeout(&cq_host->halt_comp,
+ msecs_to_jiffies(HALT_TIMEOUT_MS));
+ if (!ret && !(cmdq_readl(cq_host, CQCTL) & HALT)) {
+ retries--;
+ continue;
+ } else {
+ /* halt done: re-enable legacy interrupts */
+ if (cq_host->ops->clear_set_irqs)
+ cq_host->ops->clear_set_irqs(mmc,
+ false);
+ break;
+ }
+ }
+ ret = retries ? 0 : -ETIMEDOUT;
+ } else {
+ if (cq_host->ops->set_transfer_params)
+ cq_host->ops->set_transfer_params(mmc);
+ if (cq_host->ops->set_block_size)
+ cq_host->ops->set_block_size(mmc);
+ if (cq_host->ops->set_data_timeout)
+ cq_host->ops->set_data_timeout(mmc, 0xf);
+ if (cq_host->ops->clear_set_irqs)
+ cq_host->ops->clear_set_irqs(mmc, true);
+ cmdq_writel(cq_host, cmdq_readl(cq_host, CQCTL) & ~HALT,
+ CQCTL);
+ }
+ cmdq_runtime_pm_put(cq_host);
+ return ret;
+}
+
+static void cmdq_post_req(struct mmc_host *mmc, int tag, int err)
+{
+ struct cmdq_host *cq_host = NULL;
+ struct mmc_request *mrq = NULL;
+ struct mmc_data *data = NULL;
+
+ if (WARN_ON(!mmc))
+ return;
+
+ cq_host = (struct cmdq_host *)mmc_cmdq_private(mmc);
+ mrq = get_req_by_tag(cq_host, tag);
+ data = mrq->data;
+
+ if (data) {
+ data->error = err;
+ dma_unmap_sg(mmc_dev(mmc), data->sg, data->sg_len,
+ (data->flags & MMC_DATA_READ) ?
+ DMA_FROM_DEVICE : DMA_TO_DEVICE);
+ if (err)
+ data->bytes_xfered = 0;
+ else
+ data->bytes_xfered = blk_rq_bytes(mrq->req);
+
+ }
+}
+
+static void cmdq_dumpstate(struct mmc_host *mmc)
+{
+ struct cmdq_host *cq_host = (struct cmdq_host *)mmc_cmdq_private(mmc);
+ cmdq_runtime_pm_get(cq_host);
+ cmdq_dumpregs(cq_host);
+ cmdq_runtime_pm_put(cq_host);
+}
+
+static const struct mmc_cmdq_host_ops cmdq_host_ops = {
+ .enable = cmdq_enable,
+ .disable = cmdq_disable,
+ .request = cmdq_request,
+ .post_req = cmdq_post_req,
+ .halt = cmdq_halt,
+ .reset = cmdq_reset,
+ .dumpstate = cmdq_dumpstate,
+};
+
+struct cmdq_host *cmdq_pltfm_init(struct platform_device *pdev)
+{
+ struct cmdq_host *cq_host = NULL;
+ struct resource *cmdq_memres = NULL;
+
+ /* check and setup CMDQ interface */
+ cmdq_memres = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "cmdq_mem");
+ if (!cmdq_memres) {
+ dev_dbg(&pdev->dev, "CMDQ not supported\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ cq_host = kzalloc(sizeof(*cq_host), GFP_KERNEL);
+ if (!cq_host) {
+ dev_err(&pdev->dev, "failed to allocate memory for CMDQ\n");
+ return ERR_PTR(-ENOMEM);
+ }
+ cq_host->mmio = devm_ioremap(&pdev->dev,
+ cmdq_memres->start,
+ resource_size(cmdq_memres));
+ if (!cq_host->mmio) {
+ dev_err(&pdev->dev, "failed to remap cmdq regs\n");
+ kfree(cq_host);
+ return ERR_PTR(-EBUSY);
+ }
+ dev_dbg(&pdev->dev, "CMDQ ioremap: done\n");
+
+ return cq_host;
+}
+EXPORT_SYMBOL(cmdq_pltfm_init);
+
+int cmdq_init(struct cmdq_host *cq_host, struct mmc_host *mmc,
+ bool dma64)
+{
+ int err = 0;
+
+ cq_host->dma64 = dma64;
+ cq_host->mmc = mmc;
+ cq_host->mmc->cmdq_private = cq_host;
+
+ cq_host->num_slots = NUM_SLOTS;
+ cq_host->dcmd_slot = DCMD_SLOT;
+
+ mmc->cmdq_ops = &cmdq_host_ops;
+ mmc->num_cq_slots = NUM_SLOTS;
+ mmc->dcmd_cq_slot = DCMD_SLOT;
+
+ cq_host->mrq_slot = kzalloc(sizeof(cq_host->mrq_slot) *
+ cq_host->num_slots, GFP_KERNEL);
+ if (!cq_host->mrq_slot)
+ return -ENOMEM;
+
+ init_completion(&cq_host->halt_comp);
+ return err;
+}
+EXPORT_SYMBOL(cmdq_init);
diff -urN linux-4.9.37/drivers/mmc/host/sdhci-cmdq.h linux-4.9.y/drivers/mmc/host/sdhci-cmdq.h
--- linux-4.9.37/drivers/mmc/host/sdhci-cmdq.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/mmc/host/sdhci-cmdq.h 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+#ifndef LINUX_MMC_CQ_HCI_H
+#define LINUX_MMC_CQ_HCI_H
+#include <linux/mmc/core.h>
+
+/* registers */
+/* version */
+#define CQVER 0x00
+/* capabilities */
+#define CQCAP 0x04
+/* configuration */
+#define CQCFG 0x08
+#define CQ_DCMD 0x00001000
+#define CQ_TASK_DESC_SZ 0x00000100
+#define CQ_ENABLE 0x00000001
+
+/* control */
+#define CQCTL 0x0C
+#define CLEAR_ALL_TASKS 0x00000100
+#define HALT 0x00000001
+
+/* interrupt status */
+#define CQIS 0x10
+#define CQIS_HAC (1 << 0)
+#define CQIS_TCC (1 << 1)
+#define CQIS_RED (1 << 2)
+#define CQIS_TCL (1 << 3)
+
+/* interrupt status enable */
+#define CQISTE 0x14
+
+/* interrupt signal enable */
+#define CQISGE 0x18
+
+/* interrupt coalescing */
+#define CQIC 0x1C
+#define CQIC_ENABLE (1 << 31)
+#define CQIC_RESET (1 << 16)
+#define CQIC_ICCTHWEN (1 << 15)
+#define CQIC_ICCTH(x) ((x & 0x1F) << 8)
+#define CQIC_ICTOVALWEN (1 << 7)
+#define CQIC_ICTOVAL(x) (x & 0x7F)
+
+/* task list base address */
+#define CQTDLBA 0x20
+
+/* task list base address upper */
+#define CQTDLBAU 0x24
+
+/* door-bell */
+#define CQTDBR 0x28
+
+/* task completion notification */
+#define CQTCN 0x2C
+
+/* device queue status */
+#define CQDQS 0x30
+
+/* device pending tasks */
+#define CQDPT 0x34
+
+/* task clear */
+#define CQTCLR 0x38
+
+/* send status config 1 */
+#define CQSSC1 0x40
+/*
+ * Value n means CQE would send CMD13 during the transfer of data block
+ * BLOCK_CNT-n
+ */
+#define SEND_QSR_INTERVAL 0x70001
+
+/* send status config 2 */
+#define CQSSC2 0x44
+
+/* response for dcmd */
+#define CQCRDCT 0x48
+
+/* response mode error mask */
+#define CQRMEM 0x50
+#define CQ_EXCEPTION (1 << 6)
+
+/* task error info */
+#define CQTERRI 0x54
+
+/* CQTERRI bit fields */
+#define CQ_RMECI 0x1F
+#define CQ_RMETI (0x1F << 8)
+#define CQ_RMEFV (1 << 15)
+#define CQ_DTECI (0x3F << 16)
+#define CQ_DTETI (0x1F << 24)
+#define CQ_DTEFV (1 << 31)
+
+#define GET_CMD_ERR_TAG(__r__) ((__r__ & CQ_RMETI) >> 8)
+#define GET_DAT_ERR_TAG(__r__) ((__r__ & CQ_DTETI) >> 24)
+
+/* command response index */
+#define CQCRI 0x58
+
+/* command response argument */
+#define CQCRA 0x5C
+
+#define CQ_INT_ALL 0xF
+#define CQIC_DEFAULT_ICCTH 31
+#define CQIC_DEFAULT_ICTOVAL 1
+
+/* attribute fields */
+#define VALID(x) ((x & 1) << 0)
+#define END(x) ((x & 1) << 1)
+#define INT(x) ((x & 1) << 2)
+#define ACT(x) ((x & 0x7) << 3)
+
+/* data command task descriptor fields */
+#define FORCED_PROG(x) ((x & 1) << 6)
+#define CONTEXT(x) ((x & 0xF) << 7)
+#define DATA_TAG(x) ((x & 1) << 11)
+#define DATA_DIR(x) ((x & 1) << 12)
+#define PRIORITY(x) ((x & 1) << 13)
+#define QBAR(x) ((x & 1) << 14)
+#define REL_WRITE(x) ((x & 1) << 15)
+#define BLK_COUNT(x) ((x & 0xFFFF) << 16)
+#define BLK_ADDR(x) ((x & 0xFFFFFFFF) << 32)
+
+/* direct command task descriptor fields */
+#define CMD_INDEX(x) ((x & 0x3F) << 16)
+#define CMD_TIMING(x) ((x & 1) << 22)
+#define RESP_TYPE(x) ((x & 0x3) << 23)
+
+/* transfer descriptor fields */
+#define DAT_LENGTH(x) ((x & 0xFFFF) << 16)
+#define DAT_ADDR_LO(x) ((x & 0xFFFFFFFF) << 32)
+#define DAT_ADDR_HI(x) ((x & 0xFFFFFFFF) << 0)
+
+#define CQ_GOKE_CFG 0x100
+#define CMDQ_SEND_STATUS_TRIGGER (1 << 31)
+
+struct task_history {
+ u64 task;
+ bool is_dcmd;
+};
+
+struct cmdq_host {
+ const struct cmdq_host_ops *ops;
+ void __iomem *mmio;
+ struct mmc_host *mmc;
+
+ /* 64 bit DMA */
+ bool dma64;
+ int num_slots;
+
+ u32 dcmd_slot;
+ u32 caps;
+#define CMDQ_TASK_DESC_SZ_128 0x1
+
+ u32 quirks;
+#define CMDQ_QUIRK_SHORT_TXFR_DESC_SZ 0x1
+#define CMDQ_QUIRK_NO_DCMD 0x2
+
+ bool enabled;
+ bool halted;
+ bool init_done;
+
+ u8 *desc_base;
+
+ /* total descriptor size */
+ u8 slot_sz;
+
+ /* 64/128 bit depends on CQCFG */
+ u8 task_desc_len;
+
+ /* 64 bit on 32-bit arch, 128 bit on 64-bit */
+ u8 link_desc_len;
+
+ u8 *trans_desc_base;
+ /* same length as transfer descriptor */
+ u8 trans_desc_len;
+ /* descriptor size per slot */
+ u32 slot_desc_sz;
+
+ dma_addr_t desc_dma_base;
+ dma_addr_t trans_desc_dma_base;
+
+ struct task_history *thist;
+ u8 thist_idx;
+
+ struct completion halt_comp;
+ struct mmc_request **mrq_slot;
+ void *private;
+};
+
+struct cmdq_host_ops {
+ void (*set_transfer_params)(struct mmc_host *mmc);
+ void (*set_data_timeout)(struct mmc_host *mmc, u32 val);
+ void (*clear_set_irqs)(struct mmc_host *mmc, bool clear);
+ void (*set_block_size)(struct mmc_host *mmc);
+ void (*dump_goke_regs)(struct mmc_host *mmc);
+ void (*write_l)(struct cmdq_host *host, u32 val, int reg);
+ u32 (*read_l)(struct cmdq_host *host, int reg);
+ void (*clear_set_dumpregs)(struct mmc_host *mmc, bool set);
+ void (*enhanced_strobe_mask)(struct mmc_host *mmc, bool set);
+ int (*reset)(struct mmc_host *mmc);
+ int (*crypto_cfg)(struct mmc_host *mmc, struct mmc_request *mrq,
+ u32 slot);
+ void (*crypto_cfg_reset)(struct mmc_host *mmc, unsigned int slot);
+ void (*post_cqe_halt)(struct mmc_host *mmc);
+};
+
+static inline void cmdq_writel(struct cmdq_host *host, u32 val, int reg)
+{
+ if (unlikely(host->ops && host->ops->write_l))
+ host->ops->write_l(host, val, reg);
+ else
+ writel_relaxed(val, host->mmio + reg);
+}
+
+static inline u32 cmdq_readl(struct cmdq_host *host, int reg)
+{
+ if (unlikely(host->ops && host->ops->read_l))
+ return host->ops->read_l(host, reg);
+ else
+ return readl_relaxed(host->mmio + reg);
+}
+
+extern irqreturn_t cmdq_irq(struct mmc_host *mmc, int err);
+extern int cmdq_init(struct cmdq_host *cq_host, struct mmc_host *mmc,
+ bool dma64);
+extern struct cmdq_host *cmdq_pltfm_init(struct platform_device *pdev);
+#endif
diff -urN linux-4.9.37/drivers/mmc/host/sdhci-gk7202v300.c linux-4.9.y/drivers/mmc/host/sdhci-gk7202v300.c
--- linux-4.9.37/drivers/mmc/host/sdhci-gk7202v300.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/mmc/host/sdhci-gk7202v300.c 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,495 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/of.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <linux/reset.h>
+#include <linux/mmc/host.h>
+#include <linux/pm_runtime.h>
+#include "sdhci-pltfm.h"
+#include "sdhci-proc.h"
+
+#ifdef CONFIG_MMC_SDHCI_GOKE
+#define PHASE_SCALE 32
+#define EDGE_TUNING_PHASE_STEP 4
+#define NOT_FOUND (-1)
+#define MAX_TUNING_NUM 1
+#define MAX_FREQ 200000000
+
+#define GOKE_MMC_AUTOSUSPEND_DELAY_MS 50
+
+#define REG_EMMC_DRV_DLL_CTRL 0x1fc
+#define REG_SDIO0_DRV_DLL_CTRL 0x1fc
+#define REG_SDIO1_DRV_DLL_CTRL 0x220
+#define REG_SDIO2_DRV_DLL_CTRL /* no sdio2 */
+#define SDIO_DRV_PHASE_SEL_MASK (0x1f << 24)
+#define sdio_drv_sel(phase) ((phase) << 24)
+
+#define REG_EMMC_DRV_DLL_STATUS 0x210
+#define REG_SDIO0_DRV_DLL_STATUS 0x210
+#define REG_SDIO1_DRV_DLL_STATUS 0x228
+#define REG_SDIO2_DRV_DLL_STATUS /* no sdio2 */
+#define SDIO_DRV_DLL_LOCK BIT(15)
+#define SDIO_DRV_DLL_READY BIT(14)
+
+#define REG_EMMC_SAMPL_DLL_STATUS 0x208
+#define REG_SDIO0_SAMPL_DLL_STATUS 0x208
+#define REG_SDIO1_SAMPL_DLL_STATUS 0x224
+#define REG_SDIO2_SAMPL_DLL_STATUS /* no sdio2 */
+#define SDIO_SAMPL_DLL_SLAVE_READY BIT(0)
+
+#define REG_EMMC_SAMPL_DLL_CTRL 0x1f4
+#define REG_SDIO0_SAMPL_DLL_CTRL 0x1f4
+#define REG_SDIO1_SAMPL_DLL_CTRL 0x22c
+#define REG_SDIO2_SAMPL_DLL_CTRL /* no sdio2 */
+#define SDIO_SAMPL_DLL_SLAVE_EN BIT(16)
+
+#define REG_EMMC_SAMPLB_DLL_CTRL 0x1f8
+#define REG_SDIO0_SAMPLB_DLL_CTRL 0x1f8
+#define REG_SDIO1_SAMPLB_DLL_CTRL 0x21c
+#define REG_SDIO2_SAMPLB_DLL_CTRL /* no sdio2 */
+#define SDIO_SAMPLB_DLL_CLK_MASK (0x1f << 0)
+#define sdio_samplb_sel(phase) ((phase) << 0)
+
+#define REG_EMMC_DS_DLL_CTRL 0x200
+#define EMMC_DS_DLL_MODE_SSEL BIT(13)
+#define EMMC_DS_DLL_SSEL_MASK 0x7f
+
+#define REG_EMMC_DS180_DLL_CTRL 0x204
+#define EMMC_DS180_DLL_BYPASS BIT(15)
+#define REG_EMMC_DS180_DLL_STATUS 0x218
+#define EMMC_DS180_DLL_READY BIT(0)
+
+#define REG_EMMC_DS_DLL_STATUS 0x214
+#define EMMC_DS_DLL_READY BIT(0)
+
+#define REG_EMMC_CLK_CTRL 0x1f4
+#define REG_SDIO0_CLK_CTRL 0x1f4
+#define REG_SDIO1_CLK_CTRL 0x22c
+#define REG_SDIO2_CLK_CTRL /* no sdio2 */
+#define SDIO_CLK_DRV_DLL_RST BIT(29)
+#define SDIO_CLK_CRG_RST BIT(27)
+
+#define IO_CFG_SR BIT(10)
+#define IO_CFG_PULL_DOWN BIT(9)
+#define IO_CFG_PULL_UP BIT(8)
+#define IO_CFG_DRV_STR_MASK (0xf << 4)
+#define io_cfg_drv_str_sel(str) ((str) << 4)
+#define IO_CFG_PIN_MUX_MASK (0xf << 0)
+#define io_cfg_pin_mux_sel(type) ((type) << 0)
+#define IO_CFG_PIN_MUX_TYPE_CLK_EMMC 0x0
+#define IO_CFG_PIN_MUX_TYPE_CLK_SD 0x1
+
+#define IO_CFG_EMMC_DATA_LINE_COUNT 4
+#define REG_CTRL_EMMC_CLK 0x0014
+#define REG_CTRL_EMMC_CMD 0x0018
+#define REG_CTRL_EMMC_DATA0 0x001c
+#define REG_CTRL_EMMC_DATA1 0x0028
+#define REG_CTRL_EMMC_DATA2 0x0024
+#define REG_CTRL_EMMC_DATA3 0x0020
+
+#define REG_CTRL_EMMC_DS 0x0058
+#define REG_CTRL_EMMC_RST 0x005c
+static unsigned int io_emmc_data_reg[IO_CFG_EMMC_DATA_LINE_COUNT] = {
+ REG_CTRL_EMMC_DATA0, REG_CTRL_EMMC_DATA1,
+ REG_CTRL_EMMC_DATA2, REG_CTRL_EMMC_DATA3
+};
+
+#define IO_CFG_SDIO0_DATA_LINE_COUNT 4
+#define REG_CTRL_SDIO0_CLK 0x0040
+#define REG_CTRL_SDIO0_CMD 0x0044
+#define REG_CTRL_SDIO0_DATA0 0x0048
+#define REG_CTRL_SDIO0_DATA1 0x004C
+#define REG_CTRL_SDIO0_DATA2 0x0050
+#define REG_CTRL_SDIO0_DATA3 0x0054
+static unsigned int io_sdio0_data_reg[IO_CFG_SDIO0_DATA_LINE_COUNT] = {
+ REG_CTRL_SDIO0_DATA0, REG_CTRL_SDIO0_DATA1,
+ REG_CTRL_SDIO0_DATA2, REG_CTRL_SDIO0_DATA3
+};
+
+#define IO_CFG_SDIO1_DATA_LINE_COUNT 4
+#define REG_CTRL_SDIO1_CLK 0x0048
+#define REG_CTRL_SDIO1_CMD 0x004C
+#define REG_CTRL_SDIO1_DATA0 0x0064
+#define REG_CTRL_SDIO1_DATA1 0x0060
+#define REG_CTRL_SDIO1_DATA2 0x005C
+#define REG_CTRL_SDIO1_DATA3 0x0058
+static unsigned int io_sdio1_data_reg[IO_CFG_SDIO1_DATA_LINE_COUNT] = {
+ REG_CTRL_SDIO1_DATA0, REG_CTRL_SDIO1_DATA1,
+ REG_CTRL_SDIO1_DATA2, REG_CTRL_SDIO1_DATA3
+};
+
+struct sdhci_bsp_priv {
+ struct reset_control *crg_rst;
+ struct reset_control *dll_rst;
+ struct reset_control *sampl_rst; /* Not used */
+ struct regmap *crg_regmap;
+ struct regmap *iocfg_regmap;
+ unsigned int f_max;
+ unsigned int devid;
+ unsigned int drv_phase;
+ unsigned int sampl_phase;
+ unsigned int tuning_phase;
+};
+
+static void bsp_mmc_crg_init(struct sdhci_host *host);
+static void sdhci_bsp_hs400_enhanced_strobe(struct mmc_host *mmc, struct mmc_ios *ios);
+static int sdhci_bsp_parse_dt(struct sdhci_host *host);
+
+static inline void *sdhci_get_pltfm_priv(struct sdhci_host *host)
+{
+ return sdhci_pltfm_priv(sdhci_priv(host));
+}
+
+static void sdhci_bsp_hs400_enhanced_strobe(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+ u32 ctrl;
+ struct sdhci_host *host = mmc_priv(mmc);
+
+ ctrl = sdhci_readl(host, SDHCI_EMMC_CTRL);
+ if (ios->enhanced_strobe)
+ ctrl |= SDHCI_ENH_STROBE_EN;
+ else
+ ctrl &= ~SDHCI_ENH_STROBE_EN;
+
+ sdhci_writel(host, ctrl, SDHCI_EMMC_CTRL);
+}
+
+static int sdhci_bsp_pltfm_init(struct platform_device *pdev, struct sdhci_host *host)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_bsp_priv *bsp_priv = sdhci_pltfm_priv(pltfm_host);
+ struct device_node *np = pdev->dev.of_node;
+ struct clk *clk = NULL;
+ int ret;
+
+ bsp_priv->crg_rst = devm_reset_control_get(&pdev->dev, "crg_reset");
+ if (IS_ERR_OR_NULL(bsp_priv->crg_rst)) {
+ dev_err(&pdev->dev, "get crg_rst failed.\n");
+ return PTR_ERR(bsp_priv->crg_rst);
+ }
+
+ bsp_priv->dll_rst = devm_reset_control_get(&pdev->dev, "dll_reset");
+ if (IS_ERR_OR_NULL(bsp_priv->dll_rst)) {
+ dev_err(&pdev->dev, "get dll_rst failed.\n");
+ return PTR_ERR(bsp_priv->dll_rst);
+ }
+
+ bsp_priv->sampl_rst = NULL;
+
+ bsp_priv->crg_regmap = syscon_regmap_lookup_by_phandle(np, "crg_regmap");
+ if (IS_ERR(bsp_priv->crg_regmap)) {
+ dev_err(&pdev->dev, "get crg regmap failed.\n");
+ return PTR_ERR(bsp_priv->crg_regmap);
+ }
+
+ bsp_priv->iocfg_regmap = syscon_regmap_lookup_by_phandle(np, "iocfg_regmap");
+ if (IS_ERR(bsp_priv->iocfg_regmap)) {
+ dev_err(&pdev->dev, "get iocfg regmap failed.\n");
+ return PTR_ERR(bsp_priv->iocfg_regmap);
+ }
+
+ if (of_property_read_u32(np, "devid", &bsp_priv->devid))
+ return -EINVAL;
+
+ clk = devm_clk_get(mmc_dev(host->mmc), "mmc_clk");
+ if (IS_ERR_OR_NULL(clk)) {
+ dev_err(mmc_dev(host->mmc), "get clk err\n");
+ return -EINVAL;
+ }
+
+ pltfm_host->clk = clk;
+
+ bsp_mmc_crg_init(host);
+ ret = sdhci_bsp_parse_dt(host);
+ if (ret)
+ return ret;
+
+ /*
+ * Only eMMC has a hw reset, and now eMMC signaling
+ * is fixed to 180
+ */
+ if (host->mmc->caps & MMC_CAP_HW_RESET) {
+ host->flags &= ~SDHCI_SIGNALING_330;
+ host->flags |= SDHCI_SIGNALING_180;
+ }
+
+ /*
+ * We parse the support timings from dts, so we read the
+ * host capabilities early and clear the timing capabilities,
+ * SDHCI_QUIRK_MISSING_CAPS is set so that sdhci driver would
+ * not read it again
+ */
+ host->caps = sdhci_readl(host, SDHCI_CAPABILITIES);
+ host->caps &= ~(SDHCI_CAN_DO_HISPD | SDHCI_CAN_VDD_300);
+ host->caps1 = sdhci_readl(host, SDHCI_CAPABILITIES_1);
+ host->caps1 &= ~(SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_SDR104 |
+ SDHCI_SUPPORT_DDR50 | SDHCI_CAN_DO_ADMA3);
+ host->quirks |= SDHCI_QUIRK_MISSING_CAPS |
+ SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC |
+ SDHCI_QUIRK_SINGLE_POWER_WRITE;
+
+ host->mmc_host_ops.hs400_enhanced_strobe =
+ sdhci_bsp_hs400_enhanced_strobe;
+
+ mci_host[slot_index++] = host->mmc;
+
+ return 0;
+}
+
+static void bsp_wait_ds_dll_lock(struct sdhci_host *host)
+{
+ /* Do nothing */
+}
+
+static void bsp_wait_ds_180_dll_ready(struct sdhci_host *host)
+{
+ struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host);
+ unsigned int reg;
+ unsigned int timeout = 20;
+
+ do {
+ reg = 0;
+ regmap_read(bsp_priv->crg_regmap,
+ REG_EMMC_DS180_DLL_STATUS, &reg);
+ if (reg & EMMC_DS180_DLL_READY)
+ return;
+
+ mdelay(1);
+ timeout--;
+ } while (timeout > 0);
+
+ pr_err("%s: DS 180 DLL master not ready.\n", mmc_hostname(host->mmc));
+}
+
+static void bsp_set_ds_dll_delay(struct sdhci_host *host)
+{
+ /* Do nothing */
+}
+
+static void bsp_host_extra_init(struct sdhci_host *host)
+{
+ unsigned short ctrl;
+ unsigned int mbiiu_ctrl, val;
+
+ ctrl = sdhci_readw(host, SDHCI_MSHC_CTRL);
+ ctrl &= ~SDHCI_CMD_CONFLIT_CHECK;
+ sdhci_writew(host, ctrl, SDHCI_MSHC_CTRL);
+
+ mbiiu_ctrl = sdhci_readl(host, SDHCI_AXI_MBIIU_CTRL);
+ mbiiu_ctrl &= ~(SDHCI_GM_WR_OSRC_LMT_MASK | SDHCI_GM_RD_OSRC_LMT_MASK |
+ SDHCI_UNDEFL_INCR_EN);
+ mbiiu_ctrl |= (SDHCI_GM_WR_OSRC_LMT_SEL(0x7) | /* set write outstanding 8 (lmt + 1) */
+ SDHCI_GM_RD_OSRC_LMT_SEL(0x7)); /* set read outstanding 8 (lmt + 1) */
+ sdhci_writel(host, mbiiu_ctrl, SDHCI_AXI_MBIIU_CTRL);
+
+ val = sdhci_readl(host, SDHCI_MULTI_CYCLE);
+ val &= ~SDHCI_CMD_DLY_EN;
+ val |= SDHCI_EDGE_DETECT_EN | SDHCI_DATA_DLY_EN;
+ val &= ~SDHCI_DOUT_EN_F_EDGE;
+
+ sdhci_writel(host, val, SDHCI_MULTI_CYCLE);
+ host->error_count = 0;
+}
+
+static void bsp_set_drv_str(struct regmap *iocfg_regmap,
+ unsigned int offset, unsigned int pull_up,
+ unsigned int pull_down, unsigned int sr,
+ unsigned int drv_str)
+{
+ unsigned int reg = 0;
+
+ regmap_read(iocfg_regmap, offset, &reg);
+
+ reg &= ~(IO_CFG_PULL_UP | IO_CFG_PULL_DOWN |
+ IO_CFG_DRV_STR_MASK | IO_CFG_SR);
+ reg |= (pull_up ? IO_CFG_PULL_UP : 0);
+ reg |= (pull_down ? IO_CFG_PULL_DOWN : 0);
+ reg |= (sr ? IO_CFG_SR : 0);
+ reg |= io_cfg_drv_str_sel(drv_str);
+
+ regmap_write(iocfg_regmap, offset, reg);
+}
+
+static void bsp_set_emmc_ctrl(struct sdhci_host *host)
+{
+ unsigned int reg;
+
+ reg = sdhci_readl(host, SDHCI_EMMC_CTRL);
+ reg |= SDHCI_CARD_IS_EMMC;
+ sdhci_writel(host, reg, SDHCI_EMMC_CTRL);
+}
+
+
+static void bsp_set_mmc_drv(struct sdhci_host *host)
+{
+ struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host);
+ void *iocfg_regmap = bsp_priv->iocfg_regmap;
+ int i;
+
+ switch (host->timing) {
+ case MMC_TIMING_MMC_HS400:
+ bsp_set_emmc_ctrl(host);
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_CLK, 0, 1, 0, 0x3); /* set drv level 3 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_CMD, 1, 0, 0, 0x5); /* set drv level 5 */
+ for (i = 0; i < IO_CFG_EMMC_DATA_LINE_COUNT; i++)
+ bsp_set_drv_str(iocfg_regmap,
+ io_emmc_data_reg[i], 1, 0, 0, 0x5); /* set drv level 5 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_DS, 0, 1, 1, 0x3); /* set drv level 3 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_RST, 1, 0, 1, 0x3); /* set drv level 3 */
+ break;
+ case MMC_TIMING_MMC_HS200:
+ bsp_set_emmc_ctrl(host);
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_CLK, 0, 1, 0, 0x2); /* set drv level 2 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_CMD, 1, 0, 1, 0x4); /* set drv level 4 */
+ for (i = 0; i < IO_CFG_EMMC_DATA_LINE_COUNT; i++)
+ bsp_set_drv_str(iocfg_regmap,
+ io_emmc_data_reg[i], 1, 0, 1, 0x4); /* set drv level 4 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_RST, 1, 0, 1, 0x3); /* set drv level 3 */
+ break;
+ case MMC_TIMING_MMC_HS:
+ bsp_set_emmc_ctrl(host);
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_CLK, 0, 1, 1, 0x4); /* set drv level 4 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_CMD, 1, 0, 1, 0x6); /* set drv level 6 */
+ for (i = 0; i < IO_CFG_EMMC_DATA_LINE_COUNT; i++)
+ bsp_set_drv_str(iocfg_regmap,
+ io_emmc_data_reg[i], 1, 0, 1, 0x6); /* set drv level 6 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_RST, 1, 0, 1, 0x3); /* set drv level 3 */
+ break;
+ case MMC_TIMING_LEGACY:
+ case MMC_TIMING_MMC_DDR52:
+ default:
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_CLK, 0, 1, 1, 0x5); /* set drv level 5 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_CMD, 1, 0, 1, 0x6); /* set drv level 6 */
+ for (i = 0; i < IO_CFG_EMMC_DATA_LINE_COUNT; i++)
+ bsp_set_drv_str(iocfg_regmap,
+ io_emmc_data_reg[i], 1, 0, 1, 0x6); /* set drv level 6 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_RST, 1, 0, 1, 0x3); /* set drv level 3 */
+ break;
+ }
+}
+
+static void bsp_set_sd_drv(struct sdhci_host *host)
+{
+ struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host);
+ void *iocfg_regmap = bsp_priv->iocfg_regmap;
+ int i;
+
+ switch (host->timing) {
+ case MMC_TIMING_SD_HS:
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_SDIO0_CLK, 0, 1, 1, 0x5); /* set drv level 5 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_SDIO0_CMD, 1, 0, 1, 0x7); /* set drv level 7 */
+ for (i = 0; i < IO_CFG_SDIO0_DATA_LINE_COUNT; i++)
+ bsp_set_drv_str(iocfg_regmap,
+ io_sdio0_data_reg[i], 1, 0, 1, 0x7); /* set drv level 7 */
+ break;
+ case MMC_TIMING_LEGACY:
+ default:
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_SDIO0_CLK, 0, 1, 1, 0x5); /* set drv level 5 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_SDIO0_CMD, 1, 0, 1, 0x7); /* set drv level 7 */
+ for (i = 0; i < IO_CFG_SDIO0_DATA_LINE_COUNT; i++)
+ bsp_set_drv_str(iocfg_regmap,
+ io_sdio0_data_reg[i], 1, 0, 1, 0x7); /* set drv level 7 */
+ break;
+ }
+}
+
+static void bsp_set_sdio_drv(struct sdhci_host *host)
+{
+ struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host);
+ void *iocfg_regmap = bsp_priv->iocfg_regmap;
+ int i;
+
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_SDIO1_CLK, 0, 1, 1, 0x3); /* set drv level 3 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_SDIO1_CMD, 1, 0, 0, 0x6); /* set drv level 6 */
+ for (i = 0; i < IO_CFG_SDIO1_DATA_LINE_COUNT; i++)
+ bsp_set_drv_str(iocfg_regmap,
+ io_sdio1_data_reg[i], 1, 0, 0, 0x6); /* set drv level 6 */
+}
+
+static void bsp_set_io_config(struct sdhci_host *host)
+{
+ struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host);
+ unsigned int devid = bsp_priv->devid;
+ void *iocfg_regmap = bsp_priv->iocfg_regmap;
+ unsigned int reg = 0;
+
+ if (devid == 0) {
+ /* For mmc0: eMMC and SD card */
+ regmap_read(iocfg_regmap, REG_CTRL_EMMC_CLK, &reg);
+ if ((reg & IO_CFG_PIN_MUX_MASK) ==
+ io_cfg_pin_mux_sel(IO_CFG_PIN_MUX_TYPE_CLK_EMMC))
+ bsp_set_mmc_drv(host);
+
+ regmap_read(iocfg_regmap, REG_CTRL_SDIO0_CLK, &reg);
+ if ((reg & IO_CFG_PIN_MUX_MASK) ==
+ io_cfg_pin_mux_sel(IO_CFG_PIN_MUX_TYPE_CLK_SD))
+ bsp_set_sd_drv(host);
+ } else {
+ /* For mmc1: sdio wifi */
+ bsp_set_sdio_drv(host);
+ }
+}
+
+static void bsp_get_phase(struct sdhci_host *host)
+{
+ struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host);
+ unsigned int devid = bsp_priv->devid;
+
+ if (devid == 0) {
+ /* For eMMC and SD card */
+ if (host->mmc->ios.timing == MMC_TIMING_MMC_HS400) {
+ bsp_priv->drv_phase = 9; /* 9 for 101.25 degree */
+ bsp_priv->sampl_phase = bsp_priv->tuning_phase;
+ } else if (host->mmc->ios.timing == MMC_TIMING_MMC_HS200) {
+ bsp_priv->drv_phase = 23; /* 23 for 258.75 degree */
+ bsp_priv->sampl_phase = bsp_priv->tuning_phase;
+ } else if (host->mmc->ios.timing == MMC_TIMING_MMC_HS) {
+ bsp_priv->drv_phase = 16; /* 16 for 180 degree */
+ bsp_priv->sampl_phase = 4; /* 4 for 45 degree */
+ } else if (host->mmc->ios.timing == MMC_TIMING_SD_HS) {
+ bsp_priv->drv_phase = 20; /* 20 for 225 degree */
+ bsp_priv->sampl_phase = 4; /* 4 for 45 degree */
+ } else if (host->mmc->ios.timing == MMC_TIMING_LEGACY) {
+ bsp_priv->drv_phase = 16; /* 16 for 180 degree */
+ bsp_priv->sampl_phase = 0; /* 0 for 0 degree */
+ } else if (host->mmc->ios.timing == MMC_TIMING_MMC_DDR52) {
+ bsp_priv->drv_phase = 8; /* 8 for 90 degree */
+ bsp_priv->sampl_phase = bsp_priv->tuning_phase;
+ } else {
+ bsp_priv->drv_phase = 16; /* 16 for 180 degree */
+ bsp_priv->sampl_phase = 0; /* 0 for 0 degree */
+ }
+ } else {
+ /* For SDIO device */
+ if ((host->mmc->ios.timing == MMC_TIMING_SD_HS) ||
+ (host->mmc->ios.timing == MMC_TIMING_UHS_SDR25)) {
+ bsp_priv->drv_phase = 16; /* 16 for 180 degree */
+ bsp_priv->sampl_phase = 4; /* 4 for 45 degree */
+ } else {
+ /* UHS_SDR12 */
+ bsp_priv->drv_phase = 16; /* 16 for 180 degree */
+ bsp_priv->sampl_phase = 0; /* 0 for 0 degree */
+ }
+ }
+}
+
+static int bsp_support_runtime_pm(struct sdhci_host *host)
+{
+ struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host);
+ unsigned int devid = bsp_priv->devid;
+
+ /* Only enable for mmc0 eMMC and SD card */
+ if (devid == 0)
+ return 1;
+ else
+ return 0;
+}
+
+#include "sdhci-goke.c"
+#endif
\ В конце файла нет новой строки
diff -urN linux-4.9.37/drivers/mmc/host/sdhci-gk7205v200.c linux-4.9.y/drivers/mmc/host/sdhci-gk7205v200.c
--- linux-4.9.37/drivers/mmc/host/sdhci-gk7205v200.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/mmc/host/sdhci-gk7205v200.c 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,495 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/of.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <linux/reset.h>
+#include <linux/mmc/host.h>
+#include <linux/pm_runtime.h>
+#include "sdhci-pltfm.h"
+#include "sdhci-proc.h"
+
+#ifdef CONFIG_MMC_SDHCI_GOKE
+#define PHASE_SCALE 32
+#define EDGE_TUNING_PHASE_STEP 4
+#define NOT_FOUND (-1)
+#define MAX_TUNING_NUM 1
+#define MAX_FREQ 200000000
+
+#define GOKE_MMC_AUTOSUSPEND_DELAY_MS 50
+
+#define REG_EMMC_DRV_DLL_CTRL 0x1fc
+#define REG_SDIO0_DRV_DLL_CTRL 0x1fc
+#define REG_SDIO1_DRV_DLL_CTRL 0x220
+#define REG_SDIO2_DRV_DLL_CTRL /* no sdio2 */
+#define SDIO_DRV_PHASE_SEL_MASK (0x1f << 24)
+#define sdio_drv_sel(phase) ((phase) << 24)
+
+#define REG_EMMC_DRV_DLL_STATUS 0x210
+#define REG_SDIO0_DRV_DLL_STATUS 0x210
+#define REG_SDIO1_DRV_DLL_STATUS 0x228
+#define REG_SDIO2_DRV_DLL_STATUS /* no sdio2 */
+#define SDIO_DRV_DLL_LOCK BIT(15)
+#define SDIO_DRV_DLL_READY BIT(14)
+
+#define REG_EMMC_SAMPL_DLL_STATUS 0x208
+#define REG_SDIO0_SAMPL_DLL_STATUS 0x208
+#define REG_SDIO1_SAMPL_DLL_STATUS 0x224
+#define REG_SDIO2_SAMPL_DLL_STATUS /* no sdio2 */
+#define SDIO_SAMPL_DLL_SLAVE_READY BIT(0)
+
+#define REG_EMMC_SAMPL_DLL_CTRL 0x1f4
+#define REG_SDIO0_SAMPL_DLL_CTRL 0x1f4
+#define REG_SDIO1_SAMPL_DLL_CTRL 0x22c
+#define REG_SDIO2_SAMPL_DLL_CTRL /* no sdio2 */
+#define SDIO_SAMPL_DLL_SLAVE_EN BIT(16)
+
+#define REG_EMMC_SAMPLB_DLL_CTRL 0x1f8
+#define REG_SDIO0_SAMPLB_DLL_CTRL 0x1f8
+#define REG_SDIO1_SAMPLB_DLL_CTRL 0x21c
+#define REG_SDIO2_SAMPLB_DLL_CTRL /* no sdio2 */
+#define SDIO_SAMPLB_DLL_CLK_MASK (0x1f << 0)
+#define sdio_samplb_sel(phase) ((phase) << 0)
+
+#define REG_EMMC_DS_DLL_CTRL 0x200
+#define EMMC_DS_DLL_MODE_SSEL BIT(13)
+#define EMMC_DS_DLL_SSEL_MASK 0x7f
+
+#define REG_EMMC_DS180_DLL_CTRL 0x204
+#define EMMC_DS180_DLL_BYPASS BIT(15)
+#define REG_EMMC_DS180_DLL_STATUS 0x218
+#define EMMC_DS180_DLL_READY BIT(0)
+
+#define REG_EMMC_DS_DLL_STATUS 0x214
+#define EMMC_DS_DLL_READY BIT(0)
+
+#define REG_EMMC_CLK_CTRL 0x1f4
+#define REG_SDIO0_CLK_CTRL 0x1f4
+#define REG_SDIO1_CLK_CTRL 0x22c
+#define REG_SDIO2_CLK_CTRL /* no sdio2 */
+#define SDIO_CLK_DRV_DLL_RST BIT(29)
+#define SDIO_CLK_CRG_RST BIT(27)
+
+#define IO_CFG_SR BIT(10)
+#define IO_CFG_PULL_DOWN BIT(9)
+#define IO_CFG_PULL_UP BIT(8)
+#define IO_CFG_DRV_STR_MASK (0xf << 4)
+#define io_cfg_drv_str_sel(str) ((str) << 4)
+#define IO_CFG_PIN_MUX_MASK (0xf << 0)
+#define io_cfg_pin_mux_sel(type) ((type) << 0)
+#define IO_CFG_PIN_MUX_TYPE_CLK_EMMC 0x0
+#define IO_CFG_PIN_MUX_TYPE_CLK_SD 0x1
+
+#define IO_CFG_EMMC_DATA_LINE_COUNT 4
+#define REG_CTRL_EMMC_CLK 0x0014
+#define REG_CTRL_EMMC_CMD 0x0018
+#define REG_CTRL_EMMC_DATA0 0x001c
+#define REG_CTRL_EMMC_DATA1 0x0028
+#define REG_CTRL_EMMC_DATA2 0x0024
+#define REG_CTRL_EMMC_DATA3 0x0020
+
+#define REG_CTRL_EMMC_DS 0x0058
+#define REG_CTRL_EMMC_RST 0x005c
+static unsigned int io_emmc_data_reg[IO_CFG_EMMC_DATA_LINE_COUNT] = {
+ REG_CTRL_EMMC_DATA0, REG_CTRL_EMMC_DATA1,
+ REG_CTRL_EMMC_DATA2, REG_CTRL_EMMC_DATA3
+};
+
+#define IO_CFG_SDIO0_DATA_LINE_COUNT 4
+#define REG_CTRL_SDIO0_CLK 0x0040
+#define REG_CTRL_SDIO0_CMD 0x0044
+#define REG_CTRL_SDIO0_DATA0 0x0048
+#define REG_CTRL_SDIO0_DATA1 0x004C
+#define REG_CTRL_SDIO0_DATA2 0x0050
+#define REG_CTRL_SDIO0_DATA3 0x0054
+static unsigned int io_sdio0_data_reg[IO_CFG_SDIO0_DATA_LINE_COUNT] = {
+ REG_CTRL_SDIO0_DATA0, REG_CTRL_SDIO0_DATA1,
+ REG_CTRL_SDIO0_DATA2, REG_CTRL_SDIO0_DATA3
+};
+
+#define IO_CFG_SDIO1_DATA_LINE_COUNT 4
+#define REG_CTRL_SDIO1_CLK 0x0048
+#define REG_CTRL_SDIO1_CMD 0x004C
+#define REG_CTRL_SDIO1_DATA0 0x0064
+#define REG_CTRL_SDIO1_DATA1 0x0060
+#define REG_CTRL_SDIO1_DATA2 0x005C
+#define REG_CTRL_SDIO1_DATA3 0x0058
+static unsigned int io_sdio1_data_reg[IO_CFG_SDIO1_DATA_LINE_COUNT] = {
+ REG_CTRL_SDIO1_DATA0, REG_CTRL_SDIO1_DATA1,
+ REG_CTRL_SDIO1_DATA2, REG_CTRL_SDIO1_DATA3
+};
+
+struct sdhci_bsp_priv {
+ struct reset_control *crg_rst;
+ struct reset_control *dll_rst;
+ struct reset_control *sampl_rst; /* Not used */
+ struct regmap *crg_regmap;
+ struct regmap *iocfg_regmap;
+ unsigned int f_max;
+ unsigned int devid;
+ unsigned int drv_phase;
+ unsigned int sampl_phase;
+ unsigned int tuning_phase;
+};
+
+static void bsp_mmc_crg_init(struct sdhci_host *host);
+static void sdhci_bsp_hs400_enhanced_strobe(struct mmc_host *mmc, struct mmc_ios *ios);
+static int sdhci_bsp_parse_dt(struct sdhci_host *host);
+
+static inline void *sdhci_get_pltfm_priv(struct sdhci_host *host)
+{
+ return sdhci_pltfm_priv(sdhci_priv(host));
+}
+
+static void sdhci_bsp_hs400_enhanced_strobe(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+ u32 ctrl;
+ struct sdhci_host *host = mmc_priv(mmc);
+
+ ctrl = sdhci_readl(host, SDHCI_EMMC_CTRL);
+ if (ios->enhanced_strobe)
+ ctrl |= SDHCI_ENH_STROBE_EN;
+ else
+ ctrl &= ~SDHCI_ENH_STROBE_EN;
+
+ sdhci_writel(host, ctrl, SDHCI_EMMC_CTRL);
+}
+
+static int sdhci_bsp_pltfm_init(struct platform_device *pdev, struct sdhci_host *host)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_bsp_priv *bsp_priv = sdhci_pltfm_priv(pltfm_host);
+ struct device_node *np = pdev->dev.of_node;
+ struct clk *clk = NULL;
+ int ret;
+
+ bsp_priv->crg_rst = devm_reset_control_get(&pdev->dev, "crg_reset");
+ if (IS_ERR_OR_NULL(bsp_priv->crg_rst)) {
+ dev_err(&pdev->dev, "get crg_rst failed.\n");
+ return PTR_ERR(bsp_priv->crg_rst);
+ }
+
+ bsp_priv->dll_rst = devm_reset_control_get(&pdev->dev, "dll_reset");
+ if (IS_ERR_OR_NULL(bsp_priv->dll_rst)) {
+ dev_err(&pdev->dev, "get dll_rst failed.\n");
+ return PTR_ERR(bsp_priv->dll_rst);
+ }
+
+ bsp_priv->sampl_rst = NULL;
+
+ bsp_priv->crg_regmap = syscon_regmap_lookup_by_phandle(np, "crg_regmap");
+ if (IS_ERR(bsp_priv->crg_regmap)) {
+ dev_err(&pdev->dev, "get crg regmap failed.\n");
+ return PTR_ERR(bsp_priv->crg_regmap);
+ }
+
+ bsp_priv->iocfg_regmap = syscon_regmap_lookup_by_phandle(np, "iocfg_regmap");
+ if (IS_ERR(bsp_priv->iocfg_regmap)) {
+ dev_err(&pdev->dev, "get iocfg regmap failed.\n");
+ return PTR_ERR(bsp_priv->iocfg_regmap);
+ }
+
+ if (of_property_read_u32(np, "devid", &bsp_priv->devid))
+ return -EINVAL;
+
+ clk = devm_clk_get(mmc_dev(host->mmc), "mmc_clk");
+ if (IS_ERR_OR_NULL(clk)) {
+ dev_err(mmc_dev(host->mmc), "get clk err\n");
+ return -EINVAL;
+ }
+
+ pltfm_host->clk = clk;
+
+ bsp_mmc_crg_init(host);
+ ret = sdhci_bsp_parse_dt(host);
+ if (ret)
+ return ret;
+
+ /*
+ * Only eMMC has a hw reset, and now eMMC signaling
+ * is fixed to 180
+ */
+ if (host->mmc->caps & MMC_CAP_HW_RESET) {
+ host->flags &= ~SDHCI_SIGNALING_330;
+ host->flags |= SDHCI_SIGNALING_180;
+ }
+
+ /*
+ * We parse the support timings from dts, so we read the
+ * host capabilities early and clear the timing capabilities,
+ * SDHCI_QUIRK_MISSING_CAPS is set so that sdhci driver would
+ * not read it again
+ */
+ host->caps = sdhci_readl(host, SDHCI_CAPABILITIES);
+ host->caps &= ~(SDHCI_CAN_DO_HISPD | SDHCI_CAN_VDD_300);
+ host->caps1 = sdhci_readl(host, SDHCI_CAPABILITIES_1);
+ host->caps1 &= ~(SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_SDR104 |
+ SDHCI_SUPPORT_DDR50 | SDHCI_CAN_DO_ADMA3);
+ host->quirks |= SDHCI_QUIRK_MISSING_CAPS |
+ SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC |
+ SDHCI_QUIRK_SINGLE_POWER_WRITE;
+
+ host->mmc_host_ops.hs400_enhanced_strobe =
+ sdhci_bsp_hs400_enhanced_strobe;
+
+ mci_host[slot_index++] = host->mmc;
+
+ return 0;
+}
+
+static void bsp_wait_ds_dll_lock(struct sdhci_host *host)
+{
+ /* Do nothing */
+}
+
+static void bsp_wait_ds_180_dll_ready(struct sdhci_host *host)
+{
+ struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host);
+ unsigned int reg;
+ unsigned int timeout = 20;
+
+ do {
+ reg = 0;
+ regmap_read(bsp_priv->crg_regmap,
+ REG_EMMC_DS180_DLL_STATUS, &reg);
+ if (reg & EMMC_DS180_DLL_READY)
+ return;
+
+ mdelay(1);
+ timeout--;
+ } while (timeout > 0);
+
+ pr_err("%s: DS 180 DLL master not ready.\n", mmc_hostname(host->mmc));
+}
+
+static void bsp_set_ds_dll_delay(struct sdhci_host *host)
+{
+ /* Do nothing */
+}
+
+static void bsp_host_extra_init(struct sdhci_host *host)
+{
+ unsigned short ctrl;
+ unsigned int mbiiu_ctrl, val;
+
+ ctrl = sdhci_readw(host, SDHCI_MSHC_CTRL);
+ ctrl &= ~SDHCI_CMD_CONFLIT_CHECK;
+ sdhci_writew(host, ctrl, SDHCI_MSHC_CTRL);
+
+ mbiiu_ctrl = sdhci_readl(host, SDHCI_AXI_MBIIU_CTRL);
+ mbiiu_ctrl &= ~(SDHCI_GM_WR_OSRC_LMT_MASK | SDHCI_GM_RD_OSRC_LMT_MASK |
+ SDHCI_UNDEFL_INCR_EN);
+ mbiiu_ctrl |= (SDHCI_GM_WR_OSRC_LMT_SEL(0x7) | /* set write outstanding 8 (lmt + 1) */
+ SDHCI_GM_RD_OSRC_LMT_SEL(0x7)); /* set read outstanding 8 (lmt + 1) */
+ sdhci_writel(host, mbiiu_ctrl, SDHCI_AXI_MBIIU_CTRL);
+
+ val = sdhci_readl(host, SDHCI_MULTI_CYCLE);
+ val &= ~SDHCI_CMD_DLY_EN;
+ val |= SDHCI_EDGE_DETECT_EN | SDHCI_DATA_DLY_EN;
+ val &= ~SDHCI_DOUT_EN_F_EDGE;
+
+ sdhci_writel(host, val, SDHCI_MULTI_CYCLE);
+ host->error_count = 0;
+}
+
+static void bsp_set_drv_str(struct regmap *iocfg_regmap,
+ unsigned int offset, unsigned int pull_up,
+ unsigned int pull_down, unsigned int sr,
+ unsigned int drv_str)
+{
+ unsigned int reg = 0;
+
+ regmap_read(iocfg_regmap, offset, &reg);
+
+ reg &= ~(IO_CFG_PULL_UP | IO_CFG_PULL_DOWN |
+ IO_CFG_DRV_STR_MASK | IO_CFG_SR);
+ reg |= (pull_up ? IO_CFG_PULL_UP : 0);
+ reg |= (pull_down ? IO_CFG_PULL_DOWN : 0);
+ reg |= (sr ? IO_CFG_SR : 0);
+ reg |= io_cfg_drv_str_sel(drv_str);
+
+ regmap_write(iocfg_regmap, offset, reg);
+}
+
+static void bsp_set_emmc_ctrl(struct sdhci_host *host)
+{
+ unsigned int reg;
+
+ reg = sdhci_readl(host, SDHCI_EMMC_CTRL);
+ reg |= SDHCI_CARD_IS_EMMC;
+ sdhci_writel(host, reg, SDHCI_EMMC_CTRL);
+}
+
+
+static void bsp_set_mmc_drv(struct sdhci_host *host)
+{
+ struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host);
+ void *iocfg_regmap = bsp_priv->iocfg_regmap;
+ int i;
+
+ switch (host->timing) {
+ case MMC_TIMING_MMC_HS400:
+ bsp_set_emmc_ctrl(host);
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_CLK, 0, 1, 0, 0x3); /* set drv level 3 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_CMD, 1, 0, 0, 0x5); /* set drv level 5 */
+ for (i = 0; i < IO_CFG_EMMC_DATA_LINE_COUNT; i++)
+ bsp_set_drv_str(iocfg_regmap,
+ io_emmc_data_reg[i], 1, 0, 0, 0x5); /* set drv level 5 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_DS, 0, 1, 1, 0x3); /* set drv level 3 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_RST, 1, 0, 1, 0x3); /* set drv level 3 */
+ break;
+ case MMC_TIMING_MMC_HS200:
+ bsp_set_emmc_ctrl(host);
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_CLK, 0, 1, 0, 0x2); /* set drv level 2 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_CMD, 1, 0, 1, 0x4); /* set drv level 4 */
+ for (i = 0; i < IO_CFG_EMMC_DATA_LINE_COUNT; i++)
+ bsp_set_drv_str(iocfg_regmap,
+ io_emmc_data_reg[i], 1, 0, 1, 0x4); /* set drv level 4 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_RST, 1, 0, 1, 0x3); /* set drv level 3 */
+ break;
+ case MMC_TIMING_MMC_HS:
+ bsp_set_emmc_ctrl(host);
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_CLK, 0, 1, 1, 0x4); /* set drv level 4 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_CMD, 1, 0, 1, 0x6); /* set drv level 6 */
+ for (i = 0; i < IO_CFG_EMMC_DATA_LINE_COUNT; i++)
+ bsp_set_drv_str(iocfg_regmap,
+ io_emmc_data_reg[i], 1, 0, 1, 0x6); /* set drv level 6 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_RST, 1, 0, 1, 0x3); /* set drv level 3 */
+ break;
+ case MMC_TIMING_LEGACY:
+ case MMC_TIMING_MMC_DDR52:
+ default:
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_CLK, 0, 1, 1, 0x5); /* set drv level 5 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_CMD, 1, 0, 1, 0x6); /* set drv level 6 */
+ for (i = 0; i < IO_CFG_EMMC_DATA_LINE_COUNT; i++)
+ bsp_set_drv_str(iocfg_regmap,
+ io_emmc_data_reg[i], 1, 0, 1, 0x6); /* set drv level 6 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_RST, 1, 0, 1, 0x3); /* set drv level 3 */
+ break;
+ }
+}
+
+static void bsp_set_sd_drv(struct sdhci_host *host)
+{
+ struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host);
+ void *iocfg_regmap = bsp_priv->iocfg_regmap;
+ int i;
+
+ switch (host->timing) {
+ case MMC_TIMING_SD_HS:
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_SDIO0_CLK, 0, 1, 1, 0x5); /* set drv level 5 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_SDIO0_CMD, 1, 0, 1, 0x7); /* set drv level 7 */
+ for (i = 0; i < IO_CFG_SDIO0_DATA_LINE_COUNT; i++)
+ bsp_set_drv_str(iocfg_regmap,
+ io_sdio0_data_reg[i], 1, 0, 1, 0x7); /* set drv level 7 */
+ break;
+ case MMC_TIMING_LEGACY:
+ default:
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_SDIO0_CLK, 0, 1, 1, 0x5); /* set drv level 5 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_SDIO0_CMD, 1, 0, 1, 0x7); /* set drv level 7 */
+ for (i = 0; i < IO_CFG_SDIO0_DATA_LINE_COUNT; i++)
+ bsp_set_drv_str(iocfg_regmap,
+ io_sdio0_data_reg[i], 1, 0, 1, 0x7); /* set drv level 7 */
+ break;
+ }
+}
+
+static void bsp_set_sdio_drv(struct sdhci_host *host)
+{
+ struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host);
+ void *iocfg_regmap = bsp_priv->iocfg_regmap;
+ int i;
+
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_SDIO1_CLK, 0, 1, 1, 0x4); /* set drv level 4 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_SDIO1_CMD, 1, 0, 0, 0x7); /* set drv level 7 */
+ for (i = 0; i < IO_CFG_SDIO1_DATA_LINE_COUNT; i++)
+ bsp_set_drv_str(iocfg_regmap,
+ io_sdio1_data_reg[i], 1, 0, 0, 0x7); /* set drv level 7 */
+}
+
+static void bsp_set_io_config(struct sdhci_host *host)
+{
+ struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host);
+ unsigned int devid = bsp_priv->devid;
+ void *iocfg_regmap = bsp_priv->iocfg_regmap;
+ unsigned int reg = 0;
+
+ if (devid == 0) {
+ /* For mmc0: eMMC and SD card */
+ regmap_read(iocfg_regmap, REG_CTRL_EMMC_CLK, &reg);
+ if ((reg & IO_CFG_PIN_MUX_MASK) ==
+ io_cfg_pin_mux_sel(IO_CFG_PIN_MUX_TYPE_CLK_EMMC))
+ bsp_set_mmc_drv(host);
+
+ regmap_read(iocfg_regmap, REG_CTRL_SDIO0_CLK, &reg);
+ if ((reg & IO_CFG_PIN_MUX_MASK) ==
+ io_cfg_pin_mux_sel(IO_CFG_PIN_MUX_TYPE_CLK_SD))
+ bsp_set_sd_drv(host);
+ } else {
+ /* For mmc1: sdio wifi */
+ bsp_set_sdio_drv(host);
+ }
+}
+
+static void bsp_get_phase(struct sdhci_host *host)
+{
+ struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host);
+ unsigned int devid = bsp_priv->devid;
+
+ if (devid == 0) {
+ /* For eMMC and SD card */
+ if (host->mmc->ios.timing == MMC_TIMING_MMC_HS400) {
+ bsp_priv->drv_phase = 9; /* 9 for 101.25 degree */
+ bsp_priv->sampl_phase = bsp_priv->tuning_phase;
+ } else if (host->mmc->ios.timing == MMC_TIMING_MMC_HS200) {
+ bsp_priv->drv_phase = 23; /* 23 for 258.75 degree */
+ bsp_priv->sampl_phase = bsp_priv->tuning_phase;
+ } else if (host->mmc->ios.timing == MMC_TIMING_MMC_HS) {
+ bsp_priv->drv_phase = 16; /* 16 for 180 degree */
+ bsp_priv->sampl_phase = 4; /* 4 for 45 degree */
+ } else if (host->mmc->ios.timing == MMC_TIMING_SD_HS) {
+ bsp_priv->drv_phase = 20; /* 20 for 225 degree */
+ bsp_priv->sampl_phase = 4; /* 4 for 45 degree */
+ } else if (host->mmc->ios.timing == MMC_TIMING_LEGACY) {
+ bsp_priv->drv_phase = 16; /* 16 for 180 degree */
+ bsp_priv->sampl_phase = 0; /* 0 for 0 degree */
+ } else if (host->mmc->ios.timing == MMC_TIMING_MMC_DDR52) {
+ bsp_priv->drv_phase = 8; /* 8 for 90 degree */
+ bsp_priv->sampl_phase = bsp_priv->tuning_phase;
+ } else {
+ bsp_priv->drv_phase = 16; /* 16 for 180 degree */
+ bsp_priv->sampl_phase = 0; /* 0 for 0 degree */
+ }
+ } else {
+ /* For SDIO device */
+ if ((host->mmc->ios.timing == MMC_TIMING_SD_HS) ||
+ (host->mmc->ios.timing == MMC_TIMING_UHS_SDR25)) {
+ bsp_priv->drv_phase = 16; /* 16 for 180 degree */
+ bsp_priv->sampl_phase = 4; /* 4 for 45 degree */
+ } else {
+ /* UHS_SDR12 */
+ bsp_priv->drv_phase = 16; /* 16 for 180 degree */
+ bsp_priv->sampl_phase = 0; /* 0 for 0 degree */
+ }
+ }
+}
+
+static int bsp_support_runtime_pm(struct sdhci_host *host)
+{
+ struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host);
+ unsigned int devid = bsp_priv->devid;
+
+ /* Only enable for mmc0 eMMC and SD card */
+ if (devid == 0)
+ return 1;
+ else
+ return 0;
+}
+
+#include "sdhci-goke.c"
+#endif
\ В конце файла нет новой строки
diff -urN linux-4.9.37/drivers/mmc/host/sdhci-gk7205v300.c linux-4.9.y/drivers/mmc/host/sdhci-gk7205v300.c
--- linux-4.9.37/drivers/mmc/host/sdhci-gk7205v300.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/mmc/host/sdhci-gk7205v300.c 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,508 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/of.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <linux/reset.h>
+#include <linux/mmc/host.h>
+#include <linux/pm_runtime.h>
+#include "sdhci-pltfm.h"
+#include "sdhci-proc.h"
+
+#ifdef CONFIG_MMC_SDHCI_GOKE
+#define PHASE_SCALE 32
+#define EDGE_TUNING_PHASE_STEP 4
+#define NOT_FOUND (-1)
+#define MAX_TUNING_NUM 1
+#define MAX_FREQ 200000000
+
+#define GOKE_MMC_AUTOSUSPEND_DELAY_MS 50
+
+#define REG_EMMC_DRV_DLL_CTRL 0x1fc
+#define REG_SDIO0_DRV_DLL_CTRL 0x1fc
+#define REG_SDIO1_DRV_DLL_CTRL 0x220
+#define REG_SDIO2_DRV_DLL_CTRL /* no sdio2 */
+#define SDIO_DRV_PHASE_SEL_MASK (0x1f << 24)
+#define sdio_drv_sel(phase) ((phase) << 24)
+
+#define REG_EMMC_DRV_DLL_STATUS 0x210
+#define REG_SDIO0_DRV_DLL_STATUS 0x210
+#define REG_SDIO1_DRV_DLL_STATUS 0x228
+#define REG_SDIO2_DRV_DLL_STATUS /* no sdio2 */
+#define SDIO_DRV_DLL_LOCK BIT(15)
+#define SDIO_DRV_DLL_READY BIT(14)
+
+#define REG_EMMC_SAMPL_DLL_STATUS 0x208
+#define REG_SDIO0_SAMPL_DLL_STATUS 0x208
+#define REG_SDIO1_SAMPL_DLL_STATUS 0x224
+#define REG_SDIO2_SAMPL_DLL_STATUS /* no sdio2 */
+#define SDIO_SAMPL_DLL_SLAVE_READY BIT(0)
+
+#define REG_EMMC_SAMPL_DLL_CTRL 0x1f4
+#define REG_SDIO0_SAMPL_DLL_CTRL 0x1f4
+#define REG_SDIO1_SAMPL_DLL_CTRL 0x22c
+#define REG_SDIO2_SAMPL_DLL_CTRL /* no sdio2 */
+#define SDIO_SAMPL_DLL_SLAVE_EN BIT(16)
+
+#define REG_EMMC_SAMPLB_DLL_CTRL 0x1f8
+#define REG_SDIO0_SAMPLB_DLL_CTRL 0x1f8
+#define REG_SDIO1_SAMPLB_DLL_CTRL 0x21c
+#define REG_SDIO2_SAMPLB_DLL_CTRL /* no sdio2 */
+#define SDIO_SAMPLB_DLL_CLK_MASK (0x1f << 0)
+#define sdio_samplb_sel(phase) ((phase) << 0)
+
+#define REG_EMMC_DS_DLL_CTRL 0x200
+#define EMMC_DS_DLL_MODE_SSEL BIT(13)
+#define EMMC_DS_DLL_SSEL_MASK 0x7f
+
+#define REG_EMMC_DS180_DLL_CTRL 0x204
+#define EMMC_DS180_DLL_BYPASS BIT(15)
+#define REG_EMMC_DS180_DLL_STATUS 0x218
+#define EMMC_DS180_DLL_READY BIT(0)
+
+#define REG_EMMC_DS_DLL_STATUS 0x214
+#define EMMC_DS_DLL_READY BIT(0)
+
+#define REG_EMMC_CLK_CTRL 0x1f4
+#define REG_SDIO0_CLK_CTRL 0x1f4
+#define REG_SDIO1_CLK_CTRL 0x22c
+#define REG_SDIO2_CLK_CTRL /* no sdio2 */
+#define SDIO_CLK_DRV_DLL_RST BIT(29)
+#define SDIO_CLK_CRG_RST BIT(27)
+
+#define IO_CFG_SR BIT(10)
+#define IO_CFG_PULL_DOWN BIT(9)
+#define IO_CFG_PULL_UP BIT(8)
+#define IO_CFG_DRV_STR_MASK (0xf << 4)
+#define io_cfg_drv_str_sel(str) ((str) << 4)
+#define IO_CFG_PIN_MUX_MASK (0xf << 0)
+#define io_cfg_pin_mux_sel(type) ((type) << 0)
+#define IO_CFG_PIN_MUX_TYPE_CLK_EMMC 0x0
+#define IO_CFG_PIN_MUX_TYPE_CLK_SD 0x1
+
+#define IO_CFG_EMMC_DATA_LINE_COUNT 8
+#define REG_CTRL_EMMC_CLK 0x0014
+#define REG_CTRL_EMMC_CMD 0x0018
+#define REG_CTRL_EMMC_DATA0 0x001c
+#define REG_CTRL_EMMC_DATA1 0x0028
+#define REG_CTRL_EMMC_DATA2 0x0024
+#define REG_CTRL_EMMC_DATA3 0x0020
+#define REG_CTRL_EMMC_DATA4 0x0030
+#define REG_CTRL_EMMC_DATA5 0x0034
+#define REG_CTRL_EMMC_DATA6 0x0038
+#define REG_CTRL_EMMC_DATA7 0x003c
+#define REG_CTRL_EMMC_DS 0x0058
+#define REG_CTRL_EMMC_RST 0x005c
+static unsigned int io_emmc_data_reg[IO_CFG_EMMC_DATA_LINE_COUNT] = {
+ REG_CTRL_EMMC_DATA0, REG_CTRL_EMMC_DATA1,
+ REG_CTRL_EMMC_DATA2, REG_CTRL_EMMC_DATA3,
+ REG_CTRL_EMMC_DATA4, REG_CTRL_EMMC_DATA5,
+ REG_CTRL_EMMC_DATA6, REG_CTRL_EMMC_DATA7
+};
+
+#define IO_CFG_SDIO0_DATA_LINE_COUNT 4
+#define REG_CTRL_SDIO0_CLK 0x0040
+#define REG_CTRL_SDIO0_CMD 0x0044
+#define REG_CTRL_SDIO0_DATA0 0x0048
+#define REG_CTRL_SDIO0_DATA1 0x004C
+#define REG_CTRL_SDIO0_DATA2 0x0050
+#define REG_CTRL_SDIO0_DATA3 0x0054
+static unsigned int io_sdio0_data_reg[IO_CFG_SDIO0_DATA_LINE_COUNT] = {
+ REG_CTRL_SDIO0_DATA0, REG_CTRL_SDIO0_DATA1,
+ REG_CTRL_SDIO0_DATA2, REG_CTRL_SDIO0_DATA3
+};
+
+#define IO_CFG_SDIO1_DATA_LINE_COUNT 4
+#define REG_CTRL_SDIO1_CLK 0x0060
+#define REG_CTRL_SDIO1_CMD 0x0064
+#define REG_CTRL_SDIO1_DATA0 0x0068
+#define REG_CTRL_SDIO1_DATA1 0x006C
+#define REG_CTRL_SDIO1_DATA2 0x0070
+#define REG_CTRL_SDIO1_DATA3 0x0074
+static unsigned int io_sdio1_data_reg[IO_CFG_SDIO1_DATA_LINE_COUNT] = {
+ REG_CTRL_SDIO1_DATA0, REG_CTRL_SDIO1_DATA1,
+ REG_CTRL_SDIO1_DATA2, REG_CTRL_SDIO1_DATA3
+};
+
+struct sdhci_bsp_priv {
+ struct reset_control *crg_rst;
+ struct reset_control *dll_rst;
+ struct reset_control *sampl_rst; /* Not used */
+ struct regmap *crg_regmap;
+ struct regmap *iocfg_regmap;
+ unsigned int f_max;
+ unsigned int devid;
+ unsigned int drv_phase;
+ unsigned int sampl_phase;
+ unsigned int tuning_phase;
+};
+
+static void bsp_mmc_crg_init(struct sdhci_host *host);
+static void sdhci_bsp_hs400_enhanced_strobe(struct mmc_host *mmc, struct mmc_ios *ios);
+static int sdhci_bsp_parse_dt(struct sdhci_host *host);
+
+static inline void *sdhci_get_pltfm_priv(struct sdhci_host *host)
+{
+ return sdhci_pltfm_priv(sdhci_priv(host));
+}
+
+static void sdhci_bsp_hs400_enhanced_strobe(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+ u32 ctrl;
+ struct sdhci_host *host = mmc_priv(mmc);
+
+ ctrl = sdhci_readl(host, SDHCI_EMMC_CTRL);
+ if (ios->enhanced_strobe)
+ ctrl |= SDHCI_ENH_STROBE_EN;
+ else
+ ctrl &= ~SDHCI_ENH_STROBE_EN;
+
+ sdhci_writel(host, ctrl, SDHCI_EMMC_CTRL);
+
+ ctrl = sdhci_readl(host, SDHCI_MULTI_CYCLE);
+ if (ios->enhanced_strobe)
+ ctrl |= SDHCI_CMD_DLY_EN;
+ else
+ ctrl &= ~SDHCI_CMD_DLY_EN;
+
+ sdhci_writel(host, ctrl, SDHCI_MULTI_CYCLE);
+}
+
+static int sdhci_bsp_pltfm_init(struct platform_device *pdev, struct sdhci_host *host)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_bsp_priv *bsp_priv = sdhci_pltfm_priv(pltfm_host);
+ struct device_node *np = pdev->dev.of_node;
+ struct clk *clk = NULL;
+ int ret;
+
+ bsp_priv->crg_rst = devm_reset_control_get(&pdev->dev, "crg_reset");
+ if (IS_ERR_OR_NULL(bsp_priv->crg_rst)) {
+ dev_err(&pdev->dev, "get crg_rst failed.\n");
+ return PTR_ERR(bsp_priv->crg_rst);
+ }
+
+ bsp_priv->dll_rst = devm_reset_control_get(&pdev->dev, "dll_reset");
+ if (IS_ERR_OR_NULL(bsp_priv->dll_rst)) {
+ dev_err(&pdev->dev, "get dll_rst failed.\n");
+ return PTR_ERR(bsp_priv->dll_rst);
+ }
+
+ bsp_priv->sampl_rst = NULL;
+
+ bsp_priv->crg_regmap = syscon_regmap_lookup_by_phandle(np, "crg_regmap");
+ if (IS_ERR(bsp_priv->crg_regmap)) {
+ dev_err(&pdev->dev, "get crg regmap failed.\n");
+ return PTR_ERR(bsp_priv->crg_regmap);
+ }
+
+ bsp_priv->iocfg_regmap = syscon_regmap_lookup_by_phandle(np, "iocfg_regmap");
+ if (IS_ERR(bsp_priv->iocfg_regmap)) {
+ dev_err(&pdev->dev, "get iocfg regmap failed.\n");
+ return PTR_ERR(bsp_priv->iocfg_regmap);
+ }
+
+ if (of_property_read_u32(np, "devid", &bsp_priv->devid))
+ return -EINVAL;
+
+ clk = devm_clk_get(mmc_dev(host->mmc), "mmc_clk");
+ if (IS_ERR_OR_NULL(clk)) {
+ dev_err(mmc_dev(host->mmc), "get clk err\n");
+ return -EINVAL;
+ }
+
+ pltfm_host->clk = clk;
+
+ bsp_mmc_crg_init(host);
+ ret = sdhci_bsp_parse_dt(host);
+ if (ret)
+ return ret;
+
+ /*
+ * Only eMMC has a hw reset, and now eMMC signaling
+ * is fixed to 180
+ */
+ if (host->mmc->caps & MMC_CAP_HW_RESET) {
+ host->flags &= ~SDHCI_SIGNALING_330;
+ host->flags |= SDHCI_SIGNALING_180;
+ }
+
+ /*
+ * We parse the support timings from dts, so we read the
+ * host capabilities early and clear the timing capabilities,
+ * SDHCI_QUIRK_MISSING_CAPS is set so that sdhci driver would
+ * not read it again
+ */
+ host->caps = sdhci_readl(host, SDHCI_CAPABILITIES);
+ host->caps &= ~(SDHCI_CAN_DO_HISPD | SDHCI_CAN_VDD_300);
+ host->caps1 = sdhci_readl(host, SDHCI_CAPABILITIES_1);
+ host->caps1 &= ~(SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_SDR104 |
+ SDHCI_SUPPORT_DDR50 | SDHCI_CAN_DO_ADMA3);
+ host->quirks |= SDHCI_QUIRK_MISSING_CAPS |
+ SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC |
+ SDHCI_QUIRK_SINGLE_POWER_WRITE;
+
+ host->mmc_host_ops.hs400_enhanced_strobe =
+ sdhci_bsp_hs400_enhanced_strobe;
+
+ mci_host[slot_index++] = host->mmc;
+
+ return 0;
+}
+
+static void bsp_wait_ds_dll_lock(struct sdhci_host *host)
+{
+ /* Do nothing */
+}
+
+static void bsp_wait_ds_180_dll_ready(struct sdhci_host *host)
+{
+ struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host);
+ unsigned int reg;
+ unsigned int timeout = 20;
+
+ do {
+ reg = 0;
+ regmap_read(bsp_priv->crg_regmap,
+ REG_EMMC_DS180_DLL_STATUS, &reg);
+ if (reg & EMMC_DS180_DLL_READY)
+ return;
+
+ mdelay(1);
+ timeout--;
+ } while (timeout > 0);
+
+ pr_err("%s: DS 180 DLL master not ready.\n", mmc_hostname(host->mmc));
+}
+
+static void bsp_set_ds_dll_delay(struct sdhci_host *host)
+{
+ /* Do nothing */
+}
+
+static void bsp_host_extra_init(struct sdhci_host *host)
+{
+ unsigned short ctrl;
+ unsigned int mbiiu_ctrl, val;
+
+ ctrl = sdhci_readw(host, SDHCI_MSHC_CTRL);
+ ctrl &= ~SDHCI_CMD_CONFLIT_CHECK;
+ sdhci_writew(host, ctrl, SDHCI_MSHC_CTRL);
+
+ mbiiu_ctrl = sdhci_readl(host, SDHCI_AXI_MBIIU_CTRL);
+ mbiiu_ctrl &= ~(SDHCI_GM_WR_OSRC_LMT_MASK | SDHCI_GM_RD_OSRC_LMT_MASK |
+ SDHCI_UNDEFL_INCR_EN);
+ mbiiu_ctrl |= (SDHCI_GM_WR_OSRC_LMT_SEL(0x7) | /* set write outstanding 8 (lmt + 1) */
+ SDHCI_GM_RD_OSRC_LMT_SEL(0x7)); /* set read outstanding 8 (lmt + 1) */
+ sdhci_writel(host, mbiiu_ctrl, SDHCI_AXI_MBIIU_CTRL);
+
+ val = sdhci_readl(host, SDHCI_MULTI_CYCLE);
+ val &= ~SDHCI_CMD_DLY_EN;
+ val |= SDHCI_EDGE_DETECT_EN | SDHCI_DATA_DLY_EN;
+ val &= ~SDHCI_DOUT_EN_F_EDGE;
+
+ sdhci_writel(host, val, SDHCI_MULTI_CYCLE);
+ host->error_count = 0;
+}
+
+static void bsp_set_drv_str(struct regmap *iocfg_regmap,
+ unsigned int offset, unsigned int pull_up,
+ unsigned int pull_down, unsigned int sr,
+ unsigned int drv_str)
+{
+ unsigned int reg = 0;
+
+ regmap_read(iocfg_regmap, offset, &reg);
+
+ reg &= ~(IO_CFG_PULL_UP | IO_CFG_PULL_DOWN |
+ IO_CFG_DRV_STR_MASK | IO_CFG_SR);
+ reg |= (pull_up ? IO_CFG_PULL_UP : 0);
+ reg |= (pull_down ? IO_CFG_PULL_DOWN : 0);
+ reg |= (sr ? IO_CFG_SR : 0);
+ reg |= io_cfg_drv_str_sel(drv_str);
+
+ regmap_write(iocfg_regmap, offset, reg);
+}
+
+static void bsp_set_emmc_ctrl(struct sdhci_host *host)
+{
+ unsigned int reg;
+
+ reg = sdhci_readl(host, SDHCI_EMMC_CTRL);
+ reg |= SDHCI_CARD_IS_EMMC;
+ sdhci_writel(host, reg, SDHCI_EMMC_CTRL);
+}
+
+
+static void bsp_set_mmc_drv(struct sdhci_host *host)
+{
+ struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host);
+ void *iocfg_regmap = bsp_priv->iocfg_regmap;
+ int i;
+
+ switch (host->timing) {
+ case MMC_TIMING_MMC_HS400:
+ bsp_set_emmc_ctrl(host);
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_CLK, 0, 1, 0, 0x3); /* set drv level 3 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_CMD, 1, 0, 0, 0x5); /* set drv level 5 */
+ for (i = 0; i < IO_CFG_EMMC_DATA_LINE_COUNT; i++)
+ bsp_set_drv_str(iocfg_regmap,
+ io_emmc_data_reg[i], 1, 0, 0, 0x5); /* set drv level 5 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_DS, 0, 1, 1, 0x3); /* set drv level 3 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_RST, 1, 0, 1, 0x3); /* set drv level 3 */
+ break;
+ case MMC_TIMING_MMC_HS200:
+ bsp_set_emmc_ctrl(host);
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_CLK, 0, 1, 0, 0x2); /* set drv level 2 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_CMD, 1, 0, 1, 0x4); /* set drv level 4 */
+ for (i = 0; i < IO_CFG_EMMC_DATA_LINE_COUNT; i++)
+ bsp_set_drv_str(iocfg_regmap,
+ io_emmc_data_reg[i], 1, 0, 1, 0x4); /* set drv level 4 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_RST, 1, 0, 1, 0x3); /* set drv level 3 */
+ break;
+ case MMC_TIMING_MMC_HS:
+ bsp_set_emmc_ctrl(host);
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_CLK, 0, 1, 1, 0x4); /* set drv level 4 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_CMD, 1, 0, 1, 0x6); /* set drv level 6 */
+ for (i = 0; i < IO_CFG_EMMC_DATA_LINE_COUNT; i++)
+ bsp_set_drv_str(iocfg_regmap,
+ io_emmc_data_reg[i], 1, 0, 1, 0x6); /* set drv level 6 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_RST, 1, 0, 1, 0x3); /* set drv level 3 */
+ break;
+ case MMC_TIMING_LEGACY:
+ case MMC_TIMING_MMC_DDR52:
+ default:
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_CLK, 0, 1, 1, 0x5); /* set drv level 5 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_CMD, 1, 0, 1, 0x6); /* set drv level 6 */
+ for (i = 0; i < IO_CFG_EMMC_DATA_LINE_COUNT; i++)
+ bsp_set_drv_str(iocfg_regmap,
+ io_emmc_data_reg[i], 1, 0, 1, 0x6); /* set drv level 6 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_RST, 1, 0, 1, 0x3); /* set drv level 3 */
+ break;
+ }
+}
+
+static void bsp_set_sd_drv(struct sdhci_host *host)
+{
+ struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host);
+ void *iocfg_regmap = bsp_priv->iocfg_regmap;
+ int i;
+
+ switch (host->timing) {
+ case MMC_TIMING_SD_HS:
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_SDIO0_CLK, 0, 1, 1, 0x5); /* set drv level 5 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_SDIO0_CMD, 1, 0, 1, 0x7); /* set drv level 7 */
+ for (i = 0; i < IO_CFG_SDIO0_DATA_LINE_COUNT; i++)
+ bsp_set_drv_str(iocfg_regmap,
+ io_sdio0_data_reg[i], 1, 0, 1, 0x7); /* set drv level 7 */
+ break;
+ case MMC_TIMING_LEGACY:
+ default:
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_SDIO0_CLK, 0, 1, 1, 0x5); /* set drv level 5 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_SDIO0_CMD, 1, 0, 1, 0x7); /* set drv level 7 */
+ for (i = 0; i < IO_CFG_SDIO0_DATA_LINE_COUNT; i++)
+ bsp_set_drv_str(iocfg_regmap,
+ io_sdio0_data_reg[i], 1, 0, 1, 0x7); /* set drv level 7 */
+ break;
+ }
+}
+
+static void bsp_set_sdio_drv(struct sdhci_host *host)
+{
+ struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host);
+ void *iocfg_regmap = bsp_priv->iocfg_regmap;
+ int i;
+
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_SDIO1_CLK, 0, 1, 1, 0x5); /* set drv level 5 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_SDIO1_CMD, 1, 0, 0, 0x7); /* set drv level 7 */
+ for (i = 0; i < IO_CFG_SDIO1_DATA_LINE_COUNT; i++)
+ bsp_set_drv_str(iocfg_regmap,
+ io_sdio1_data_reg[i], 1, 0, 0, 0x7); /* set drv level 7 */
+}
+
+static void bsp_set_io_config(struct sdhci_host *host)
+{
+ struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host);
+ unsigned int devid = bsp_priv->devid;
+ void *iocfg_regmap = bsp_priv->iocfg_regmap;
+ unsigned int reg = 0;
+
+ if (devid == 0) {
+ /* For mmc0: eMMC and SD card */
+ regmap_read(iocfg_regmap, REG_CTRL_EMMC_CLK, &reg);
+ if ((reg & IO_CFG_PIN_MUX_MASK) ==
+ io_cfg_pin_mux_sel(IO_CFG_PIN_MUX_TYPE_CLK_EMMC))
+ bsp_set_mmc_drv(host);
+
+ regmap_read(iocfg_regmap, REG_CTRL_SDIO0_CLK, &reg);
+ if ((reg & IO_CFG_PIN_MUX_MASK) ==
+ io_cfg_pin_mux_sel(IO_CFG_PIN_MUX_TYPE_CLK_SD))
+ bsp_set_sd_drv(host);
+ } else {
+ /* For mmc1: sdio wifi */
+ bsp_set_sdio_drv(host);
+ }
+}
+
+static void bsp_get_phase(struct sdhci_host *host)
+{
+ struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host);
+ unsigned int devid = bsp_priv->devid;
+
+ if (devid == 0) {
+ /* For eMMC and SD card */
+ if (host->mmc->ios.timing == MMC_TIMING_MMC_HS400) {
+ bsp_priv->drv_phase = 9; /* 9 for 101.25 degree */
+ bsp_priv->sampl_phase = bsp_priv->tuning_phase;
+ } else if (host->mmc->ios.timing == MMC_TIMING_MMC_HS200) {
+ bsp_priv->drv_phase = 23; /* 23 for 258.75 degree */
+ bsp_priv->sampl_phase = bsp_priv->tuning_phase;
+ } else if (host->mmc->ios.timing == MMC_TIMING_MMC_HS) {
+ bsp_priv->drv_phase = 16; /* 16 for 180 degree */
+ bsp_priv->sampl_phase = 4; /* 4 for 45 degree */
+ } else if (host->mmc->ios.timing == MMC_TIMING_SD_HS) {
+ bsp_priv->drv_phase = 20; /* 20 for 225 degree */
+ bsp_priv->sampl_phase = 4; /* 4 for 45 degree */
+ } else if (host->mmc->ios.timing == MMC_TIMING_LEGACY) {
+ bsp_priv->drv_phase = 16; /* 16 for 180 degree */
+ bsp_priv->sampl_phase = 0; /* 0 for 0 degree */
+ } else if (host->mmc->ios.timing == MMC_TIMING_MMC_DDR52) {
+ bsp_priv->drv_phase = 8; /* 8 for 90 degree */
+ bsp_priv->sampl_phase = bsp_priv->tuning_phase;
+ } else {
+ bsp_priv->drv_phase = 16; /* 16 for 180 degree */
+ bsp_priv->sampl_phase = 0; /* 0 for 0 degree */
+ }
+ } else {
+ /* For SDIO device */
+ if ((host->mmc->ios.timing == MMC_TIMING_SD_HS) ||
+ (host->mmc->ios.timing == MMC_TIMING_UHS_SDR25)) {
+ bsp_priv->drv_phase = 16; /* 16 for 180 degree */
+ bsp_priv->sampl_phase = 4; /* 4 for 45 degree */
+ } else {
+ /* UHS_SDR12 */
+ bsp_priv->drv_phase = 16; /* 16 for 180 degree */
+ bsp_priv->sampl_phase = 0; /* 0 for 0 degree */
+ }
+ }
+}
+
+static int bsp_support_runtime_pm(struct sdhci_host *host)
+{
+ struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host);
+ unsigned int devid = bsp_priv->devid;
+
+ /* Only enable for mmc0 eMMC and SD card */
+ if (devid == 0)
+ return 1;
+ else
+ return 0;
+}
+
+#include "sdhci-goke.c"
+#endif
\ В конце файла нет новой строки
diff -urN linux-4.9.37/drivers/mmc/host/sdhci-gk7605v100.c linux-4.9.y/drivers/mmc/host/sdhci-gk7605v100.c
--- linux-4.9.37/drivers/mmc/host/sdhci-gk7605v100.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/mmc/host/sdhci-gk7605v100.c 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,508 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/of.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <linux/reset.h>
+#include <linux/mmc/host.h>
+#include <linux/pm_runtime.h>
+#include "sdhci-pltfm.h"
+#include "sdhci-proc.h"
+
+#ifdef CONFIG_MMC_SDHCI_GOKE
+#define PHASE_SCALE 32
+#define EDGE_TUNING_PHASE_STEP 4
+#define NOT_FOUND (-1)
+#define MAX_TUNING_NUM 1
+#define MAX_FREQ 200000000
+
+#define GOKE_MMC_AUTOSUSPEND_DELAY_MS 50
+
+#define REG_EMMC_DRV_DLL_CTRL 0x1fc
+#define REG_SDIO0_DRV_DLL_CTRL 0x1fc
+#define REG_SDIO1_DRV_DLL_CTRL 0x220
+#define REG_SDIO2_DRV_DLL_CTRL /* no sdio2 */
+#define SDIO_DRV_PHASE_SEL_MASK (0x1f << 24)
+#define sdio_drv_sel(phase) ((phase) << 24)
+
+#define REG_EMMC_DRV_DLL_STATUS 0x210
+#define REG_SDIO0_DRV_DLL_STATUS 0x210
+#define REG_SDIO1_DRV_DLL_STATUS 0x228
+#define REG_SDIO2_DRV_DLL_STATUS /* no sdio2 */
+#define SDIO_DRV_DLL_LOCK BIT(15)
+#define SDIO_DRV_DLL_READY BIT(14)
+
+#define REG_EMMC_SAMPL_DLL_STATUS 0x208
+#define REG_SDIO0_SAMPL_DLL_STATUS 0x208
+#define REG_SDIO1_SAMPL_DLL_STATUS 0x224
+#define REG_SDIO2_SAMPL_DLL_STATUS /* no sdio2 */
+#define SDIO_SAMPL_DLL_SLAVE_READY BIT(0)
+
+#define REG_EMMC_SAMPL_DLL_CTRL 0x1f4
+#define REG_SDIO0_SAMPL_DLL_CTRL 0x1f4
+#define REG_SDIO1_SAMPL_DLL_CTRL 0x22c
+#define REG_SDIO2_SAMPL_DLL_CTRL /* no sdio2 */
+#define SDIO_SAMPL_DLL_SLAVE_EN BIT(16)
+
+#define REG_EMMC_SAMPLB_DLL_CTRL 0x1f8
+#define REG_SDIO0_SAMPLB_DLL_CTRL 0x1f8
+#define REG_SDIO1_SAMPLB_DLL_CTRL 0x21c
+#define REG_SDIO2_SAMPLB_DLL_CTRL /* no sdio2 */
+#define SDIO_SAMPLB_DLL_CLK_MASK (0x1f << 0)
+#define sdio_samplb_sel(phase) ((phase) << 0)
+
+#define REG_EMMC_DS_DLL_CTRL 0x200
+#define EMMC_DS_DLL_MODE_SSEL BIT(13)
+#define EMMC_DS_DLL_SSEL_MASK 0x7f
+
+#define REG_EMMC_DS180_DLL_CTRL 0x204
+#define EMMC_DS180_DLL_BYPASS BIT(15)
+#define REG_EMMC_DS180_DLL_STATUS 0x218
+#define EMMC_DS180_DLL_READY BIT(0)
+
+#define REG_EMMC_DS_DLL_STATUS 0x214
+#define EMMC_DS_DLL_READY BIT(0)
+
+#define REG_EMMC_CLK_CTRL 0x1f4
+#define REG_SDIO0_CLK_CTRL 0x1f4
+#define REG_SDIO1_CLK_CTRL 0x22c
+#define REG_SDIO2_CLK_CTRL /* no sdio2 */
+#define SDIO_CLK_DRV_DLL_RST BIT(29)
+#define SDIO_CLK_CRG_RST BIT(27)
+
+#define IO_CFG_SR BIT(10)
+#define IO_CFG_PULL_DOWN BIT(9)
+#define IO_CFG_PULL_UP BIT(8)
+#define IO_CFG_DRV_STR_MASK (0xf << 4)
+#define io_cfg_drv_str_sel(str) ((str) << 4)
+#define IO_CFG_PIN_MUX_MASK (0xf << 0)
+#define io_cfg_pin_mux_sel(type) ((type) << 0)
+#define IO_CFG_PIN_MUX_TYPE_CLK_EMMC 0x0
+#define IO_CFG_PIN_MUX_TYPE_CLK_SD 0x1
+
+#define IO_CFG_EMMC_DATA_LINE_COUNT 8
+#define REG_CTRL_EMMC_CLK 0x0014
+#define REG_CTRL_EMMC_CMD 0x0018
+#define REG_CTRL_EMMC_DATA0 0x001c
+#define REG_CTRL_EMMC_DATA1 0x0028
+#define REG_CTRL_EMMC_DATA2 0x0024
+#define REG_CTRL_EMMC_DATA3 0x0020
+#define REG_CTRL_EMMC_DATA4 0x0030
+#define REG_CTRL_EMMC_DATA5 0x0034
+#define REG_CTRL_EMMC_DATA6 0x0038
+#define REG_CTRL_EMMC_DATA7 0x003c
+#define REG_CTRL_EMMC_DS 0x0058
+#define REG_CTRL_EMMC_RST 0x005c
+static unsigned int io_emmc_data_reg[IO_CFG_EMMC_DATA_LINE_COUNT] = {
+ REG_CTRL_EMMC_DATA0, REG_CTRL_EMMC_DATA1,
+ REG_CTRL_EMMC_DATA2, REG_CTRL_EMMC_DATA3,
+ REG_CTRL_EMMC_DATA4, REG_CTRL_EMMC_DATA5,
+ REG_CTRL_EMMC_DATA6, REG_CTRL_EMMC_DATA7
+};
+
+#define IO_CFG_SDIO0_DATA_LINE_COUNT 4
+#define REG_CTRL_SDIO0_CLK 0x0040
+#define REG_CTRL_SDIO0_CMD 0x0044
+#define REG_CTRL_SDIO0_DATA0 0x0048
+#define REG_CTRL_SDIO0_DATA1 0x004C
+#define REG_CTRL_SDIO0_DATA2 0x0050
+#define REG_CTRL_SDIO0_DATA3 0x0054
+static unsigned int io_sdio0_data_reg[IO_CFG_SDIO0_DATA_LINE_COUNT] = {
+ REG_CTRL_SDIO0_DATA0, REG_CTRL_SDIO0_DATA1,
+ REG_CTRL_SDIO0_DATA2, REG_CTRL_SDIO0_DATA3
+};
+
+#define IO_CFG_SDIO1_DATA_LINE_COUNT 4
+#define REG_CTRL_SDIO1_CLK 0x0060
+#define REG_CTRL_SDIO1_CMD 0x0064
+#define REG_CTRL_SDIO1_DATA0 0x0068
+#define REG_CTRL_SDIO1_DATA1 0x006C
+#define REG_CTRL_SDIO1_DATA2 0x0070
+#define REG_CTRL_SDIO1_DATA3 0x0074
+static unsigned int io_sdio1_data_reg[IO_CFG_SDIO1_DATA_LINE_COUNT] = {
+ REG_CTRL_SDIO1_DATA0, REG_CTRL_SDIO1_DATA1,
+ REG_CTRL_SDIO1_DATA2, REG_CTRL_SDIO1_DATA3
+};
+
+struct sdhci_bsp_priv {
+ struct reset_control *crg_rst;
+ struct reset_control *dll_rst;
+ struct reset_control *sampl_rst; /* Not used */
+ struct regmap *crg_regmap;
+ struct regmap *iocfg_regmap;
+ unsigned int f_max;
+ unsigned int devid;
+ unsigned int drv_phase;
+ unsigned int sampl_phase;
+ unsigned int tuning_phase;
+};
+
+static void bsp_mmc_crg_init(struct sdhci_host *host);
+static void sdhci_bsp_hs400_enhanced_strobe(struct mmc_host *mmc, struct mmc_ios *ios);
+static int sdhci_bsp_parse_dt(struct sdhci_host *host);
+
+static inline void *sdhci_get_pltfm_priv(struct sdhci_host *host)
+{
+ return sdhci_pltfm_priv(sdhci_priv(host));
+}
+
+static void sdhci_bsp_hs400_enhanced_strobe(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+ u32 ctrl;
+ struct sdhci_host *host = mmc_priv(mmc);
+
+ ctrl = sdhci_readl(host, SDHCI_EMMC_CTRL);
+ if (ios->enhanced_strobe)
+ ctrl |= SDHCI_ENH_STROBE_EN;
+ else
+ ctrl &= ~SDHCI_ENH_STROBE_EN;
+
+ sdhci_writel(host, ctrl, SDHCI_EMMC_CTRL);
+
+ ctrl = sdhci_readl(host, SDHCI_MULTI_CYCLE);
+ if (ios->enhanced_strobe)
+ ctrl |= SDHCI_CMD_DLY_EN;
+ else
+ ctrl &= ~SDHCI_CMD_DLY_EN;
+
+ sdhci_writel(host, ctrl, SDHCI_MULTI_CYCLE);
+}
+
+static int sdhci_bsp_pltfm_init(struct platform_device *pdev, struct sdhci_host *host)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_bsp_priv *bsp_priv = sdhci_pltfm_priv(pltfm_host);
+ struct device_node *np = pdev->dev.of_node;
+ struct clk *clk = NULL;
+ int ret;
+
+ bsp_priv->crg_rst = devm_reset_control_get(&pdev->dev, "crg_reset");
+ if (IS_ERR_OR_NULL(bsp_priv->crg_rst)) {
+ dev_err(&pdev->dev, "get crg_rst failed.\n");
+ return PTR_ERR(bsp_priv->crg_rst);
+ }
+
+ bsp_priv->dll_rst = devm_reset_control_get(&pdev->dev, "dll_reset");
+ if (IS_ERR_OR_NULL(bsp_priv->dll_rst)) {
+ dev_err(&pdev->dev, "get dll_rst failed.\n");
+ return PTR_ERR(bsp_priv->dll_rst);
+ }
+
+ bsp_priv->sampl_rst = NULL;
+
+ bsp_priv->crg_regmap = syscon_regmap_lookup_by_phandle(np, "crg_regmap");
+ if (IS_ERR(bsp_priv->crg_regmap)) {
+ dev_err(&pdev->dev, "get crg regmap failed.\n");
+ return PTR_ERR(bsp_priv->crg_regmap);
+ }
+
+ bsp_priv->iocfg_regmap = syscon_regmap_lookup_by_phandle(np, "iocfg_regmap");
+ if (IS_ERR(bsp_priv->iocfg_regmap)) {
+ dev_err(&pdev->dev, "get iocfg regmap failed.\n");
+ return PTR_ERR(bsp_priv->iocfg_regmap);
+ }
+
+ if (of_property_read_u32(np, "devid", &bsp_priv->devid))
+ return -EINVAL;
+
+ clk = devm_clk_get(mmc_dev(host->mmc), "mmc_clk");
+ if (IS_ERR_OR_NULL(clk)) {
+ dev_err(mmc_dev(host->mmc), "get clk err\n");
+ return -EINVAL;
+ }
+
+ pltfm_host->clk = clk;
+
+ bsp_mmc_crg_init(host);
+ ret = sdhci_bsp_parse_dt(host);
+ if (ret)
+ return ret;
+
+ /*
+ * Only eMMC has a hw reset, and now eMMC signaling
+ * is fixed to 180
+ */
+ if (host->mmc->caps & MMC_CAP_HW_RESET) {
+ host->flags &= ~SDHCI_SIGNALING_330;
+ host->flags |= SDHCI_SIGNALING_180;
+ }
+
+ /*
+ * We parse the support timings from dts, so we read the
+ * host capabilities early and clear the timing capabilities,
+ * SDHCI_QUIRK_MISSING_CAPS is set so that sdhci driver would
+ * not read it again
+ */
+ host->caps = sdhci_readl(host, SDHCI_CAPABILITIES);
+ host->caps &= ~(SDHCI_CAN_DO_HISPD | SDHCI_CAN_VDD_300);
+ host->caps1 = sdhci_readl(host, SDHCI_CAPABILITIES_1);
+ host->caps1 &= ~(SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_SDR104 |
+ SDHCI_SUPPORT_DDR50 | SDHCI_CAN_DO_ADMA3);
+ host->quirks |= SDHCI_QUIRK_MISSING_CAPS |
+ SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC |
+ SDHCI_QUIRK_SINGLE_POWER_WRITE;
+
+ host->mmc_host_ops.hs400_enhanced_strobe =
+ sdhci_bsp_hs400_enhanced_strobe;
+
+ mci_host[slot_index++] = host->mmc;
+
+ return 0;
+}
+
+static void bsp_wait_ds_dll_lock(struct sdhci_host *host)
+{
+ /* Do nothing */
+}
+
+static void bsp_wait_ds_180_dll_ready(struct sdhci_host *host)
+{
+ struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host);
+ unsigned int reg;
+ unsigned int timeout = 20;
+
+ do {
+ reg = 0;
+ regmap_read(bsp_priv->crg_regmap,
+ REG_EMMC_DS180_DLL_STATUS, &reg);
+ if (reg & EMMC_DS180_DLL_READY)
+ return;
+
+ mdelay(1);
+ timeout--;
+ } while (timeout > 0);
+
+ pr_err("%s: DS 180 DLL master not ready.\n", mmc_hostname(host->mmc));
+}
+
+static void bsp_set_ds_dll_delay(struct sdhci_host *host)
+{
+ /* Do nothing */
+}
+
+static void bsp_host_extra_init(struct sdhci_host *host)
+{
+ unsigned short ctrl;
+ unsigned int mbiiu_ctrl, val;
+
+ ctrl = sdhci_readw(host, SDHCI_MSHC_CTRL);
+ ctrl &= ~SDHCI_CMD_CONFLIT_CHECK;
+ sdhci_writew(host, ctrl, SDHCI_MSHC_CTRL);
+
+ mbiiu_ctrl = sdhci_readl(host, SDHCI_AXI_MBIIU_CTRL);
+ mbiiu_ctrl &= ~(SDHCI_GM_WR_OSRC_LMT_MASK | SDHCI_GM_RD_OSRC_LMT_MASK |
+ SDHCI_UNDEFL_INCR_EN);
+ mbiiu_ctrl |= (SDHCI_GM_WR_OSRC_LMT_SEL(0x7) | /* set write outstanding 8 (lmt + 1) */
+ SDHCI_GM_RD_OSRC_LMT_SEL(0x7)); /* set read outstanding 8 (lmt + 1) */
+ sdhci_writel(host, mbiiu_ctrl, SDHCI_AXI_MBIIU_CTRL);
+
+ val = sdhci_readl(host, SDHCI_MULTI_CYCLE);
+ val &= ~SDHCI_CMD_DLY_EN;
+ val |= SDHCI_EDGE_DETECT_EN | SDHCI_DATA_DLY_EN;
+ val &= ~SDHCI_DOUT_EN_F_EDGE;
+
+ sdhci_writel(host, val, SDHCI_MULTI_CYCLE);
+ host->error_count = 0;
+}
+
+static void bsp_set_drv_str(struct regmap *iocfg_regmap,
+ unsigned int offset, unsigned int pull_up,
+ unsigned int pull_down, unsigned int sr,
+ unsigned int drv_str)
+{
+ unsigned int reg = 0;
+
+ regmap_read(iocfg_regmap, offset, &reg);
+
+ reg &= ~(IO_CFG_PULL_UP | IO_CFG_PULL_DOWN |
+ IO_CFG_DRV_STR_MASK | IO_CFG_SR);
+ reg |= (pull_up ? IO_CFG_PULL_UP : 0);
+ reg |= (pull_down ? IO_CFG_PULL_DOWN : 0);
+ reg |= (sr ? IO_CFG_SR : 0);
+ reg |= io_cfg_drv_str_sel(drv_str);
+
+ regmap_write(iocfg_regmap, offset, reg);
+}
+
+static void bsp_set_emmc_ctrl(struct sdhci_host *host)
+{
+ unsigned int reg;
+
+ reg = sdhci_readl(host, SDHCI_EMMC_CTRL);
+ reg |= SDHCI_CARD_IS_EMMC;
+ sdhci_writel(host, reg, SDHCI_EMMC_CTRL);
+}
+
+
+static void bsp_set_mmc_drv(struct sdhci_host *host)
+{
+ struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host);
+ void *iocfg_regmap = bsp_priv->iocfg_regmap;
+ int i;
+
+ switch (host->timing) {
+ case MMC_TIMING_MMC_HS400:
+ bsp_set_emmc_ctrl(host);
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_CLK, 0, 1, 0, 0x3); /* set drv level 3 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_CMD, 1, 0, 0, 0x5); /* set drv level 5 */
+ for (i = 0; i < IO_CFG_EMMC_DATA_LINE_COUNT; i++)
+ bsp_set_drv_str(iocfg_regmap,
+ io_emmc_data_reg[i], 1, 0, 0, 0x5); /* set drv level 5 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_DS, 0, 1, 1, 0x3); /* set drv level 3 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_RST, 1, 0, 1, 0x3); /* set drv level 3 */
+ break;
+ case MMC_TIMING_MMC_HS200:
+ bsp_set_emmc_ctrl(host);
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_CLK, 0, 1, 0, 0x2); /* set drv level 2 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_CMD, 1, 0, 1, 0x4); /* set drv level 4 */
+ for (i = 0; i < IO_CFG_EMMC_DATA_LINE_COUNT; i++)
+ bsp_set_drv_str(iocfg_regmap,
+ io_emmc_data_reg[i], 1, 0, 1, 0x4); /* set drv level 4 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_RST, 1, 0, 1, 0x3); /* set drv level 3 */
+ break;
+ case MMC_TIMING_MMC_HS:
+ bsp_set_emmc_ctrl(host);
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_CLK, 0, 1, 1, 0x4); /* set drv level 4 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_CMD, 1, 0, 1, 0x6); /* set drv level 6 */
+ for (i = 0; i < IO_CFG_EMMC_DATA_LINE_COUNT; i++)
+ bsp_set_drv_str(iocfg_regmap,
+ io_emmc_data_reg[i], 1, 0, 1, 0x6); /* set drv level 6 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_RST, 1, 0, 1, 0x3); /* set drv level 3 */
+ break;
+ case MMC_TIMING_LEGACY:
+ case MMC_TIMING_MMC_DDR52:
+ default:
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_CLK, 0, 1, 1, 0x5); /* set drv level 5 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_CMD, 1, 0, 1, 0x6); /* set drv level 6 */
+ for (i = 0; i < IO_CFG_EMMC_DATA_LINE_COUNT; i++)
+ bsp_set_drv_str(iocfg_regmap,
+ io_emmc_data_reg[i], 1, 0, 1, 0x6); /* set drv level 6 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_EMMC_RST, 1, 0, 1, 0x3); /* set drv level 3 */
+ break;
+ }
+}
+
+static void bsp_set_sd_drv(struct sdhci_host *host)
+{
+ struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host);
+ void *iocfg_regmap = bsp_priv->iocfg_regmap;
+ int i;
+
+ switch (host->timing) {
+ case MMC_TIMING_SD_HS:
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_SDIO0_CLK, 0, 1, 1, 0x5); /* set drv level 5 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_SDIO0_CMD, 1, 0, 1, 0x7); /* set drv level 7 */
+ for (i = 0; i < IO_CFG_SDIO0_DATA_LINE_COUNT; i++)
+ bsp_set_drv_str(iocfg_regmap,
+ io_sdio0_data_reg[i], 1, 0, 1, 0x7); /* set drv level 7 */
+ break;
+ case MMC_TIMING_LEGACY:
+ default:
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_SDIO0_CLK, 0, 1, 1, 0x5); /* set drv level 5 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_SDIO0_CMD, 1, 0, 1, 0x7); /* set drv level 7 */
+ for (i = 0; i < IO_CFG_SDIO0_DATA_LINE_COUNT; i++)
+ bsp_set_drv_str(iocfg_regmap,
+ io_sdio0_data_reg[i], 1, 0, 1, 0x7); /* set drv level 7 */
+ break;
+ }
+}
+
+static void bsp_set_sdio_drv(struct sdhci_host *host)
+{
+ struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host);
+ void *iocfg_regmap = bsp_priv->iocfg_regmap;
+ int i;
+
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_SDIO1_CLK, 0, 1, 1, 0x5); /* set drv level 5 */
+ bsp_set_drv_str(iocfg_regmap, REG_CTRL_SDIO1_CMD, 1, 0, 0, 0x7); /* set drv level 7 */
+ for (i = 0; i < IO_CFG_SDIO1_DATA_LINE_COUNT; i++)
+ bsp_set_drv_str(iocfg_regmap,
+ io_sdio1_data_reg[i], 1, 0, 0, 0x7); /* set drv level 7 */
+}
+
+static void bsp_set_io_config(struct sdhci_host *host)
+{
+ struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host);
+ unsigned int devid = bsp_priv->devid;
+ void *iocfg_regmap = bsp_priv->iocfg_regmap;
+ unsigned int reg = 0;
+
+ if (devid == 0) {
+ /* For mmc0: eMMC and SD card */
+ regmap_read(iocfg_regmap, REG_CTRL_EMMC_CLK, &reg);
+ if ((reg & IO_CFG_PIN_MUX_MASK) ==
+ io_cfg_pin_mux_sel(IO_CFG_PIN_MUX_TYPE_CLK_EMMC))
+ bsp_set_mmc_drv(host);
+
+ regmap_read(iocfg_regmap, REG_CTRL_SDIO0_CLK, &reg);
+ if ((reg & IO_CFG_PIN_MUX_MASK) ==
+ io_cfg_pin_mux_sel(IO_CFG_PIN_MUX_TYPE_CLK_SD))
+ bsp_set_sd_drv(host);
+ } else {
+ /* For mmc1: sdio wifi */
+ bsp_set_sdio_drv(host);
+ }
+}
+
+static void bsp_get_phase(struct sdhci_host *host)
+{
+ struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host);
+ unsigned int devid = bsp_priv->devid;
+
+ if (devid == 0) {
+ /* For eMMC and SD card */
+ if (host->mmc->ios.timing == MMC_TIMING_MMC_HS400) {
+ bsp_priv->drv_phase = 9; /* 9 for 101.25 degree */
+ bsp_priv->sampl_phase = bsp_priv->tuning_phase;
+ } else if (host->mmc->ios.timing == MMC_TIMING_MMC_HS200) {
+ bsp_priv->drv_phase = 23; /* 23 for 258.75 degree */
+ bsp_priv->sampl_phase = bsp_priv->tuning_phase;
+ } else if (host->mmc->ios.timing == MMC_TIMING_MMC_HS) {
+ bsp_priv->drv_phase = 16; /* 16 for 180 degree */
+ bsp_priv->sampl_phase = 4; /* 4 for 45 degree */
+ } else if (host->mmc->ios.timing == MMC_TIMING_SD_HS) {
+ bsp_priv->drv_phase = 20; /* 20 for 225 degree */
+ bsp_priv->sampl_phase = 4; /* 4 for 45 degree */
+ } else if (host->mmc->ios.timing == MMC_TIMING_LEGACY) {
+ bsp_priv->drv_phase = 16; /* 16 for 180 degree */
+ bsp_priv->sampl_phase = 0; /* 0 for 0 degree */
+ } else if (host->mmc->ios.timing == MMC_TIMING_MMC_DDR52) {
+ bsp_priv->drv_phase = 8; /* 8 for 90 degree */
+ bsp_priv->sampl_phase = bsp_priv->tuning_phase;
+ } else {
+ bsp_priv->drv_phase = 16; /* 16 for 180 degree */
+ bsp_priv->sampl_phase = 0; /* 0 for 0 degree */
+ }
+ } else {
+ /* For SDIO device */
+ if ((host->mmc->ios.timing == MMC_TIMING_SD_HS) ||
+ (host->mmc->ios.timing == MMC_TIMING_UHS_SDR25)) {
+ bsp_priv->drv_phase = 16; /* 16 for 180 degree */
+ bsp_priv->sampl_phase = 4; /* 4 for 45 degree */
+ } else {
+ /* UHS_SDR12 */
+ bsp_priv->drv_phase = 16; /* 16 for 180 degree */
+ bsp_priv->sampl_phase = 0; /* 0 for 0 degree */
+ }
+ }
+}
+
+static int bsp_support_runtime_pm(struct sdhci_host *host)
+{
+ struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host);
+ unsigned int devid = bsp_priv->devid;
+
+ /* Only enable for mmc0 eMMC and SD card */
+ if (devid == 0)
+ return 1;
+ else
+ return 0;
+}
+
+#include "sdhci-goke.c"
+#endif
\ В конце файла нет новой строки
diff -urN linux-4.9.37/drivers/mmc/host/sdhci-goke.c linux-4.9.y/drivers/mmc/host/sdhci-goke.c
--- linux-4.9.37/drivers/mmc/host/sdhci-goke.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/mmc/host/sdhci-goke.c 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,714 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+static unsigned int sdhci_bsp_get_max_clk(struct sdhci_host *host)
+{
+ struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host);
+
+ return bsp_priv->f_max;
+}
+
+static int sdhci_bsp_parse_dt(struct sdhci_host *host)
+{
+ struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host);
+ struct device_node *np = host->mmc->parent->of_node;
+ int ret, len;
+
+ ret = mmc_of_parse(host->mmc);
+ if (ret)
+ return ret;
+
+ if (of_property_read_u32(np, "max-frequency", &bsp_priv->f_max))
+ bsp_priv->f_max = MAX_FREQ;
+
+ if (of_find_property(np, "mmc-cmd-queue", &len))
+ host->mmc->caps2 |= MMC_CAP2_CMD_QUEUE;
+
+ if (of_find_property(np, "mmc-broken-cmd23", &len) ||
+ (host->mmc->caps2 & MMC_CAP2_CMD_QUEUE))
+ host->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23;
+
+ return 0;
+}
+
+static void bsp_mmc_crg_init(struct sdhci_host *host)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_bsp_priv *bsp_priv = sdhci_pltfm_priv(pltfm_host);
+
+ clk_prepare_enable(pltfm_host->clk);
+ reset_control_assert(bsp_priv->crg_rst);
+ reset_control_assert(bsp_priv->dll_rst);
+ if (bsp_priv->sampl_rst)
+ reset_control_assert(bsp_priv->sampl_rst);
+
+ udelay(25); /* delay 25us */
+ reset_control_deassert(bsp_priv->crg_rst);
+ udelay(10); /* delay 10us */
+}
+
+static void bsp_set_drv_phase(struct sdhci_host *host, unsigned int phase)
+{
+ struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host);
+ unsigned int devid = bsp_priv->devid;
+ unsigned int offset[] = {
+ REG_EMMC_DRV_DLL_CTRL,
+ REG_SDIO0_DRV_DLL_CTRL,
+ REG_SDIO1_DRV_DLL_CTRL,
+ REG_SDIO2_DRV_DLL_CTRL
+ };
+
+ regmap_write_bits(bsp_priv->crg_regmap, offset[devid],
+ SDIO_DRV_PHASE_SEL_MASK, sdio_drv_sel(phase));
+}
+
+static void bsp_set_sampl_phase(struct sdhci_host *host, unsigned int phase)
+{
+ unsigned int reg;
+
+ reg = sdhci_readl(host, SDHCI_AT_STAT);
+ reg &= ~SDHCI_PHASE_SEL_MASK;
+ reg |= phase;
+ sdhci_writel(host, reg, SDHCI_AT_STAT);
+}
+
+static void bsp_disable_card_clk(struct sdhci_host *host)
+{
+ u16 clk;
+
+ clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+ clk &= ~SDHCI_CLOCK_CARD_EN;
+ sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+}
+
+static void bsp_enable_card_clk(struct sdhci_host *host)
+{
+ u16 clk;
+
+ clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+ clk |= SDHCI_CLOCK_CARD_EN;
+ sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+}
+
+static void bsp_disable_inter_clk(struct sdhci_host *host)
+{
+ u16 clk;
+
+ clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+ clk &= ~SDHCI_CLOCK_INT_EN;
+ sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+}
+
+static void bsp_enable_sampl_dll_slave(struct sdhci_host *host)
+{
+ struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host);
+ unsigned int devid = bsp_priv->devid;
+ unsigned int offset[] = {
+ REG_EMMC_SAMPL_DLL_CTRL,
+ REG_SDIO0_SAMPL_DLL_CTRL,
+ REG_SDIO1_SAMPL_DLL_CTRL,
+ REG_SDIO2_SAMPL_DLL_CTRL
+ };
+
+ regmap_write_bits(bsp_priv->crg_regmap, offset[devid],
+ SDIO_SAMPL_DLL_SLAVE_EN, SDIO_SAMPL_DLL_SLAVE_EN);
+}
+
+static void bsp_wait_drv_dll_lock(struct sdhci_host *host)
+{
+ struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host);
+ unsigned int devid = bsp_priv->devid;
+ unsigned int reg;
+ unsigned int timeout = 20;
+ unsigned int offset[] = {
+ REG_EMMC_DRV_DLL_STATUS,
+ REG_SDIO0_DRV_DLL_STATUS,
+ REG_SDIO1_DRV_DLL_STATUS,
+ REG_SDIO2_DRV_DLL_STATUS
+ };
+
+ do {
+ reg = 0;
+ regmap_read(bsp_priv->crg_regmap, offset[devid], &reg);
+ if (reg & SDIO_DRV_DLL_LOCK)
+ return;
+
+ mdelay(1);
+ timeout--;
+ } while (timeout > 0);
+
+ pr_err("%s: DRV DLL master not locked.\n", mmc_hostname(host->mmc));
+}
+
+static void bsp_wait_sampl_dll_slave_ready(struct sdhci_host *host)
+{
+ struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host);
+ unsigned int devid = bsp_priv->devid;
+ unsigned int reg;
+ unsigned int timeout = 20;
+ unsigned int offset[] = {
+ REG_EMMC_SAMPL_DLL_STATUS,
+ REG_SDIO0_SAMPL_DLL_STATUS,
+ REG_SDIO1_SAMPL_DLL_STATUS,
+ REG_SDIO2_SAMPL_DLL_STATUS
+ };
+
+ do {
+ reg = 0;
+ regmap_read(bsp_priv->crg_regmap, offset[devid], &reg);
+ if (reg & SDIO_SAMPL_DLL_SLAVE_READY)
+ return;
+
+ mdelay(1);
+ timeout--;
+ } while (timeout > 0);
+
+ pr_err("%s: SAMPL DLL slave not ready.\n", mmc_hostname(host->mmc));
+}
+
+static void bsp_enable_sample(struct sdhci_host *host)
+{
+ unsigned int reg;
+
+ reg = sdhci_readl(host, SDHCI_AT_CTRL);
+ reg |= SDHCI_SAMPLE_EN;
+ sdhci_writel(host, reg, SDHCI_AT_CTRL);
+}
+
+static void sdhci_bsp_set_clock(struct sdhci_host *host, unsigned int clock)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_bsp_priv *bsp_priv = sdhci_pltfm_priv(pltfm_host);
+ unsigned long timeout;
+ u16 clk;
+
+ host->mmc->actual_clock = 0;
+ bsp_disable_card_clk(host);
+ udelay(25); /* delay 25us */
+ bsp_disable_inter_clk(host);
+ if (clock == 0)
+ return;
+
+ reset_control_assert(bsp_priv->dll_rst);
+ if (bsp_priv->sampl_rst)
+ reset_control_assert(bsp_priv->sampl_rst);
+ udelay(25); /* delay 25us */
+
+ clk_set_rate(pltfm_host->clk, clock);
+ host->mmc->actual_clock = clk_get_rate(pltfm_host->clk);
+
+ bsp_get_phase(host);
+ bsp_set_drv_phase(host, bsp_priv->drv_phase);
+ bsp_enable_sample(host);
+ bsp_set_sampl_phase(host, bsp_priv->sampl_phase);
+ udelay(25); /* delay 25us */
+
+ if (host->mmc->actual_clock > MMC_HIGH_52_MAX_DTR) {
+ bsp_enable_sampl_dll_slave(host);
+ reset_control_deassert(bsp_priv->dll_rst);
+ if (bsp_priv->sampl_rst)
+ reset_control_deassert(bsp_priv->sampl_rst);
+ }
+
+ clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+ clk |= SDHCI_CLOCK_INT_EN | SDHCI_CLOCK_PLL_EN;
+ sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+ timeout = 20; /* default timeout 20ms */
+ clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+ while (!(clk & SDHCI_CLOCK_INT_STABLE)) {
+ clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+ if (timeout == 0) {
+ pr_err("%s: Internal clock never stabilised.\n",
+ mmc_hostname(host->mmc));
+ return;
+ }
+ timeout--;
+ mdelay(1);
+ }
+
+ if (host->mmc->actual_clock > MMC_HIGH_52_MAX_DTR) {
+ bsp_wait_drv_dll_lock(host);
+ bsp_wait_sampl_dll_slave_ready(host);
+ }
+
+ if (host->mmc->ios.timing == MMC_TIMING_MMC_HS400)
+ bsp_wait_ds_180_dll_ready(host);
+
+ clk |= SDHCI_CLOCK_CARD_EN;
+ sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+ udelay(100); /* delay 100us */
+
+ if (host->mmc->ios.timing == MMC_TIMING_MMC_HS400) {
+ bsp_wait_ds_dll_lock(host);
+ bsp_set_ds_dll_delay(host);
+ }
+}
+
+static void bsp_select_sampl_phase(struct sdhci_host *host, unsigned int phase)
+{
+ bsp_disable_card_clk(host);
+ bsp_set_sampl_phase(host, phase);
+ bsp_wait_sampl_dll_slave_ready(host);
+ bsp_enable_card_clk(host);
+ udelay(1);
+}
+
+static int bsp_send_tuning(struct sdhci_host *host, u32 opcode)
+{
+ int count, err;
+
+ count = 0;
+ do {
+ err = mmc_send_tuning(host->mmc, opcode, NULL);
+ if (err)
+ break;
+
+ count++;
+ } while (count < MAX_TUNING_NUM);
+
+ return err;
+}
+
+static void bsp_pre_tuning(struct sdhci_host *host)
+{
+ sdhci_writel(host, host->ier | SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE);
+ sdhci_writel(host, host->ier | SDHCI_INT_DATA_AVAIL,
+ SDHCI_SIGNAL_ENABLE);
+
+ bsp_wait_drv_dll_lock(host);
+ bsp_enable_sampl_dll_slave(host);
+ bsp_enable_sample(host);
+ host->is_tuning = 1;
+}
+
+static void bsp_post_tuning(struct sdhci_host *host)
+{
+ unsigned short ctrl;
+
+ ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+ ctrl |= SDHCI_CTRL_TUNED_CLK;
+ sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
+
+ sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
+ sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
+ host->is_tuning = 0;
+}
+
+#ifndef SDHCI_GOKE_EDGE_TUNING
+static int bsp_get_best_sampl(u32 candidates)
+{
+ int rise = NOT_FOUND;
+ int fall = NOT_FOUND;
+ int win_max_r = NOT_FOUND;
+ int win_max_f = NOT_FOUND;
+ int end_fall = NOT_FOUND;
+ int found = NOT_FOUND;
+ int win_max = 0;
+ int i, win;
+
+ for (i = 0; i < PHASE_SCALE; i++) {
+ if ((candidates & 0x3) == 0x2)
+ rise = (i + 1) % PHASE_SCALE;
+
+ if ((candidates & 0x3) == 0x1) {
+ fall = i;
+ if (rise != NOT_FOUND) {
+ win = fall - rise + 1;
+ if (win > win_max) {
+ win_max = win;
+ found = (fall + rise) / 2; /* Get window center by devide 2 */
+ win_max_r = rise;
+ win_max_f = fall;
+ rise = NOT_FOUND;
+ fall = NOT_FOUND;
+ }
+ } else {
+ end_fall = fall;
+ }
+ }
+ candidates = ror32(candidates, 1);
+ }
+
+ if (end_fall != NOT_FOUND && rise != NOT_FOUND) {
+ fall = end_fall;
+ if (end_fall < rise)
+ end_fall += PHASE_SCALE;
+
+ win = end_fall - rise + 1;
+ if (win > win_max) {
+ found = (rise + (win / 2)) % PHASE_SCALE; /* Get window center by devide 2 */
+ win_max_r = rise;
+ win_max_f = fall;
+ }
+ }
+
+ if (found != NOT_FOUND)
+ pr_info("valid phase shift [%d, %d] Final Phase:%d\n",
+ win_max_r, win_max_f, found);
+
+ return found;
+}
+
+static int sdhci_bsp_exec_tuning(struct sdhci_host *host, u32 opcode)
+{
+ struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host);
+ unsigned int sampl;
+ unsigned int candidates = 0;
+ int phase, err;
+
+ bsp_pre_tuning(host);
+
+ for (sampl = 0; sampl < PHASE_SCALE; sampl++) {
+ bsp_select_sampl_phase(host, sampl);
+
+ err = bsp_send_tuning(host, opcode);
+ if (err)
+ pr_debug("send tuning CMD%u fail! phase:%d err:%d\n",
+ opcode, sampl, err);
+ else
+ candidates |= (0x1 << sampl);
+ }
+
+ pr_info("%s: tuning done! candidates 0x%X: ",
+ mmc_hostname(host->mmc), candidates);
+
+ phase = bsp_get_best_sampl(candidates);
+ if (phase == NOT_FOUND) {
+ phase = bsp_priv->sampl_phase;
+ pr_err("no valid phase shift! use default %d\n", phase);
+ }
+
+ bsp_priv->tuning_phase = phase;
+ bsp_select_sampl_phase(host, phase);
+ bsp_post_tuning(host);
+
+ return 0;
+}
+
+#else
+static void bsp_enable_edge_tuning(struct sdhci_host *host)
+{
+ struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host);
+ unsigned int devid = bsp_priv->devid;
+ unsigned int samplb_offset[] = {
+ REG_EMMC_SAMPLB_DLL_CTRL,
+ REG_SDIO0_SAMPLB_DLL_CTRL,
+ REG_SDIO1_SAMPLB_DLL_CTRL,
+ REG_SDIO2_SAMPLB_DLL_CTRL
+ };
+ unsigned int reg;
+
+ regmap_write_bits(bsp_priv->crg_regmap, samplb_offset[devid],
+ SDIO_SAMPLB_DLL_CLK_MASK, sdio_samplb_sel(8)); /* 8 for 180 degree */
+
+ reg = sdhci_readl(host, SDHCI_MULTI_CYCLE);
+ reg |= SDHCI_EDGE_DETECT_EN;
+ sdhci_writel(host, reg, SDHCI_MULTI_CYCLE);
+}
+
+static void bsp_disable_edge_tuning(struct sdhci_host *host)
+{
+ unsigned int reg;
+
+ reg = sdhci_readl(host, SDHCI_MULTI_CYCLE);
+ reg &= ~SDHCI_EDGE_DETECT_EN;
+ sdhci_writel(host, reg, SDHCI_MULTI_CYCLE);
+}
+
+static int sdhci_bsp_exec_edge_tuning(struct sdhci_host *host, u32 opcode)
+{
+ struct sdhci_bsp_priv *bsp_priv = sdhci_get_pltfm_priv(host);
+ unsigned int index, val;
+ unsigned int edge_p2f, edge_f2p, start, end, phase;
+ unsigned int fall, rise, fall_updat_flag;
+ unsigned int found = 0;
+ unsigned int prev_found = 0;
+ int prev_err = 0;
+ int err;
+
+ bsp_pre_tuning(host);
+ bsp_enable_edge_tuning(host);
+
+ start = 0;
+ end = PHASE_SCALE / EDGE_TUNING_PHASE_STEP;
+
+ edge_p2f = start;
+ edge_f2p = end;
+ for (index = 0; index <= end; index++) {
+ bsp_select_sampl_phase(host, index * EDGE_TUNING_PHASE_STEP);
+
+ err = mmc_send_tuning(host->mmc, opcode, NULL);
+ if (!err) {
+ val = sdhci_readl(host, SDHCI_MULTI_CYCLE);
+ found = val & SDHCI_FOUND_EDGE;
+ } else {
+ found = 1;
+ }
+
+ if (prev_found && !found)
+ edge_f2p = index;
+ else if (!prev_found && found)
+ edge_p2f = index;
+
+ if ((edge_p2f != start) && (edge_f2p != end))
+ break;
+
+ prev_found = found;
+ found = 0;
+ }
+
+ if ((edge_p2f == start) && (edge_f2p == end)) {
+ pr_err("%s: tuning failed! can not found edge!\n",
+ mmc_hostname(host->mmc));
+ return -1;
+ }
+
+ bsp_disable_edge_tuning(host);
+
+ start = edge_p2f * EDGE_TUNING_PHASE_STEP;
+ end = edge_f2p * EDGE_TUNING_PHASE_STEP;
+ if (end <= start)
+ end += PHASE_SCALE;
+
+ fall = start;
+ rise = end;
+ fall_updat_flag = 0;
+ for (index = start; index <= end; index++) {
+ bsp_select_sampl_phase(host, index % PHASE_SCALE);
+
+ err = bsp_send_tuning(host, opcode);
+ if (err)
+ pr_debug("send tuning CMD%u fail! phase:%d err:%d\n",
+ opcode, index, err);
+
+ if (err && index == start) {
+ if (!fall_updat_flag) {
+ fall_updat_flag = 1;
+ fall = start;
+ }
+ } else {
+ if (!prev_err && err) {
+ if (!fall_updat_flag) {
+ fall_updat_flag = 1;
+ fall = index;
+ }
+ }
+ }
+
+
+ if (prev_err && !err)
+ rise = index;
+
+ if (err && index == end)
+ rise = end;
+
+
+ prev_err = err;
+ }
+
+ phase = ((fall + rise) / 2 + PHASE_SCALE / 2) % PHASE_SCALE; /* Get window center by divide 2 */
+
+ pr_info("%s: tuning done! valid phase shift [%d, %d] Final Phase:%d\n",
+ mmc_hostname(host->mmc), rise % PHASE_SCALE,
+ fall % PHASE_SCALE, phase);
+
+ bsp_priv->tuning_phase = phase;
+ bsp_select_sampl_phase(host, phase);
+ bsp_post_tuning(host);
+
+ return 0;
+}
+#endif
+
+static void sdhci_bsp_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
+{
+ sdhci_set_uhs_signaling(host, timing);
+ host->timing = timing;
+
+ /* Goke add set io config here to set pin drv strength */
+ bsp_set_io_config(host);
+}
+
+static void sdhci_bsp_hw_reset(struct sdhci_host *host)
+{
+ sdhci_writel(host, 0x0, SDHCI_EMMC_HW_RESET);
+ udelay(10); /* delay 10us */
+ sdhci_writel(host, 0x1, SDHCI_EMMC_HW_RESET);
+ udelay(200); /* delay 200us */
+}
+
+/*
+ * This api is for wifi driver rescan the sdio device,
+ * ugly but it is needed
+ */
+int bsp_sdio_rescan(int slot)
+{
+ struct mmc_host *mmc = mci_host[slot];
+
+ if (mmc == NULL) {
+ pr_err("invalid mmc, please check the argument\n");
+ return -EINVAL;
+ }
+
+ mmc_detect_change(mmc, 0);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(bsp_sdio_rescan);
+
+static const struct sdhci_ops sdhci_bsp_ops = {
+ .get_max_clock = sdhci_bsp_get_max_clk,
+ .set_clock = sdhci_bsp_set_clock,
+ .set_bus_width = sdhci_set_bus_width,
+ .reset = sdhci_reset,
+ .set_uhs_signaling = sdhci_bsp_set_uhs_signaling,
+ .hw_reset = sdhci_bsp_hw_reset,
+
+#ifdef SDHCI_GOKE_EDGE_TUNING
+ .platform_execute_tuning = sdhci_bsp_exec_edge_tuning,
+#else
+ .platform_execute_tuning = sdhci_bsp_exec_tuning,
+#endif
+ .pre_init = bsp_mmc_crg_init,
+ .extra_init = bsp_host_extra_init,
+};
+
+static const struct sdhci_pltfm_data sdhci_bsp_pdata = {
+ .ops = &sdhci_bsp_ops,
+ .quirks = SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
+ SDHCI_QUIRK_INVERTED_WRITE_PROTECT |
+ SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN |
+ SDHCI_QUIRK_BROKEN_TIMEOUT_VAL,
+ .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
+};
+static int sdhci_bsp_probe(struct platform_device *pdev)
+{
+ struct sdhci_host *host;
+ struct sdhci_pltfm_host *pltfm_host = NULL;
+ int ret;
+
+ host = sdhci_pltfm_init(pdev, &sdhci_bsp_pdata,
+ sizeof(struct sdhci_bsp_priv));
+ if (IS_ERR(host))
+ return PTR_ERR(host);
+
+ ret = sdhci_bsp_pltfm_init(pdev, host);
+ if (ret)
+ goto err_sdhci_add;
+
+ if (bsp_support_runtime_pm(host)) {
+ pm_runtime_get_noresume(&pdev->dev);
+ pm_runtime_set_autosuspend_delay(&pdev->dev,
+ GOKE_MMC_AUTOSUSPEND_DELAY_MS);
+ pm_runtime_use_autosuspend(&pdev->dev);
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+ }
+
+ ret = sdhci_add_host(host);
+ if (ret)
+ goto pm_runtime_disable;
+
+ if (bsp_support_runtime_pm(host)) {
+ pm_runtime_mark_last_busy(&pdev->dev);
+ pm_runtime_put_autosuspend(&pdev->dev);
+ }
+
+ return 0;
+
+pm_runtime_disable:
+ if (bsp_support_runtime_pm(host)) {
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
+ }
+
+err_sdhci_add:
+ pltfm_host = sdhci_priv(host);
+ clk_disable_unprepare(pltfm_host->clk);
+ sdhci_pltfm_free(pdev);
+ return ret;
+}
+
+static int sdhci_bsp_remove(struct platform_device *pdev)
+{
+ struct sdhci_host *host = platform_get_drvdata(pdev);
+
+ if (bsp_support_runtime_pm(host)) {
+ pm_runtime_get_sync(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
+ }
+ return sdhci_pltfm_unregister(pdev);
+}
+
+#ifdef CONFIG_PM
+static int sdhci_bsp_runtime_suspend(struct device *dev)
+{
+ struct sdhci_host *host = dev_get_drvdata(dev);
+
+ bsp_disable_card_clk(host);
+ return 0;
+}
+
+static int sdhci_bsp_runtime_resume(struct device *dev)
+{
+ struct sdhci_host *host = dev_get_drvdata(dev);
+
+ bsp_enable_card_clk(host);
+ return 0;
+}
+#endif
+
+static const struct of_device_id sdhci_bsp_match[] = {
+ { .compatible = "goke,sdhci" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, sdhci_bsp_match);
+
+static const struct dev_pm_ops sdhci_bsp_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(sdhci_pltfm_suspend,
+ sdhci_pltfm_resume)
+
+ SET_RUNTIME_PM_OPS(sdhci_bsp_runtime_suspend,
+ sdhci_bsp_runtime_resume,
+ NULL)
+};
+
+static struct platform_driver sdhci_bsp_driver = {
+ .driver = {
+ .name = "sdhci-goke",
+ .of_match_table = sdhci_bsp_match,
+ .pm = &sdhci_bsp_pm_ops,
+ },
+ .probe = sdhci_bsp_probe,
+ .remove = sdhci_bsp_remove,
+};
+
+static int __init sdhci_bsp_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&sdhci_bsp_driver);
+ if (ret)
+ return ret;
+
+ ret = mci_proc_init();
+ if (ret)
+ platform_driver_unregister(&sdhci_bsp_driver);
+
+ return ret;
+}
+
+static void __exit sdhci_bsp_exit(void)
+{
+ mci_proc_shutdown();
+
+ platform_driver_unregister(&sdhci_bsp_driver);
+}
+
+module_init(sdhci_bsp_init);
+module_exit(sdhci_bsp_exit);
+
+MODULE_DESCRIPTION("SDHCI driver for goke");
+MODULE_LICENSE("GPL v2");
diff -urN linux-4.9.37/drivers/mmc/host/sdhci.h linux-4.9.y/drivers/mmc/host/sdhci.h
--- linux-4.9.37/drivers/mmc/host/sdhci.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/mmc/host/sdhci.h 2021-06-07 13:01:33.000000000 +0300
@@ -20,6 +20,8 @@
#include <linux/mmc/host.h>
+#define SDHCI_GOKE_EDGE_TUNING /* enable edge tuning */
+
/*
* Controller registers
*/
@@ -84,6 +86,7 @@
#define SDHCI_CTRL_ADMA1 0x08
#define SDHCI_CTRL_ADMA32 0x10
#define SDHCI_CTRL_ADMA64 0x18
+#define SDHCI_CTRL_ADMA3 0x18
#define SDHCI_CTRL_8BITBUS 0x20
#define SDHCI_CTRL_CDTEST_INS 0x40
#define SDHCI_CTRL_CDTEST_EN 0x80
@@ -108,6 +111,7 @@
#define SDHCI_DIV_MASK_LEN 8
#define SDHCI_DIV_HI_MASK 0x300
#define SDHCI_PROG_CLOCK_MODE 0x0020
+#define SDHCI_CLOCK_PLL_EN 0x0008
#define SDHCI_CLOCK_CARD_EN 0x0004
#define SDHCI_CLOCK_INT_STABLE 0x0002
#define SDHCI_CLOCK_INT_EN 0x0001
@@ -132,6 +136,7 @@
#define SDHCI_INT_CARD_REMOVE 0x00000080
#define SDHCI_INT_CARD_INT 0x00000100
#define SDHCI_INT_RETUNE 0x00001000
+#define SDHCI_INT_CQE 0x00004000
#define SDHCI_INT_ERROR 0x00008000
#define SDHCI_INT_TIMEOUT 0x00010000
#define SDHCI_INT_CRC 0x00020000
@@ -141,14 +146,16 @@
#define SDHCI_INT_DATA_CRC 0x00200000
#define SDHCI_INT_DATA_END_BIT 0x00400000
#define SDHCI_INT_BUS_POWER 0x00800000
-#define SDHCI_INT_ACMD12ERR 0x01000000
+#define SDHCI_INT_ACMD_ERR 0x01000000
#define SDHCI_INT_ADMA_ERROR 0x02000000
#define SDHCI_INT_NORMAL_MASK 0x00007FFF
#define SDHCI_INT_ERROR_MASK 0xFFFF8000
#define SDHCI_INT_CMD_MASK (SDHCI_INT_RESPONSE | SDHCI_INT_TIMEOUT | \
- SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX)
+ SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX | \
+ SDHCI_INT_ACMD_ERR)
+
#define SDHCI_INT_DATA_MASK (SDHCI_INT_DATA_END | SDHCI_INT_DMA_END | \
SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | \
SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | \
@@ -156,7 +163,13 @@
SDHCI_INT_BLK_GAP)
#define SDHCI_INT_ALL_MASK ((unsigned int)-1)
-#define SDHCI_ACMD12_ERR 0x3C
+#define SDHCI_AUTO_CMD_ERR 0x3C
+#define SDHCI_AUTO_CMD12_NOT_EXEC 0x0001
+#define SDHCI_AUTO_CMD_TIMEOUT_ERR 0x0002
+#define SDHCI_AUTO_CMD_CRC_ERR 0x0004
+#define SDHCI_AUTO_CMD_ENDBIT_ERR 0x0008
+#define SDHCI_AUTO_CMD_INDEX_ERR 0x0010
+#define SDHCI_AUTO_CMD12_NOT_ISSUED 0x0080
#define SDHCI_HOST_CONTROL2 0x3E
#define SDHCI_CTRL_UHS_MASK 0x0007
@@ -165,7 +178,7 @@
#define SDHCI_CTRL_UHS_SDR50 0x0002
#define SDHCI_CTRL_UHS_SDR104 0x0003
#define SDHCI_CTRL_UHS_DDR50 0x0004
-#define SDHCI_CTRL_HS400 0x0005 /* Non-standard */
+#define SDHCI_CTRL_HS400 0x0007 /* Non-standard */
#define SDHCI_CTRL_VDD_180 0x0008
#define SDHCI_CTRL_DRV_TYPE_MASK 0x0030
#define SDHCI_CTRL_DRV_TYPE_B 0x0000
@@ -174,6 +187,9 @@
#define SDHCI_CTRL_DRV_TYPE_D 0x0030
#define SDHCI_CTRL_EXEC_TUNING 0x0040
#define SDHCI_CTRL_TUNED_CLK 0x0080
+#define SDHCI_CTRL_HOST_VER4_ENABLE 0x1000
+#define SDHCI_CTRL_ADDRESSING_64BIT 0x2000
+#define SDHCI_CTRL_ASYNC_INT_ENABLE 0x4000
#define SDHCI_CTRL_PRESET_VAL_ENABLE 0x8000
#define SDHCI_CAPABILITIES 0x40
@@ -195,6 +211,7 @@
#define SDHCI_CAN_VDD_300 0x02000000
#define SDHCI_CAN_VDD_180 0x04000000
#define SDHCI_CAN_64BIT 0x10000000
+#define SDHCI_CAN_ASYNC_INT 0x20000000
#define SDHCI_SUPPORT_SDR50 0x00000001
#define SDHCI_SUPPORT_SDR104 0x00000002
@@ -209,6 +226,7 @@
#define SDHCI_RETUNING_MODE_SHIFT 14
#define SDHCI_CLOCK_MUL_MASK 0x00FF0000
#define SDHCI_CLOCK_MUL_SHIFT 16
+#define SDHCI_CAN_DO_ADMA3 0x08000000
#define SDHCI_SUPPORT_HS400 0x80000000 /* Non-standard */
#define SDHCI_CAPABILITIES_1 0x44
@@ -250,6 +268,9 @@
#define SDHCI_PRESET_SDCLK_FREQ_MASK 0x3FF
#define SDHCI_PRESET_SDCLK_FREQ_SHIFT 0
+#define SDHCI_ADMA3_ID_ADDR_LOW 0x78
+#define SDHCI_ADMA3_ID_ADDR_HI 0x7C
+
#define SDHCI_SLOT_INT_STATUS 0xFC
#define SDHCI_HOST_VERSION 0xFE
@@ -260,7 +281,38 @@
#define SDHCI_SPEC_100 0
#define SDHCI_SPEC_200 1
#define SDHCI_SPEC_300 2
-
+#define SDHCI_SPEC_400 3
+#define SDHCI_SPEC_410 4
+#define SDHCI_SPEC_420 5
+
+#define SDHCI_MSHC_CTRL 0x508
+#define SDHCI_CMD_CONFLIT_CHECK 0x01
+
+#define SDHCI_AXI_MBIIU_CTRL 0x510
+#define SDHCI_GM_WR_OSRC_LMT_MASK (0x7 << 24)
+#define SDHCI_GM_WR_OSRC_LMT_SEL(x) ((x) << 24)
+#define SDHCI_GM_RD_OSRC_LMT_MASK (0x7 << 16)
+#define SDHCI_GM_RD_OSRC_LMT_SEL(x) ((x) << 16)
+#define SDHCI_UNDEFL_INCR_EN 0x1
+
+#define SDHCI_EMMC_CTRL 0x52c
+#define SDHCI_CARD_IS_EMMC 0x00000001
+#define SDHCI_ENH_STROBE_EN 0x00000100
+
+#define SDHCI_EMMC_HW_RESET 0x534
+
+#define SDHCI_AT_CTRL 0x540
+#define SDHCI_SAMPLE_EN 0x00000010
+
+#define SDHCI_AT_STAT 0x544
+#define SDHCI_PHASE_SEL_MASK 0x000000ff
+
+#define SDHCI_MULTI_CYCLE 0x54c
+#define SDHCI_FOUND_EDGE (0x1 << 11)
+#define SDHCI_EDGE_DETECT_EN (0x1 << 8)
+#define SDHCI_DOUT_EN_F_EDGE (0x1 << 6)
+#define SDHCI_DATA_DLY_EN (0x1 << 3)
+#define SDHCI_CMD_DLY_EN (0x1 << 2)
/*
* End of controller registers.
*/
@@ -273,6 +325,7 @@
*/
#define SDHCI_DEFAULT_BOUNDARY_SIZE (512 * 1024)
#define SDHCI_DEFAULT_BOUNDARY_ARG (ilog2(SDHCI_DEFAULT_BOUNDARY_SIZE) - 12)
+#define SDHCI_DMA_BOUNDARY_SIZE (0x1 << 27)
/* ADMA2 32-bit DMA descriptor size */
#define SDHCI_ADMA2_32_DESC_SZ 8
@@ -298,6 +351,12 @@
/* ADMA2 64-bit DMA descriptor size */
#define SDHCI_ADMA2_64_DESC_SZ 12
+/* ADMA3 32-bit DMA descriptor size */
+#define SDHCI_ADMA3_32_DESC_SZ 8
+
+/* ADMA3 64-bit DMA descriptor size */
+#define SDHCI_ADMA3_64_DESC_SZ 16
+
/*
* ADMA2 64-bit descriptor. Note 12-byte descriptor can't always be 8-byte
* aligned.
@@ -312,6 +371,9 @@
#define ADMA2_TRAN_VALID 0x21
#define ADMA2_NOP_END_VALID 0x3
#define ADMA2_END 0x2
+#define ADMA2_LINK_VALID 0x31
+#define ADMA3_CMD_VALID 0x9
+#define ADMA3_END 0x3b
/*
* Maximum segments assuming a 512KiB maximum requisition size and a minimum
@@ -328,6 +390,18 @@
COOKIE_MAPPED, /* mapped by sdhci_prepare_data() */
};
+struct card_info {
+ unsigned int card_type;
+ unsigned char timing;
+ unsigned char card_connect;
+#define CARD_CONNECT 1
+#define CARD_DISCONNECT 0
+ unsigned int card_support_clock; /* clock rate */
+ unsigned int card_state; /* (our) card state */
+ unsigned int sd_bus_speed;
+ unsigned int ssr[16];
+};
+
struct sdhci_host {
/* Data set by hardware interface driver */
const char *hw_name; /* Hardware bus name */
@@ -425,6 +499,7 @@
#define SDHCI_QUIRK2_ACMD23_BROKEN (1<<14)
/* Broken Clock divider zero in controller */
#define SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN (1<<15)
+#define SDHCI_QUIRK2_BROKEN_ADMA3 (1<<16)
int irq; /* Device IRQ */
void __iomem *ioaddr; /* Mapped address */
@@ -458,6 +533,8 @@
#define SDHCI_SIGNALING_330 (1<<14) /* Host is capable of 3.3V signaling */
#define SDHCI_SIGNALING_180 (1<<15) /* Host is capable of 1.8V signaling */
#define SDHCI_SIGNALING_120 (1<<16) /* Host is capable of 1.2V signaling */
+#define SDHCI_USE_ADMA3 (1<<17) /* Host is ADMA3 capable */
+#define SDHCI_HOST_VER4_ENABLE (1<<18) /* Host version 4 enable */
unsigned int version; /* SDHCI spec. version */
@@ -486,14 +563,21 @@
void *adma_table; /* ADMA descriptor table */
void *align_buffer; /* Bounce buffer */
+ void *adma3_table; /* ADMA3 integrated descriptor table */
+ void *cmd_table; /* ADMA3 command descriptor table */
size_t adma_table_sz; /* ADMA descriptor table size */
size_t align_buffer_sz; /* Bounce buffer size */
+ size_t adma3_table_sz; /* ADMA3 integrated descriptor table size */
+ size_t cmd_table_sz; /* ADMA3 command descriptor table size */
dma_addr_t adma_addr; /* Mapped ADMA descr. table */
dma_addr_t align_addr; /* Mapped bounce buffer */
+ dma_addr_t adma3_addr; /* Mapped ADMA3 integrated descr. table */
+ dma_addr_t cmd_addr; /* Mapped ADMA3 command descr. table */
unsigned int desc_sz; /* ADMA descriptor size */
+ unsigned int adma3_desc_sz; /* ADMA3 integrated descriptor size */
struct tasklet_struct finish_tasklet; /* Tasklet structures */
@@ -525,6 +609,10 @@
#define SDHCI_TUNING_MODE_2 1
#define SDHCI_TUNING_MODE_3 2
+ struct cmdq_host *cq_host;
+ unsigned int is_tuning;
+ unsigned int error_count;
+ struct card_info c_info;
unsigned long private[0] ____cacheline_aligned;
};
@@ -564,6 +652,10 @@
struct mmc_card *card,
unsigned int max_dtr, int host_drv,
int card_drv, int *drv_type);
+ int (*start_signal_voltage_switch)(struct sdhci_host *host,
+ struct mmc_ios *ios);
+ void (*pre_init)(struct sdhci_host *host);
+ void (*extra_init)(struct sdhci_host *host);
};
#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
@@ -698,4 +790,18 @@
extern int sdhci_runtime_resume_host(struct sdhci_host *host);
#endif
+#define UNSTUFF_BITS(resp,start,size) \
+ ({ \
+ const int __size = size; \
+ const u32 __mask = (__size < 32 ? 1 << __size : 0) - 1; \
+ const int __off = 3 - ((start) / 32); \
+ const int __shft = (start) & 31; \
+ u32 __res; \
+ \
+ __res = resp[__off] >> __shft; \
+ if (__size + __shft > 32) \
+ __res |= resp[__off-1] << ((32 - __shft) % 32); \
+ __res & __mask; \
+ })
+
#endif /* __SDHCI_HW_H */
diff -urN linux-4.9.37/drivers/mmc/host/sdhci-pltfm.c linux-4.9.y/drivers/mmc/host/sdhci-pltfm.c
--- linux-4.9.37/drivers/mmc/host/sdhci-pltfm.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/mmc/host/sdhci-pltfm.c 2021-06-07 13:01:33.000000000 +0300
@@ -209,19 +209,21 @@
EXPORT_SYMBOL_GPL(sdhci_pltfm_unregister);
#ifdef CONFIG_PM_SLEEP
-static int sdhci_pltfm_suspend(struct device *dev)
+int sdhci_pltfm_suspend(struct device *dev)
{
struct sdhci_host *host = dev_get_drvdata(dev);
return sdhci_suspend_host(host);
}
+EXPORT_SYMBOL_GPL(sdhci_pltfm_suspend);
-static int sdhci_pltfm_resume(struct device *dev)
+int sdhci_pltfm_resume(struct device *dev)
{
struct sdhci_host *host = dev_get_drvdata(dev);
return sdhci_resume_host(host);
}
+EXPORT_SYMBOL_GPL(sdhci_pltfm_resume);
#endif
const struct dev_pm_ops sdhci_pltfm_pmops = {
diff -urN linux-4.9.37/drivers/mmc/host/sdhci-pltfm.h linux-4.9.y/drivers/mmc/host/sdhci-pltfm.h
--- linux-4.9.37/drivers/mmc/host/sdhci-pltfm.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/mmc/host/sdhci-pltfm.h 2021-06-07 13:01:33.000000000 +0300
@@ -109,6 +109,8 @@
return (void *)host->private;
}
+int sdhci_pltfm_suspend(struct device *dev);
+int sdhci_pltfm_resume(struct device *dev);
extern const struct dev_pm_ops sdhci_pltfm_pmops;
#endif /* _DRIVERS_MMC_SDHCI_PLTFM_H */
diff -urN linux-4.9.37/drivers/mmc/host/sdhci-proc.c linux-4.9.y/drivers/mmc/host/sdhci-proc.c
--- linux-4.9.37/drivers/mmc/host/sdhci-proc.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/mmc/host/sdhci-proc.c 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+#include "sdhci.h"
+#include "sdhci-proc.h"
+
+#define MCI_PARENT "mci"
+#define MCI_STATS_PROC "mci_info"
+#define MAX_CLOCK_SCALE 4
+
+unsigned int slot_index;
+struct mmc_host *mci_host[MCI_SLOT_NUM] = {NULL};
+static struct proc_dir_entry *proc_mci_dir;
+
+static char *card_type[MAX_CARD_TYPE + 1] = {
+ "MMC card",
+ "SD card",
+ "SDIO card",
+ "SD combo (IO+mem) card",
+ "unknown"
+};
+static char *clock_unit[MAX_CLOCK_SCALE] = {
+ "Hz",
+ "KHz",
+ "MHz",
+ "GHz"
+};
+
+static char *mci_get_card_type(unsigned int sd_type)
+{
+ if (sd_type >= MAX_CARD_TYPE)
+ return card_type[MAX_CARD_TYPE];
+ else
+ return card_type[sd_type];
+}
+
+static unsigned int analyze_clock_scale(unsigned int clock, unsigned int *clock_val)
+{
+ unsigned int scale = 0;
+ unsigned int tmp = clock;
+
+ while (1) {
+ tmp = tmp / 1000; /* 1000 for clk calculate */
+ if (tmp > 0) {
+ *clock_val = tmp;
+ scale++;
+ } else {
+ break;
+ }
+ }
+ return scale;
+}
+
+static inline int is_card_uhs(unsigned char timing)
+{
+ return timing >= MMC_TIMING_UHS_SDR12 &&
+ timing <= MMC_TIMING_UHS_DDR50;
+};
+
+static inline int is_card_hs(unsigned char timing)
+{
+ return timing == MMC_TIMING_SD_HS || timing == MMC_TIMING_MMC_HS;
+};
+
+static void mci_stats_seq_printout(struct seq_file *s)
+{
+ unsigned int index_mci;
+ unsigned int clock;
+ unsigned int clock_scale;
+ unsigned int clock_value = 0;
+ const char *type = NULL;
+ static struct mmc_host *mmc = NULL;
+ const char *uhs_bus_speed_mode = "";
+ static const char *uhs_speeds[] = {
+ [UHS_SDR12_BUS_SPEED] = "SDR12 ",
+ [UHS_SDR25_BUS_SPEED] = "SDR25 ",
+ [UHS_SDR50_BUS_SPEED] = "SDR50 ",
+ [UHS_SDR104_BUS_SPEED] = "SDR104 ",
+ [UHS_DDR50_BUS_SPEED] = "DDR50 ",
+ };
+ unsigned int speed_class, grade_speed_uhs;
+ struct card_info *info = NULL;
+ unsigned int present;
+ struct sdhci_host *host = NULL;
+
+ for (index_mci = 0; index_mci < MCI_SLOT_NUM; index_mci++) {
+ mmc = mci_host[index_mci];
+ if (mmc == NULL) {
+ seq_printf(s, "MCI%d: invalid\n", index_mci);
+ continue;
+ } else {
+ seq_printf(s, "MCI%d", index_mci);
+ }
+ host = mmc_priv(mmc);
+ info = &host->c_info;
+
+ present = host->mmc->ops->get_cd(host->mmc);
+ if (present)
+ seq_puts(s, ": pluged");
+ else
+ seq_puts(s, ": unplugged");
+
+ if (info->card_connect != CARD_CONNECT) {
+ if (mmc->card_status == MMC_CARD_INIT_FAIL)
+ seq_puts(s, "_init_failed\n");
+ else
+ seq_puts(s, "_disconnected\n");
+ } else {
+ seq_puts(s, "_connected\n");
+
+ seq_printf(s, "\tType: %s",
+ mci_get_card_type(info->card_type));
+
+ if (info->card_state & MMC_STATE_BLOCKADDR) {
+ if (info->card_state & MMC_CARD_SDXC)
+ type = "SDXC";
+ else
+ type = "SDHC";
+ seq_printf(s, "(%s)\n", type);
+ }
+
+ if (is_card_uhs(info->timing) &&
+ info->sd_bus_speed < ARRAY_SIZE(uhs_speeds))
+ uhs_bus_speed_mode =
+ uhs_speeds[info->sd_bus_speed];
+
+ seq_printf(s, "\tMode: %s%s%s%s\n",
+ is_card_uhs(info->timing) ? "UHS " :
+ (is_card_hs(info->timing) ? "HS " : ""),
+ info->timing == MMC_TIMING_MMC_HS400 ? "HS400 " :
+ (info->timing == MMC_TIMING_MMC_HS200 ? "HS200 " : ""),
+ info->timing == MMC_TIMING_MMC_DDR52 ? "DDR " : "",
+ uhs_bus_speed_mode);
+
+ speed_class = UNSTUFF_BITS(info->ssr, 56, 8); /* 56 equal 440 -384 */
+ grade_speed_uhs = UNSTUFF_BITS(info->ssr, 12, 4); /* 12 equal 396 - 384 */
+ seq_printf(s, "\tSpeed Class: Class %s\n",
+ (speed_class == 0x00) ? "0" :
+ (speed_class == 0x01) ? "2" :
+ (speed_class == 0x02) ? "4" :
+ (speed_class == 0x03) ? "6" :
+ (speed_class == 0x04) ? "10" :
+ "Reserved");
+ seq_printf(s, "\tUhs Speed Grade: %s\n",
+ (grade_speed_uhs == 0x00) ?
+ "Less than 10MB/sec(0h)" :
+ (grade_speed_uhs == 0x01) ?
+ "10MB/sec and above(1h)" :
+ "Reserved");
+
+ clock = info->card_support_clock;
+ clock_scale = analyze_clock_scale(clock, &clock_value);
+ seq_printf(s, "\tHost work clock: %d%s\n",
+ clock_value, clock_unit[clock_scale]);
+
+ clock = info->card_support_clock;
+ clock_scale = analyze_clock_scale(clock, &clock_value);
+ seq_printf(s, "\tCard support clock: %d%s\n",
+ clock_value, clock_unit[clock_scale]);
+
+ clock = mmc->actual_clock;
+ clock_scale = analyze_clock_scale(clock, &clock_value);
+ seq_printf(s, "\tCard work clock: %d%s\n",
+ clock_value, clock_unit[clock_scale]);
+
+ /* add card read/write error count */
+ seq_printf(s, "\tCard error count: %d\n",
+ host->error_count);
+ }
+ }
+}
+
+/* proc interface setup */
+static void *mci_seq_start(struct seq_file *s, loff_t *pos)
+{
+ /* counter is used to tracking multi proc interfaces
+ * We have only one interface so return zero
+ * pointer to start the sequence.
+ */
+ static unsigned long counter;
+
+ if (*pos == 0)
+ return &counter;
+
+ *pos = 0;
+ return NULL;
+}
+
+/* proc interface next */
+static void *mci_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+ (*pos)++;
+ if (*pos >= MCI_SLOT_NUM)
+ return NULL;
+
+ return NULL;
+}
+
+/* define parameters where showed in proc file */
+static int mci_stats_seq_show(struct seq_file *s, void *v)
+{
+ mci_stats_seq_printout(s);
+ return 0;
+}
+
+/* proc interface stop */
+static void mci_seq_stop(struct seq_file *s, void *v)
+{
+}
+
+/* proc interface operation */
+static const struct seq_operations mci_stats_seq_ops = {
+ .start = mci_seq_start,
+ .next = mci_seq_next,
+ .stop = mci_seq_stop,
+ .show = mci_stats_seq_show
+};
+
+/* proc file open */
+static int mci_stats_proc_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &mci_stats_seq_ops);
+};
+
+/* proc file operation */
+static const struct file_operations mci_stats_proc_ops = {
+ .owner = THIS_MODULE,
+ .open = mci_stats_proc_open,
+ .read = seq_read,
+ .release = seq_release
+};
+
+int mci_proc_init(void)
+{
+ struct proc_dir_entry *proc_stats_entry = NULL;
+
+ proc_mci_dir = proc_mkdir(MCI_PARENT, NULL);
+ if (!proc_mci_dir) {
+ pr_err("%s: failed to create proc file %s\n",
+ __func__, MCI_PARENT);
+ return 1;
+ }
+
+ proc_stats_entry = proc_create(MCI_STATS_PROC,
+ 0, proc_mci_dir, &mci_stats_proc_ops);
+ if (!proc_stats_entry) {
+ pr_err("%s: failed to create proc file %s\n",
+ __func__, MCI_STATS_PROC);
+ return 1;
+ }
+
+ return 0;
+}
+
+int mci_proc_shutdown(void)
+{
+ if (proc_mci_dir) {
+ remove_proc_entry(MCI_STATS_PROC, proc_mci_dir);
+ remove_proc_entry(MCI_PARENT, NULL);
+ proc_mci_dir = NULL;
+ }
+
+ return 0;
+}
diff -urN linux-4.9.37/drivers/mmc/host/sdhci-proc.h linux-4.9.y/drivers/mmc/host/sdhci-proc.h
--- linux-4.9.37/drivers/mmc/host/sdhci-proc.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/mmc/host/sdhci-proc.h 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+/*
+ * MCI connection table manager
+ */
+#ifndef __MCI_PROC_H__
+#define __MCI_PROC_H__
+
+#include <linux/proc_fs.h>
+
+#define MAX_CARD_TYPE 4
+#define MAX_SPEED_MODE 5
+
+
+
+#if defined(CONFIG_ARCH_GK7205V200) || defined(CONFIG_ARCH_GK7205V300) ||\
+ defined(CONFIG_ARCH_GK7202V300) || defined(CONFIG_ARCH_GK7605V100)
+ #define MCI_SLOT_NUM 3
+#endif
+
+extern unsigned int slot_index;
+extern struct mmc_host *mci_host[MCI_SLOT_NUM];
+
+int mci_proc_init(void);
+int mci_proc_shutdown(void);
+
+#endif /* __MCI_PROC_H__ */
diff -urN linux-4.9.37/drivers/mtd/Makefile linux-4.9.y/drivers/mtd/Makefile
--- linux-4.9.37/drivers/mtd/Makefile 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/mtd/Makefile 2021-06-07 13:01:33.000000000 +0300
@@ -30,7 +30,7 @@
nftl-objs := nftlcore.o nftlmount.o
inftl-objs := inftlcore.o inftlmount.o
+obj-$(CONFIG_MTD_SPI_NOR) += spi-nor/
obj-y += chips/ lpddr/ maps/ devices/ nand/ onenand/ tests/
-obj-$(CONFIG_MTD_SPI_NOR) += spi-nor/
obj-$(CONFIG_MTD_UBI) += ubi/
diff -urN linux-4.9.37/drivers/mtd/nand/gkfmc100/fmc100.c linux-4.9.y/drivers/mtd/nand/gkfmc100/fmc100.c
--- linux-4.9.37/drivers/mtd/nand/gkfmc100/fmc100.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/mtd/nand/gkfmc100/fmc100.c 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,1199 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/mtd/nand.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <asm/setup.h>
+
+#include "../nfc_gen.h"
+#include "fmc100.h"
+
+/*****************************************************************************/
+static void fmc100_switch_to_spi_nand(struct fmc_host *host)
+{
+ u32 reg;
+
+ reg = fmc_readl(host, FMC_CFG);
+ reg &= ~FLASH_TYPE_SEL_MASK;
+ reg |= FMC_CFG_FLASH_SEL(FLASH_TYPE_SPI_NAND);
+ fmc_writel(host, FMC_CFG, reg);
+}
+
+/*****************************************************************************/
+static void fmc100_set_str_mode(struct fmc_host *host)
+{
+ u32 reg;
+
+ reg = fmc_readl(host, FMC_GLOBAL_CFG);
+ reg &= (~FMC_GLOBAL_CFG_DTR_MODE);
+ fmc_writel(host, FMC_GLOBAL_CFG, reg);
+}
+
+/*****************************************************************************/
+static void fmc100_operation_config(struct fmc_host *host, int op)
+{
+ int ret, clkrate = 0;
+ struct fmc_spi *spi = host->spi;
+
+ fmc100_switch_to_spi_nand(host);
+ clk_prepare_enable(host->clk);
+ switch (op) {
+ case OP_STYPE_WRITE:
+ clkrate = min((u_long)host->clkrate,
+ (u_long)CLK_FMC_TO_CRG_MHZ(spi->write->clock));
+ break;
+ case OP_STYPE_READ:
+ clkrate = min((u_long)host->clkrate,
+ (u_long)CLK_FMC_TO_CRG_MHZ(spi->read->clock));
+ break;
+ case OP_STYPE_ERASE:
+ clkrate = min((u_long)host->clkrate,
+ (u_long)CLK_FMC_TO_CRG_MHZ(spi->erase->clock));
+ break;
+ default:
+ break;
+ }
+
+ ret = clk_set_rate(host->clk, clkrate);
+ if (WARN_ON(ret)) {
+ pr_err("clk_set_rate failed: %d\n", ret);
+ }
+}
+
+/*****************************************************************************/
+static void fmc100_send_cmd_write(struct fmc_host *host)
+{
+ unsigned char pages_per_block_shift;
+ unsigned int reg, block_num, block_num_h, page_num;
+ struct fmc_spi *spi = host->spi;
+ struct nand_chip *chip = host->chip;
+#ifdef FMC100_SPI_NAND_SUPPORT_REG_WRITE
+ const char *op = "Reg";
+#else
+ const char *op = "Dma";
+#endif
+
+ if (WR_DBG) {
+ pr_info("\n");
+ }
+ FMC_PR(WR_DBG, "*-Start send %s page write command\n", op);
+
+ mutex_lock(host->lock);
+ fmc100_operation_config(host, OP_STYPE_WRITE);
+
+ reg = spi->driver->wait_ready(spi);
+ if (reg) {
+ DB_MSG("Error: %s program wait ready failed! status: %#x\n",
+ op, reg);
+ goto end;
+ }
+
+ reg = spi->driver->write_enable(spi);
+ if (reg) {
+ DB_MSG("Error: %s program write enable failed! reg: %#x\n",
+ op, reg);
+ goto end;
+ }
+
+ reg = FMC_INT_CLR_ALL;
+ fmc_writel(host, FMC_INT_CLR, reg);
+ FMC_PR(WR_DBG, "|-Set INT_CLR[%#x]%#x\n", FMC_INT_CLR, reg);
+
+ reg = OP_CFG_FM_CS(host->cmd_op.cs)
+ | OP_CFG_MEM_IF_TYPE(spi->write->iftype)
+ | OP_CFG_OEN_EN;
+ fmc_writel(host, FMC_OP_CFG, reg);
+ FMC_PR(WR_DBG, "|-Set OP_CFG[%#x]%#x\n", FMC_OP_CFG, reg);
+
+ pages_per_block_shift = chip->phys_erase_shift - chip->page_shift;
+ block_num = host->addr_value[1] >> pages_per_block_shift;
+ block_num_h = block_num >> REG_CNT_HIGH_BLOCK_NUM_SHIFT;
+ reg = FMC_ADDRH_SET(block_num_h);
+ fmc_writel(host, FMC_ADDRH, reg);
+ FMC_PR(WR_DBG, "|-Set ADDRH[%#x]%#x\n", FMC_ADDRH, reg);
+
+ page_num = host->addr_value[1] - (block_num << pages_per_block_shift);
+ reg = ((block_num & REG_CNT_BLOCK_NUM_MASK) << REG_CNT_BLOCK_NUM_SHIFT)
+ | ((page_num & REG_CNT_PAGE_NUM_MASK) << REG_CNT_PAGE_NUM_SHIFT);
+ fmc_writel(host, FMC_ADDRL, reg);
+ FMC_PR(WR_DBG, "|-Set ADDRL[%#x]%#x\n", FMC_ADDRL, reg);
+
+ *host->epm = 0x0000;
+
+#ifndef FMC100_SPI_NAND_SUPPORT_REG_WRITE
+ reg = host->dma_buffer;
+ fmc_writel(host, FMC_DMA_SADDR_D0, reg);
+ FMC_PR(WR_DBG, "|-Set DMA_SADDR_D[0x40]%#x\n", reg);
+
+#ifdef CONFIG_64BIT
+ reg = (host->dma_buffer & FMC_DMA_SADDRH_MASK) >> 32;
+ fmc_writel(host, FMC_DMA_SADDRH_D0, reg);
+ FMC_PR(WR_DBG, "\t|-Set DMA_SADDRH_D0[%#x]%#x\n", FMC_DMA_SADDRH_D0, reg);
+#endif
+
+ reg = host->dma_oob;
+ fmc_writel(host, FMC_DMA_SADDR_OOB, reg);
+ FMC_PR(WR_DBG, "|-Set DMA_SADDR_OOB[%#x]%#x\n", FMC_DMA_SADDR_OOB, reg);
+#ifdef CONFIG_64BIT
+ reg = (host->dma_oob & FMC_DMA_SADDRH_MASK) >> 32;
+ fmc_writel(host, FMC_DMA_SADDRH_OOB, reg);
+ FMC_PR(WR_DBG, "\t|-Set DMA_SADDRH_OOB[%#x]%#x\n", FMC_DMA_SADDRH_OOB,
+ reg);
+#endif
+#endif
+
+ reg = OP_CTRL_WR_OPCODE(spi->write->cmd)
+#ifdef FMC100_SPI_NAND_SUPPORT_REG_WRITE
+ | OP_CTRL_DMA_OP(OP_TYPE_REG)
+#else
+ | OP_CTRL_DMA_OP(OP_TYPE_DMA)
+#endif
+ | OP_CTRL_RW_OP(RW_OP_WRITE)
+ | OP_CTRL_DMA_OP_READY;
+ fmc_writel(host, FMC_OP_CTRL, reg);
+ FMC_PR(WR_DBG, "|-Set OP_CTRL[%#x]%#x\n", FMC_OP_CTRL, reg);
+
+ FMC_DMA_WAIT_INT_FINISH(host);
+
+end:
+ mutex_unlock(host->lock);
+ FMC_PR(WR_DBG, "*-End %s page program!\n", op);
+}
+
+/*****************************************************************************/
+static void fmc100_send_cmd_status(struct fmc_host *host)
+{
+ unsigned char status, addr = STATUS_ADDR;
+ struct fmc_spi *spi = host->spi;
+
+ if (host->cmd_op.l_cmd == NAND_CMD_GET_FEATURES) {
+ addr = PROTECT_ADDR;
+ }
+
+ status = spi_nand_feature_op(spi, GET_OP, addr, 0);
+ FMC_PR((ER_DBG || WR_DBG), "\t*-Get status[%#x]: %#x\n", addr, status);
+}
+
+/*****************************************************************************/
+static void fmc100_send_cmd_read(struct fmc_host *host)
+{
+ unsigned char pages_per_block_shift, only_oob = 0;
+ unsigned short wrap = 0;
+ unsigned int reg, block_num, block_num_h, page_num, addr_of = 0;
+ struct fmc_spi *spi = host->spi;
+ struct nand_chip *chip = host->chip;
+#ifdef FMC100_SPI_NAND_SUPPORT_REG_READ
+ char *op = "Reg";
+#else
+ char *op = "Dma";
+#endif
+
+ if (RD_DBG) {
+ pr_info("\n");
+ }
+ FMC_PR(RD_DBG, "\t*-Start %s page read\n", op);
+
+ if ((host->addr_value[0] == host->cache_addr_value[0])
+ && (host->addr_value[1] == host->cache_addr_value[1])) {
+ FMC_PR(RD_DBG, "\t*-%s read cache hit, addr[%#x %#x]\n",
+ op, host->addr_value[1], host->addr_value[0]);
+ return;
+ }
+
+ mutex_lock(host->lock);
+ fmc100_operation_config(host, OP_STYPE_READ);
+
+ FMC_PR(RD_DBG, "\t|-Wait ready before %s page read\n", op);
+ reg = spi->driver->wait_ready(spi);
+ if (reg) {
+ DB_MSG("Error: %s read wait ready fail! reg: %#x\n", op, reg);
+ goto end;
+ }
+
+ reg = FMC_INT_CLR_ALL;
+ fmc_writel(host, FMC_INT_CLR, reg);
+ FMC_PR(RD_DBG, "\t|-Set INT_CLR[%#x]%#x\n", FMC_INT_CLR, reg);
+
+ if (host->cmd_op.l_cmd == NAND_CMD_READOOB) {
+ only_oob = 1;
+ host->cmd_op.op_cfg = OP_CTRL_RD_OP_SEL(RD_OP_READ_OOB);
+ } else {
+ host->cmd_op.op_cfg = OP_CTRL_RD_OP_SEL(RD_OP_READ_ALL_PAGE);
+ }
+
+ reg = OP_CFG_FM_CS(host->cmd_op.cs)
+ | OP_CFG_MEM_IF_TYPE(spi->read->iftype)
+ | OP_CFG_DUMMY_NUM(spi->read->dummy)
+ | OP_CFG_OEN_EN;
+ fmc_writel(host, FMC_OP_CFG, reg);
+ FMC_PR(RD_DBG, "\t|-Set OP_CFG[%#x]%#x\n", FMC_OP_CFG, reg);
+
+ pages_per_block_shift = chip->phys_erase_shift - chip->page_shift;
+ block_num = host->addr_value[1] >> pages_per_block_shift;
+ block_num_h = block_num >> REG_CNT_HIGH_BLOCK_NUM_SHIFT;
+
+ reg = FMC_ADDRH_SET(block_num_h);
+ fmc_writel(host, FMC_ADDRH, reg);
+ FMC_PR(RD_DBG, "\t|-Set ADDRH[%#x]%#x\n", FMC_ADDRH, reg);
+
+ page_num = host->addr_value[1] - (block_num << pages_per_block_shift);
+ if (only_oob)
+ switch (host->ecctype) {
+ case NAND_ECC_8BIT:
+ addr_of = REG_CNT_ECC_8BIT_OFFSET;
+ break;
+ case NAND_ECC_16BIT:
+ addr_of = REG_CNT_ECC_16BIT_OFFSET;
+ break;
+ case NAND_ECC_24BIT:
+ addr_of = REG_CNT_ECC_24BIT_OFFSET;
+ break;
+ case NAND_ECC_0BIT:
+ default:
+ break;
+ }
+
+ reg = ((block_num & REG_CNT_BLOCK_NUM_MASK) << REG_CNT_BLOCK_NUM_SHIFT)
+ | ((page_num & REG_CNT_PAGE_NUM_MASK) << REG_CNT_PAGE_NUM_SHIFT)
+ | ((wrap & REG_CNT_WRAP_MASK) << REG_CNT_WRAP_SHIFT)
+ | (addr_of & REG_CNT_ECC_OFFSET_MASK);
+ fmc_writel(host, FMC_ADDRL, reg);
+ FMC_PR(RD_DBG, "\t|-Set ADDRL[%#x]%#x\n", FMC_ADDRL, reg);
+
+#ifndef FMC100_SPI_NAND_SUPPORT_REG_READ
+ reg = host->dma_buffer;
+ fmc_writel(host, FMC_DMA_SADDR_D0, reg);
+ FMC_PR(RD_DBG, "\t|-Set DMA_SADDR_D0[%#x]%#x\n", FMC_DMA_SADDR_D0, reg);
+
+#ifdef CONFIG_64BIT
+ reg = (host->dma_buffer & FMC_DMA_SADDRH_MASK) >> 32;
+ fmc_writel(host, FMC_DMA_SADDRH_D0, reg);
+ FMC_PR(RD_DBG, "\t|-Set DMA_SADDRH_D0[%#x]%#x\n", FMC_DMA_SADDRH_D0, reg);
+#endif
+
+ reg = host->dma_oob;
+ fmc_writel(host, FMC_DMA_SADDR_OOB, reg);
+ FMC_PR(RD_DBG, "\t|-Set DMA_SADDR_OOB[%#x]%#x\n", FMC_DMA_SADDR_OOB,
+ reg);
+
+#ifdef CONFIG_64BIT
+ reg = (host->dma_oob & FMC_DMA_SADDRH_MASK) >> 32;
+ fmc_writel(host, FMC_DMA_SADDRH_OOB, reg);
+ FMC_PR(RD_DBG, "\t|-Set DMA_SADDRH_OOB[%#x]%#x\n", FMC_DMA_SADDRH_OOB,
+ reg);
+#endif
+#endif
+
+ reg = OP_CTRL_RD_OPCODE(spi->read->cmd) | host->cmd_op.op_cfg
+#ifdef FMC100_SPI_NAND_SUPPORT_REG_READ
+ | OP_CTRL_DMA_OP(OP_TYPE_REG)
+#else
+ | OP_CTRL_DMA_OP(OP_TYPE_DMA)
+#endif
+ | OP_CTRL_RW_OP(RW_OP_READ) | OP_CTRL_DMA_OP_READY;
+ fmc_writel(host, FMC_OP_CTRL, reg);
+ FMC_PR(RD_DBG, "\t|-Set OP_CTRL[%#x]%#x\n", FMC_OP_CTRL, reg);
+
+ FMC_DMA_WAIT_INT_FINISH(host);
+
+ host->cache_addr_value[0] = host->addr_value[0];
+ host->cache_addr_value[1] = host->addr_value[1];
+
+end:
+ mutex_unlock(host->lock);
+ FMC_PR(RD_DBG, "\t*-End %s page read\n", op);
+}
+
+/*****************************************************************************/
+static void fmc100_send_cmd_erase(struct fmc_host *host)
+{
+ unsigned int reg;
+ struct fmc_spi *spi = host->spi;
+
+ if (ER_DBG) {
+ pr_info("\n");
+ }
+ FMC_PR(ER_DBG, "\t*-Start send cmd erase!\n");
+
+ mutex_lock(host->lock);
+ fmc100_operation_config(host, OP_STYPE_ERASE);
+
+ reg = spi->driver->wait_ready(spi);
+ FMC_PR(ER_DBG, "\t|-Erase wait ready, reg: %#x\n", reg);
+ if (reg) {
+ DB_MSG("Error: Erase wait ready fail! status: %#x\n", reg);
+ goto end;
+ }
+
+ reg = spi->driver->write_enable(spi);
+ if (reg) {
+ DB_MSG("Error: Erase write enable failed! reg: %#x\n", reg);
+ goto end;
+ }
+
+ reg = FMC_INT_CLR_ALL;
+ fmc_writel(host, FMC_INT_CLR, reg);
+ FMC_PR(ER_DBG, "\t|-Set INT_CLR[%#x]%#x\n", FMC_INT_CLR, reg);
+
+ reg = spi->erase->cmd;
+ fmc_writel(host, FMC_CMD, FMC_CMD_CMD1(reg));
+ FMC_PR(ER_DBG, "\t|-Set CMD[%#x]%#x\n", FMC_CMD, reg);
+
+ reg = FMC_ADDRL_BLOCK_H_MASK(host->addr_value[1])
+ | FMC_ADDRL_BLOCK_L_MASK(host->addr_value[0]);
+ fmc_writel(host, FMC_ADDRL, reg);
+ FMC_PR(ER_DBG, "\t|-Set ADDRL[%#x]%#x\n", FMC_ADDRL, reg);
+
+ reg = OP_CFG_FM_CS(host->cmd_op.cs)
+ | OP_CFG_MEM_IF_TYPE(spi->erase->iftype)
+ | OP_CFG_ADDR_NUM(STD_OP_ADDR_NUM)
+ | OP_CFG_DUMMY_NUM(spi->erase->dummy)
+ | OP_CFG_OEN_EN;
+ fmc_writel(host, FMC_OP_CFG, reg);
+ FMC_PR(ER_DBG, "\t|-Set OP_CFG[%#x]%#x\n", FMC_OP_CFG, reg);
+
+ reg = FMC_OP_CMD1_EN
+ | FMC_OP_ADDR_EN
+ | FMC_OP_REG_OP_START;
+ fmc_writel(host, FMC_OP, reg);
+ FMC_PR(ER_DBG, "\t|-Set OP[%#x]%#x\n", FMC_OP, reg);
+
+ FMC_CMD_WAIT_CPU_FINISH(host);
+
+end:
+ mutex_unlock(host->lock);
+ FMC_PR(ER_DBG, "\t*-End send cmd erase!\n");
+}
+
+/*****************************************************************************/
+void fmc100_ecc0_switch(struct fmc_host *host, unsigned char op)
+{
+ unsigned int config;
+#if EC_DBG
+ unsigned int cmp_cfg;
+
+ config = fmc_readl(host, FMC_CFG);
+ FMC_PR(EC_DBG, "\t *-Get CFG[%#x]%#x\n", FMC_CFG, config);
+
+ if (op) {
+ cmp_cfg = host->fmc_cfg;
+ } else {
+ cmp_cfg = host->fmc_cfg_ecc0;
+ }
+
+ if (cmp_cfg != config)
+ DB_MSG("Warning: FMC config[%#x] is different.\n",
+ cmp_cfg);
+#endif
+
+ if (op == ENABLE) {
+ config = host->fmc_cfg_ecc0;
+ } else if (op == DISABLE) {
+ config = host->fmc_cfg;
+ } else {
+ DB_MSG("Error: Invalid opcode: %d\n", op);
+ return;
+ }
+
+ fmc_writel(host, FMC_CFG, config);
+ FMC_PR(EC_DBG, "\t *-Set CFG[%#x]%#x\n", FMC_CFG, config);
+}
+
+/*****************************************************************************/
+static void fmc100_send_cmd_readid(struct fmc_host *host)
+{
+ unsigned int reg;
+
+ FMC_PR(BT_DBG, "\t|*-Start send cmd read ID\n");
+
+ fmc100_ecc0_switch(host, ENABLE);
+
+ reg = FMC_CMD_CMD1(SPI_CMD_RDID);
+ fmc_writel(host, FMC_CMD, reg);
+ FMC_PR(BT_DBG, "\t||-Set CMD[%#x]%#x\n", FMC_CMD, reg);
+
+ reg = READ_ID_ADDR;
+ fmc_writel(host, FMC_ADDRL, reg);
+ FMC_PR(BT_DBG, "\t||-Set ADDRL[%#x]%#x\n", FMC_ADDRL, reg);
+
+ reg = OP_CFG_FM_CS(host->cmd_op.cs)
+ | OP_CFG_ADDR_NUM(READ_ID_ADDR_NUM)
+ | OP_CFG_OEN_EN;
+ fmc_writel(host, FMC_OP_CFG, reg);
+ FMC_PR(BT_DBG, "\t||-Set OP_CFG[%#x]%#x\n", FMC_OP_CFG, reg);
+
+ reg = FMC_DATA_NUM_CNT(MAX_SPI_NAND_ID_LEN);
+ fmc_writel(host, FMC_DATA_NUM, reg);
+ FMC_PR(BT_DBG, "\t||-Set DATA_NUM[%#x]%#x\n", FMC_DATA_NUM, reg);
+
+ reg = FMC_OP_CMD1_EN
+ | FMC_OP_ADDR_EN
+ | FMC_OP_READ_DATA_EN
+ | FMC_OP_REG_OP_START;
+ fmc_writel(host, FMC_OP, reg);
+ FMC_PR(BT_DBG, "\t||-Set OP[%#x]%#x\n", FMC_OP, reg);
+
+ host->addr_cycle = 0x0;
+
+ FMC_CMD_WAIT_CPU_FINISH(host);
+
+ fmc100_ecc0_switch(host, DISABLE);
+
+ FMC_PR(BT_DBG, "\t|*-End read flash ID\n");
+}
+
+/*****************************************************************************/
+static void fmc100_send_cmd_reset(struct fmc_host *host)
+{
+ unsigned int reg;
+
+ FMC_PR(BT_DBG, "\t|*-Start send cmd reset\n");
+
+ reg = FMC_CMD_CMD1(SPI_CMD_RESET);
+ fmc_writel(host, FMC_CMD, reg);
+ FMC_PR(BT_DBG, "\t||-Set CMD[%#x]%#x\n", FMC_CMD, reg);
+
+ reg = OP_CFG_FM_CS(host->cmd_op.cs) | OP_CFG_OEN_EN;
+ fmc_writel(host, FMC_OP_CFG, reg);
+ FMC_PR(BT_DBG, "\t||-Set OP_CFG[%#x]%#x\n", FMC_OP_CFG, reg);
+
+ reg = FMC_OP_CMD1_EN | FMC_OP_REG_OP_START;
+ fmc_writel(host, FMC_OP, reg);
+ FMC_PR(BT_DBG, "\t||-Set OP[%#x]%#x\n", FMC_OP, reg);
+
+ FMC_CMD_WAIT_CPU_FINISH(host);
+
+ FMC_PR(BT_DBG, "\t|*-End send cmd reset\n");
+}
+
+/*****************************************************************************/
+static void fmc100_host_init(struct fmc_host *host)
+{
+ unsigned int reg;
+
+ FMC_PR(BT_DBG, "\t||*-Start SPI Nand host init\n");
+
+ reg = fmc_readl(host, FMC_CFG);
+ if ((reg & FMC_CFG_OP_MODE_MASK) == FMC_CFG_OP_MODE_BOOT) {
+ reg |= FMC_CFG_OP_MODE(FMC_CFG_OP_MODE_NORMAL);
+ fmc_writel(host, FMC_CFG, reg);
+ FMC_PR(BT_DBG, "\t|||-Set CFG[%#x]%#x\n", FMC_CFG, reg);
+ }
+
+ host->fmc_cfg = reg;
+ host->fmc_cfg_ecc0 = (reg & ~ECC_TYPE_MASK) | ECC_TYPE_0BIT;
+
+ reg = fmc_readl(host, FMC_GLOBAL_CFG);
+ if (reg & FMC_GLOBAL_CFG_WP_ENABLE) {
+ reg &= ~FMC_GLOBAL_CFG_WP_ENABLE;
+ fmc_writel(host, FMC_GLOBAL_CFG, reg);
+ }
+
+ host->addr_cycle = 0;
+ host->addr_value[0] = 0;
+ host->addr_value[1] = 0;
+ host->cache_addr_value[0] = ~0;
+ host->cache_addr_value[1] = ~0;
+
+ host->send_cmd_write = fmc100_send_cmd_write;
+ host->send_cmd_status = fmc100_send_cmd_status;
+ host->send_cmd_read = fmc100_send_cmd_read;
+ host->send_cmd_erase = fmc100_send_cmd_erase;
+ host->send_cmd_readid = fmc100_send_cmd_readid;
+ host->send_cmd_reset = fmc100_send_cmd_reset;
+#ifdef CONFIG_PM
+ host->suspend = fmc100_suspend;
+ host->resume = fmc100_resume;
+#endif
+
+ reg = TIMING_CFG_TCSH(CS_HOLD_TIME)
+ | TIMING_CFG_TCSS(CS_SETUP_TIME)
+ | TIMING_CFG_TSHSL(CS_DESELECT_TIME);
+ fmc_writel(host, FMC_SPI_TIMING_CFG, reg);
+
+ reg = ALL_BURST_ENABLE;
+ fmc_writel(host, FMC_DMA_AHB_CTRL, reg);
+
+ FMC_PR(BT_DBG, "\t||*-End SPI Nand host init\n");
+}
+
+/*****************************************************************************/
+static unsigned char fmc100_read_byte(struct mtd_info *mtd)
+{
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct fmc_host *host = chip->priv;
+ unsigned char value, ret_val = 0;
+
+ if (host->cmd_op.l_cmd == NAND_CMD_READID) {
+ value = fmc_readb(host->iobase + host->offset);
+ host->offset++;
+ if (host->cmd_op.data_no == host->offset) {
+ host->cmd_op.l_cmd = 0;
+ }
+ return value;
+ }
+
+ if (host->cmd_op.cmd == NAND_CMD_STATUS) {
+ value = fmc_readl(host, FMC_STATUS);
+ if (host->cmd_op.l_cmd == NAND_CMD_GET_FEATURES) {
+ FMC_PR((ER_DBG || WR_DBG), "\t\tRead BP status:%#x\n",
+ value);
+ if (ANY_BP_ENABLE(value)) {
+ ret_val |= NAND_STATUS_WP;
+ }
+
+ host->cmd_op.l_cmd = NAND_CMD_STATUS;
+ }
+
+ if (!(value & STATUS_OIP_MASK)) {
+ ret_val |= NAND_STATUS_READY;
+ }
+
+ if (value & STATUS_E_FAIL_MASK) {
+ FMC_PR(ER_DBG, "\t\tGet erase status: %#x\n", value);
+ ret_val |= NAND_STATUS_FAIL;
+ }
+
+ if (value & STATUS_P_FAIL_MASK) {
+ FMC_PR(WR_DBG, "\t\tGet write status: %#x\n", value);
+ ret_val |= NAND_STATUS_FAIL;
+ }
+
+ return ret_val;
+ }
+
+ if (host->cmd_op.l_cmd == NAND_CMD_READOOB) {
+ value = fmc_readb(host->buffer + host->pagesize + host->offset);
+ host->offset++;
+ return value;
+ }
+
+ host->offset++;
+
+ return fmc_readb(host->buffer + host->column + host->offset - 1);
+}
+
+/*****************************************************************************/
+static unsigned short fmc100_read_word(struct mtd_info *mtd)
+{
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct fmc_host *host = chip->priv;
+
+ host->offset += 2;
+ return fmc_readw(host->buffer + host->column + host->offset - 2);
+}
+
+/*****************************************************************************/
+static void fmc100_write_buf(struct mtd_info *mtd,
+ const u_char *buf, int len)
+{
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct fmc_host *host = chip->priv;
+
+#ifdef FMC100_SPI_NAND_SUPPORT_REG_WRITE
+ if (buf == chip->oob_poi) {
+ memcpy((char *)host->iobase + host->pagesize, buf, len);
+ } else {
+ memcpy((char *)host->iobase, buf, len);
+ }
+#else
+ if (buf == chip->oob_poi) {
+ memcpy((char *)(host->buffer + host->pagesize), buf, len);
+ } else {
+ memcpy((char *)host->buffer, buf, len);
+ }
+#endif
+ return;
+}
+
+/*****************************************************************************/
+static void fmc100_read_buf(struct mtd_info *mtd, u_char *buf, int len)
+{
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct fmc_host *host = chip->priv;
+
+#ifdef FMC100_SPI_NAND_SUPPORT_REG_READ
+ if (buf == chip->oob_poi) {
+ memcpy(buf, (char *)host->iobase + host->pagesize, len);
+ } else {
+ memcpy(buf, (char *)host->iobase, len);
+ }
+#else
+ if (buf == chip->oob_poi) {
+ memcpy(buf, (char *)host->buffer + host->pagesize, len);
+ } else {
+ memcpy(buf, (char *)host->buffer, len);
+ }
+#endif
+
+#ifdef CONFIG_GOKE_NAND_ECC_STATUS_REPORT
+ if (buf != chip->oob_poi) {
+ u_int reg, ecc_step = host->pagesize >> 10;
+
+ reg = fmc_readl(host, FMC100_ECC_ERR_NUM0_BUF0);
+ while (ecc_step) {
+ u_char err_num;
+
+ err_num = GET_ECC_ERR_NUM(--ecc_step, reg);
+ if (err_num == 0xff) {
+ mtd->ecc_stats.failed++;
+ } else {
+ mtd->ecc_stats.corrected += err_num;
+ }
+ }
+ }
+#endif
+
+ return;
+}
+
+/*****************************************************************************/
+static void fmc100_select_chip(struct mtd_info *mtd, int chipselect)
+{
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct fmc_host *host = chip->priv;
+
+ if (chipselect < 0) {
+ mutex_unlock(&fmc_switch_mutex);
+ return;
+ }
+
+ mutex_lock(&fmc_switch_mutex);
+
+ if (chipselect > CONFIG_SPI_NAND_MAX_CHIP_NUM) {
+ DB_BUG("Error: Invalid chipselect: %d\n", chipselect);
+ }
+
+ if (host->mtd != mtd) {
+ host->mtd = mtd;
+ host->cmd_op.cs = chipselect;
+ }
+
+ if (!(chip->options & NAND_BROKEN_XD)) {
+ if ((chip->state == FL_ERASING) || (chip->state == FL_WRITING)) {
+ host->cmd_op.l_cmd = NAND_CMD_GET_FEATURES;
+ }
+ }
+}
+
+/*****************************************************************************/
+static void fmc100_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned ctrl)
+{
+ unsigned char cmd;
+ int is_cache_invalid = 1;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct fmc_host *host = chip->priv;
+ unsigned int udat = (unsigned int)dat;
+
+ if (ctrl & NAND_ALE) {
+ unsigned int addr_value = 0;
+ unsigned int addr_offset = 0;
+
+ if (ctrl & NAND_CTRL_CHANGE) {
+ host->addr_cycle = 0x0;
+ host->addr_value[0] = 0x0;
+ host->addr_value[1] = 0x0;
+ }
+ addr_offset = host->addr_cycle << 3;
+
+ if (host->addr_cycle >= FMC100_ADDR_CYCLE_MASK) {
+ addr_offset = (host->addr_cycle -
+ FMC100_ADDR_CYCLE_MASK) << 3;
+ addr_value = 1;
+ }
+ host->addr_value[addr_value] |=
+ ((udat & 0xff) << addr_offset);
+
+ host->addr_cycle++;
+ }
+
+ if ((ctrl & NAND_CLE) && (ctrl & NAND_CTRL_CHANGE)) {
+ cmd = udat & 0xff;
+ host->cmd_op.cmd = cmd;
+ switch (cmd) {
+ case NAND_CMD_PAGEPROG:
+ host->offset = 0;
+ host->send_cmd_write(host);
+ break;
+
+ case NAND_CMD_READSTART:
+ is_cache_invalid = 0;
+ if (host->addr_value[0] == host->pagesize) {
+ host->cmd_op.l_cmd = NAND_CMD_READOOB;
+ }
+ host->send_cmd_read(host);
+ break;
+
+ case NAND_CMD_ERASE2:
+ host->send_cmd_erase(host);
+ break;
+
+ case NAND_CMD_READID:
+ memset((u_char *)(host->iobase), 0,
+ MAX_SPI_NAND_ID_LEN);
+ host->cmd_op.l_cmd = cmd;
+ host->cmd_op.data_no = MAX_SPI_NAND_ID_LEN;
+ host->send_cmd_readid(host);
+ break;
+
+ case NAND_CMD_STATUS:
+ host->send_cmd_status(host);
+ break;
+
+ case NAND_CMD_READ0:
+ host->cmd_op.l_cmd = cmd;
+ break;
+
+ case NAND_CMD_RESET:
+ host->send_cmd_reset(host);
+ break;
+
+ case NAND_CMD_SEQIN:
+ case NAND_CMD_ERASE1:
+ default:
+ break;
+ }
+ }
+
+ if ((dat == NAND_CMD_NONE) && host->addr_cycle) {
+ if (host->cmd_op.cmd == NAND_CMD_SEQIN
+ || host->cmd_op.cmd == NAND_CMD_READ0
+ || host->cmd_op.cmd == NAND_CMD_READID) {
+ host->offset = 0x0;
+ host->column = (host->addr_value[0] & 0xffff);
+ }
+ }
+
+ if (is_cache_invalid) {
+ host->cache_addr_value[0] = ~0;
+ host->cache_addr_value[1] = ~0;
+ }
+}
+
+/*****************************************************************************/
+static int fmc100_dev_ready(struct mtd_info *mtd)
+{
+ unsigned int reg;
+ unsigned long deadline = jiffies + FMC_MAX_READY_WAIT_JIFFIES;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct fmc_host *host = chip->priv;
+
+ do {
+ reg = OP_CFG_FM_CS(host->cmd_op.cs) | OP_CFG_OEN_EN;
+ fmc_writel(host, FMC_OP_CFG, reg);
+
+ reg = FMC_OP_READ_STATUS_EN | FMC_OP_REG_OP_START;
+ fmc_writel(host, FMC_OP, reg);
+
+ FMC_CMD_WAIT_CPU_FINISH(host);
+
+ reg = fmc_readl(host, FMC_STATUS);
+
+ if (!(reg & STATUS_OIP_MASK)) {
+ return NAND_STATUS_READY;
+ }
+
+ cond_resched();
+
+ } while (!time_after_eq(jiffies, deadline));
+
+ if (!(chip->options & NAND_SCAN_SILENT_NODEV)) {
+ pr_warn("Wait SPI nand ready timeout, status: %#x\n", reg);
+ }
+
+ return 0;
+}
+
+/*****************************************************************************/
+/*
+ * 'host->epm' only use the first oobfree[0] field, it looks very simple, But...
+ */
+/* Default OOB area layout */
+static int fmc_ooblayout_ecc_default(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *oobregion)
+{
+ if (section) {
+ return -ERANGE;
+ }
+
+ oobregion->length = 32;
+ oobregion->offset = 32;
+
+ return 0;
+}
+
+static int fmc_ooblayout_free_default(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *oobregion)
+{
+ if (section) {
+ return -ERANGE;
+ }
+
+ oobregion->length = 30;
+ oobregion->offset = 2;
+
+ return 0;
+}
+
+static struct mtd_ooblayout_ops fmc_ooblayout_default_ops = {
+ .ecc = fmc_ooblayout_ecc_default,
+ .free = fmc_ooblayout_free_default,
+};
+
+#ifdef CONFIG_GOKE_NAND_FS_MAY_NO_YAFFS2
+static int fmc_ooblayout_ecc_4k16bit(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *oobregion)
+{
+ if (section) {
+ return -ERANGE;
+ }
+
+ oobregion->length = 14;
+ oobregion->offset = 14;
+
+ return 0;
+}
+
+static int fmc_ooblayout_free_4k16bit(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *oobregion)
+{
+ if (section) {
+ return -ERANGE;
+ }
+
+ oobregion->length = 14;
+ oobregion->offset = 2;
+
+ return 0;
+}
+
+static struct mtd_ooblayout_ops fmc_ooblayout_4k16bit_ops = {
+ .ecc = fmc_ooblayout_ecc_4k16bit,
+ .free = fmc_ooblayout_free_4k16bit,
+};
+
+static int fmc_ooblayout_ecc_2k16bit(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *oobregion)
+{
+ if (section) {
+ return -ERANGE;
+ }
+
+ oobregion->length = 6;
+ oobregion->offset = 6;
+
+ return 0;
+}
+
+static int fmc_ooblayout_free_2k16bit(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *oobregion)
+{
+ if (section) {
+ return -ERANGE;
+ }
+
+ oobregion->length = 6;
+ oobregion->offset = 2;
+
+ return 0;
+}
+
+static struct mtd_ooblayout_ops fmc_ooblayout_2k16bit_ops = {
+ .ecc = fmc_ooblayout_ecc_2k16bit,
+ .free = fmc_ooblayout_free_2k16bit,
+};
+#endif
+
+/*****************************************************************************/
+static struct nand_config_info fmc_spi_nand_config_table[] = {
+ {NAND_PAGE_4K, NAND_ECC_24BIT, 24, 200, &fmc_ooblayout_default_ops},
+#ifdef CONFIG_GOKE_NAND_FS_MAY_NO_YAFFS2
+ {NAND_PAGE_4K, NAND_ECC_16BIT, 16, 128, &fmc_ooblayout_4k16bit_ops},
+#endif
+ {NAND_PAGE_4K, NAND_ECC_8BIT, 8, 128, &fmc_ooblayout_default_ops},
+ {NAND_PAGE_4K, NAND_ECC_0BIT, 0, 32, &fmc_ooblayout_default_ops},
+
+ {NAND_PAGE_2K, NAND_ECC_24BIT, 24, 128, &fmc_ooblayout_default_ops},
+#ifdef CONFIG_GOKE_NAND_FS_MAY_NO_YAFFS2
+ {NAND_PAGE_2K, NAND_ECC_16BIT, 16, 64, &fmc_ooblayout_2k16bit_ops},
+#endif
+ {NAND_PAGE_2K, NAND_ECC_8BIT, 8, 64, &fmc_ooblayout_default_ops},
+ {NAND_PAGE_2K, NAND_ECC_0BIT, 0, 32, &fmc_ooblayout_default_ops},
+
+ {0, 0, 0, 0, NULL},
+};
+
+/*
+ * Auto-sensed the page size and ecc type value. driver will try each of page
+ * size and ecc type one by one till flash can be read and wrote accurately.
+ * so the page size and ecc type is match adaptively without switch on the board
+ */
+static struct nand_config_info *fmc100_get_config_type_info(
+ struct mtd_info *mtd, struct nand_dev_t *nand_dev)
+{
+ struct nand_config_info *best = NULL;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct nand_config_info *info = fmc_spi_nand_config_table;
+
+ nand_dev->start_type = "Auto";
+
+ for (; info->ooblayout_ops; info++) {
+ if (match_page_type_to_size(info->pagetype) != mtd->writesize) {
+ continue;
+ }
+
+ if (mtd->oobsize < info->oobsize) {
+ continue;
+ }
+
+ if (!best || (best->ecctype < info->ecctype)) {
+ best = info;
+ }
+ }
+
+ /* All SPI NAND are small-page, SLC */
+ chip->bits_per_cell = 1;
+
+ return best;
+}
+
+/*****************************************************************************/
+static void fmc100_chip_init(struct nand_chip *chip)
+{
+ chip->read_byte = fmc100_read_byte;
+ chip->read_word = fmc100_read_word;
+ chip->write_buf = fmc100_write_buf;
+ chip->read_buf = fmc100_read_buf;
+
+ chip->select_chip = fmc100_select_chip;
+
+ chip->cmd_ctrl = fmc100_cmd_ctrl;
+ chip->dev_ready = fmc100_dev_ready;
+
+ chip->chip_delay = FMC_CHIP_DELAY;
+
+ chip->options = NAND_SKIP_BBTSCAN | NAND_BROKEN_XD
+ | NAND_SCAN_SILENT_NODEV;
+
+ chip->ecc.mode = NAND_ECC_NONE;
+}
+
+/*****************************************************************************/
+static void fmc100_set_oob_info(struct mtd_info *mtd,
+ struct nand_config_info *info, struct nand_dev_t *nand_dev)
+{
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct fmc_host *host = chip->priv;
+ struct mtd_oob_region fmc_oobregion = {0, 0};
+
+ if (info->ecctype != NAND_ECC_0BIT) {
+ mtd->oobsize = info->oobsize;
+ }
+
+ host->oobsize = mtd->oobsize;
+ nand_dev->oobsize = host->oobsize;
+
+ host->dma_oob = host->dma_buffer + host->pagesize;
+ host->bbm = (u_char *)(host->buffer + host->pagesize
+ + FMC_BAD_BLOCK_POS);
+
+ info->ooblayout_ops->free(mtd, 0, &fmc_oobregion);
+
+ mtd_set_ooblayout(mtd, info->ooblayout_ops);
+
+ /* EB bits locate in the bottom two of CTRL(30) */
+ host->epm = (u_short *)(host->buffer + host->pagesize
+ + fmc_oobregion.offset + 28);
+
+#ifdef CONFIG_GOKE_NAND_FS_MAY_NO_YAFFS2
+ if (best->ecctype == NAND_ECC_16BIT) {
+ if (host->pagesize == _2K) {
+ /* EB bits locate in the bottom two of CTRL(4) */
+ host->epm = (u_short *)(host->buffer + host->pagesize
+ + fmc_oobregion.offset + 4);
+ } else if (host->pagesize == _4K) {
+ /* EB bit locate in the bottom two of CTRL(14) */
+ host->epm = (u_short *)(host->buffer + host->pagesize
+ + fmc_oobregion.offset + 12);
+ }
+ }
+#endif
+}
+
+/*****************************************************************************/
+static unsigned int fmc100_get_ecc_reg(struct fmc_host *host,
+ struct nand_config_info *info, struct nand_dev_t *nand_dev)
+{
+ host->ecctype = info->ecctype;
+ nand_dev->ecctype = host->ecctype;
+
+ return FMC_CFG_ECC_TYPE(match_ecc_type_to_reg(info->ecctype));
+}
+
+/*****************************************************************************/
+static unsigned int fmc100_get_page_reg(struct fmc_host *host,
+ struct nand_config_info *info)
+{
+ host->pagesize = match_page_type_to_size(info->pagetype);
+
+ return FMC_CFG_PAGE_SIZE(match_page_type_to_reg(info->pagetype));
+}
+
+/*****************************************************************************/
+static unsigned int fmc100_get_block_reg(struct fmc_host *host,
+ struct nand_config_info *info)
+{
+ unsigned int block_reg = 0, page_per_block;
+ struct mtd_info *mtd = host->mtd;
+
+ host->block_page_mask = ((mtd->erasesize / mtd->writesize) - 1);
+ page_per_block = mtd->erasesize / match_page_type_to_size(info->pagetype);
+ switch (page_per_block) {
+ case 64:
+ block_reg = BLOCK_SIZE_64_PAGE;
+ break;
+ case 128:
+ block_reg = BLOCK_SIZE_128_PAGE;
+ break;
+ case 256:
+ block_reg = BLOCK_SIZE_256_PAGE;
+ break;
+ case 512:
+ block_reg = BLOCK_SIZE_512_PAGE;
+ break;
+ default:
+ DB_MSG("Can't support block %#x and page %#x size\n",
+ mtd->erasesize, mtd->writesize);
+ }
+
+ return FMC_CFG_BLOCK_SIZE(block_reg);
+}
+
+/*****************************************************************************/
+static void fmc100_set_fmc_cfg_reg(struct fmc_host *host,
+ struct nand_config_info *type_info, struct nand_dev_t *nand_dev)
+{
+ unsigned int page_reg, ecc_reg, block_reg, reg_fmc_cfg;
+
+ ecc_reg = fmc100_get_ecc_reg(host, type_info, nand_dev);
+ page_reg = fmc100_get_page_reg(host, type_info);
+ block_reg = fmc100_get_block_reg(host, type_info);
+
+ reg_fmc_cfg = fmc_readl(host, FMC_CFG);
+ reg_fmc_cfg &= ~(PAGE_SIZE_MASK | ECC_TYPE_MASK | BLOCK_SIZE_MASK);
+ reg_fmc_cfg |= ecc_reg | page_reg | block_reg;
+ fmc_writel(host, FMC_CFG, reg_fmc_cfg);
+
+ /* Save value of FMC_CFG and FMC_CFG_ECC0 to turn on/off ECC */
+ host->fmc_cfg = reg_fmc_cfg;
+ host->fmc_cfg_ecc0 = (host->fmc_cfg & ~ECC_TYPE_MASK) | ECC_TYPE_0BIT;
+ FMC_PR(BT_DBG, "\t|-Save FMC_CFG[%#x]: %#x and FMC_CFG_ECC0: %#x\n",
+ FMC_CFG, host->fmc_cfg, host->fmc_cfg_ecc0);
+}
+
+/*****************************************************************************/
+static int fmc100_set_config_info(struct mtd_info *mtd,
+ struct nand_chip *chip, struct nand_dev_t *nand_dev)
+{
+ struct fmc_host *host = chip->priv;
+ struct nand_config_info *type_info = NULL;
+
+ FMC_PR(BT_DBG, "\t*-Start config Block Page OOB and Ecc\n");
+
+ type_info = fmc100_get_config_type_info(mtd, nand_dev);
+ BUG_ON(!type_info);
+
+ FMC_PR(BT_DBG, "\t|-%s Config, PageSize %s EccType %s OOBSize %d\n",
+ nand_dev->start_type, nand_page_name(type_info->pagetype),
+ nand_ecc_name(type_info->ecctype), type_info->oobsize);
+
+ /* Set the page_size, ecc_type, block_size of FMC_CFG[0x0] register */
+ fmc100_set_fmc_cfg_reg(host, type_info, nand_dev);
+
+ fmc100_set_oob_info(mtd, type_info, nand_dev);
+
+ FMC_PR(BT_DBG, "\t*-End config Block Page Oob and Ecc\n");
+
+ return 0;
+}
+
+/*****************************************************************************/
+int fmc100_spi_nand_init(struct nand_chip *chip)
+{
+ struct fmc_host *host = chip->priv;
+
+ FMC_PR(BT_DBG, "\t|*-Start fmc100 SPI Nand init\n");
+
+ /* Set system clock and enable controller */
+ clk_prepare_enable(host->clk);
+
+ /* Switch SPI type to SPI nand */
+ fmc100_switch_to_spi_nand(host);
+
+ /* hold on STR mode */
+ fmc100_set_str_mode(host);
+
+ /* fmc host init */
+ fmc100_host_init(host);
+ host->chip = chip;
+
+ /* fmc nand_chip struct init */
+ fmc100_chip_init(chip);
+
+ fmc_spi_nand_ids_register();
+ nfc_param_adjust = fmc100_set_config_info;
+
+ FMC_PR(BT_DBG, "\t|*-End fmc100 SPI Nand init\n");
+
+ return 0;
+}
+#ifdef CONFIG_PM
+/*****************************************************************************/
+int fmc100_suspend(struct platform_device *pltdev, pm_message_t state)
+{
+ unsigned int ret;
+ struct fmc_host *host = platform_get_drvdata(pltdev);
+ struct fmc_spi *spi = host->spi;
+
+ mutex_lock(host->lock);
+ fmc100_switch_to_spi_nand(host);
+
+ ret = spi->driver->wait_ready(spi);
+ if (ret)
+ DB_MSG("Error: wait ready failed!");
+
+ clk_disable_unprepare(host->clk);
+ mutex_unlock(host->lock);
+
+ return 0;
+}
+/*****************************************************************************/
+int fmc100_resume(struct platform_device *pltdev)
+{
+ int cs;
+ struct fmc_host *host = platform_get_drvdata(pltdev);
+ struct nand_chip *chip = host->chip;
+
+ mutex_lock(host->lock);
+ fmc100_switch_to_spi_nand(host);
+ clk_prepare_enable(host->clk);
+
+ for (cs = 0; cs < chip->numchips; cs++) {
+ host->send_cmd_reset(host);
+ }
+
+ fmc100_spi_nand_config(host);
+
+ mutex_unlock(host->lock);
+ return 0;
+}
+#endif
+
diff -urN linux-4.9.37/drivers/mtd/nand/gkfmc100/fmc100.h linux-4.9.y/drivers/mtd/nand/gkfmc100/fmc100.h
--- linux-4.9.37/drivers/mtd/nand/gkfmc100/fmc100.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/mtd/nand/gkfmc100/fmc100.h 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,375 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#ifndef __FMC100_H__
+#define __FMC100_H__
+
+/*****************************************************************************/
+#include <linux/platform_device.h>
+#include <linux/mfd/goke_fmc.h>
+
+/*****************************************************************************/
+#define INFINITE (0xFFFFFFFF)
+
+/*****************************************************************************/
+#define SPI_IF_READ_STD (0x01)
+#define SPI_IF_READ_FAST (0x02)
+#define SPI_IF_READ_DUAL (0x04)
+#define SPI_IF_READ_DUAL_ADDR (0x08)
+#define SPI_IF_READ_QUAD (0x10)
+#define SPI_IF_READ_QUAD_ADDR (0x20)
+
+#define SPI_IF_WRITE_STD (0x01)
+#define SPI_IF_WRITE_DUAL (0x02)
+#define SPI_IF_WRITE_DUAL_ADDR (0x04)
+#define SPI_IF_WRITE_QUAD (0x08)
+#define SPI_IF_WRITE_QUAD_ADDR (0x10)
+
+#define SPI_IF_ERASE_SECTOR_4K (0x01)
+#define SPI_IF_ERASE_SECTOR_32K (0x02)
+#define SPI_IF_ERASE_SECTOR_64K (0x04)
+#define SPI_IF_ERASE_SECTOR_128K (0x08)
+#define SPI_IF_ERASE_SECTOR_256K (0x10)
+
+/******************************************************************************/
+#define FMC_SPI_NAND_SUPPORT_READ (SPI_IF_READ_STD \
+ | SPI_IF_READ_FAST \
+ | SPI_IF_READ_DUAL \
+ | SPI_IF_READ_DUAL_ADDR \
+ | SPI_IF_READ_QUAD \
+ | SPI_IF_READ_QUAD_ADDR)
+
+#define FMC_SPI_NAND_SUPPORT_WRITE (SPI_IF_WRITE_STD | SPI_IF_WRITE_QUAD)
+
+#define FMC_SPI_NAND_SUPPORT_MAX_DUMMY 8
+
+/*****************************************************************************/
+#define SPI_CMD_READ_STD 0x03 /* Standard read cache */
+#define SPI_CMD_READ_FAST 0x0B /* Higher speed read cache */
+#define SPI_CMD_READ_DUAL 0x3B /* 2 IO read cache only date */
+#define SPI_CMD_READ_DUAL_ADDR 0xBB /* 2 IO read cache date&addr */
+#define SPI_CMD_READ_QUAD 0x6B /* 4 IO read cache only date */
+#define SPI_CMD_READ_QUAD_ADDR 0xEB /* 4 IO read cache date&addr */
+
+#define SPI_CMD_WRITE_STD 0x02 /* Standard page program */
+#define SPI_CMD_WRITE_DUAL 0xA2 /* 2 IO program only date */
+#define SPI_CMD_WRITE_DUAL_ADDR 0xD2 /* 2 IO program date&addr */
+#define SPI_CMD_WRITE_QUAD 0x32 /* 4 IO program only date */
+#define SPI_CMD_WRITE_QUAD_ADDR 0x12 /* 4 IO program date&addr */
+
+#define SPI_CMD_SE_4K 0x20 /* 4KB sector Erase */
+#define SPI_CMD_SE_32K 0x52 /* 32KB sector Erase */
+#define SPI_CMD_SE_64K 0xD8 /* 64KB sector Erase */
+#define SPI_CMD_SE_128K 0xD8 /* 128KB sector Erase */
+#define SPI_CMD_SE_256K 0xD8 /* 256KB sector Erase */
+
+/*****************************************************************************/
+#define SET_READ_STD(_dummy_, _size_, _clk_) \
+ static struct spi_op read_std_##_dummy_##_size_##_clk_ = { \
+ SPI_IF_READ_STD, SPI_CMD_READ_STD, _dummy_, _size_, _clk_ }
+
+#define SET_READ_FAST(_dummy_, _size_, _clk_) \
+ static struct spi_op read_fast_##_dummy_##_size_##_clk_ = { \
+ SPI_IF_READ_FAST, SPI_CMD_READ_FAST, _dummy_, _size_, _clk_ }
+
+#define SET_READ_DUAL(_dummy_, _size_, _clk_) \
+ static struct spi_op read_dual_##_dummy_##_size_##_clk_ = { \
+ SPI_IF_READ_DUAL, SPI_CMD_READ_DUAL, _dummy_, _size_, _clk_ }
+
+#define SET_READ_DUAL_ADDR(_dummy_, _size_, _clk_) \
+ static struct spi_op read_dual_addr_##_dummy_##_size_##_clk_ = { \
+ SPI_IF_READ_DUAL_ADDR, SPI_CMD_READ_DUAL_ADDR, _dummy_, _size_, _clk_ }
+
+#define SET_READ_QUAD(_dummy_, _size_, _clk_) \
+ static struct spi_op read_quad_##_dummy_##_size_##_clk_ = { \
+ SPI_IF_READ_QUAD, SPI_CMD_READ_QUAD, _dummy_, _size_, _clk_ }
+
+#define SET_READ_QUAD_ADDR(_dummy_, _size_, _clk_) \
+ static struct spi_op read_quad_addr_##_dummy_##_size_##_clk_ = { \
+ SPI_IF_READ_QUAD_ADDR, SPI_CMD_READ_QUAD_ADDR, _dummy_, _size_, _clk_ }
+
+/*****************************************************************************/
+#define SET_WRITE_STD(_dummy_, _size_, _clk_) \
+ static struct spi_op write_std_##_dummy_##_size_##_clk_ = { \
+ SPI_IF_WRITE_STD, SPI_CMD_WRITE_STD, _dummy_, _size_, _clk_ }
+
+#define SET_WRITE_DUAL(_dummy_, _size_, _clk_) \
+ static struct spi_op write_dual_##_dummy_##_size_##_clk_ = { \
+ SPI_IF_WRITE_DUAL, SPI_CMD_WRITE_DUAL, _dummy_, _size_, _clk_ }
+
+#define SET_WRITE_DUAL_ADDR(_dummy_, _size_, _clk_) \
+ static struct spi_op write_dual_addr_##_dummy_##_size_##_clk_ = { \
+SPI_IF_WRITE_DUAL_ADDR, SPI_CMD_WRITE_DUAL_ADDR, _dummy_, _size_, _clk_ }
+
+#define SET_WRITE_QUAD(_dummy_, _size_, _clk_) \
+ static struct spi_op write_quad_##_dummy_##_size_##_clk_ = { \
+ SPI_IF_WRITE_QUAD, SPI_CMD_WRITE_QUAD, _dummy_, _size_, _clk_ }
+
+#define SET_WRITE_QUAD_ADDR(_dummy_, _size_, _clk_) \
+ static struct spi_op write_quad_addr_##_dummy_##_size_##_clk_ = { \
+SPI_IF_WRITE_QUAD_ADDR, SPI_CMD_WRITE_QUAD_ADDR, _dummy_, _size_, _clk_ }
+
+/*****************************************************************************/
+#define SET_ERASE_SECTOR_4K(_dummy_, _size_, _clk_) \
+ static struct spi_op erase_sector_4k_##_dummy_##_size_##_clk_ = { \
+ SPI_IF_ERASE_SECTOR_4K, SPI_CMD_SE_4K, _dummy_, _size_, _clk_ }
+
+#define SET_ERASE_SECTOR_32K(_dummy_, _size_, _clk_) \
+ static struct spi_op erase_sector_32k_##_dummy_##_size_##_clk_ = { \
+ SPI_IF_ERASE_SECTOR_32K, SPI_CMD_SE_32K, _dummy_, _size_, _clk_ }
+
+#define SET_ERASE_SECTOR_64K(_dummy_, _size_, _clk_) \
+ static struct spi_op erase_sector_64k_##_dummy_##_size_##_clk_ = { \
+ SPI_IF_ERASE_SECTOR_64K, SPI_CMD_SE_64K, _dummy_, _size_, _clk_ }
+
+#define SET_ERASE_SECTOR_128K(_dummy_, _size_, _clk_) \
+ static struct spi_op erase_sector_128k_##_dummy_##_size_##_clk_ = { \
+ SPI_IF_ERASE_SECTOR_128K, SPI_CMD_SE_128K, _dummy_, _size_, _clk_ }
+
+#define SET_ERASE_SECTOR_256K(_dummy_, _size_, _clk_) \
+ static struct spi_op erase_sector_256k_##_dummy_##_size_##_clk_ = { \
+ SPI_IF_ERASE_SECTOR_256K, SPI_CMD_SE_256K, _dummy_, _size_, _clk_ }
+
+/*****************************************************************************/
+#define READ_STD(_dummy_, _size_, _clk_) read_std_##_dummy_##_size_##_clk_
+#define READ_FAST(_dummy_, _size_, _clk_) read_fast_##_dummy_##_size_##_clk_
+#define READ_DUAL(_dummy_, _size_, _clk_) read_dual_##_dummy_##_size_##_clk_
+#define READ_DUAL_ADDR(_dummy_, _size_, _clk_) \
+ read_dual_addr_##_dummy_##_size_##_clk_
+#define READ_QUAD(_dummy_, _size_, _clk_) read_quad_##_dummy_##_size_##_clk_
+#define READ_QUAD_ADDR(_dummy_, _size_, _clk_) \
+ read_quad_addr_##_dummy_##_size_##_clk_
+
+/*****************************************************************************/
+#define WRITE_STD(_dummy_, _size_, _clk_) write_std_##_dummy_##_size_##_clk_
+#define WRITE_DUAL(_dummy_, _size_, _clk_) write_dual_##_dummy_##_size_##_clk_
+#define WRITE_DUAL_ADDR(_dummy_, _size_, _clk_) \
+ write_dual_addr_##_dummy_##_size_##_clk_
+#define WRITE_QUAD(_dummy_, _size_, _clk_) write_quad_##_dummy_##_size_##_clk_
+#define WRITE_QUAD_ADDR(_dummy_, _size_, _clk_) \
+ write_quad_addr_##_dummy_##_size_##_clk_
+
+/*****************************************************************************/
+#define ERASE_SECTOR_4K(_dummy_, _size_, _clk_) \
+ erase_sector_4k_##_dummy_##_size_##_clk_
+#define ERASE_SECTOR_32K(_dummy_, _size_, _clk_) \
+ erase_sector_32k_##_dummy_##_size_##_clk_
+#define ERASE_SECTOR_64K(_dummy_, _size_, _clk_) \
+ erase_sector_64k_##_dummy_##_size_##_clk_
+#define ERASE_SECTOR_128K(_dummy_, _size_, _clk_) \
+ erase_sector_128k_##_dummy_##_size_##_clk_
+#define ERASE_SECTOR_256K(_dummy_, _size_, _clk_) \
+ erase_sector_256k_##_dummy_##_size_##_clk_
+
+/*****************************************************************************/
+#define SPI_CMD_WREN 0x06 /* Write Enable */
+#define SPI_CMD_WRDI 0x04 /* Write Disable */
+
+#define SPI_CMD_RDID 0x9F /* Read Identification */
+
+/*****************************************************************************/
+#define SPI_CMD_GET_FEATURES 0x0F /* Get Features */
+#define SPI_CMD_SET_FEATURE 0x1F /* Set Feature */
+
+#define SPI_CMD_PAGE_READ 0x13 /* Page Read to Cache */
+
+#define SPI_CMD_RESET 0xff /* Reset the device */
+
+/*****************************************************************************/
+/* These macroes are for debug only, reg option is slower then dma option */
+#undef FMC100_SPI_NAND_SUPPORT_REG_READ
+/* #define FMC100_SPI_NAND_SUPPORT_REG_READ */
+
+#undef FMC100_SPI_NAND_SUPPORT_REG_WRITE
+/* #define FMC100_SPI_NAND_SUPPORT_REG_WRITE */
+
+#ifdef CONFIG_GOKE_NAND_ECC_STATUS_REPORT
+/*****************************************************************************/
+#define FMC100_ECC_ERR_NUM0_BUF0 0xc0
+
+#define GET_ECC_ERR_NUM(_i, _reg) (((_reg) >> ((_i) * 8)) & 0xff)
+#endif
+/*****************************************************************************/
+#define REG_CNT_HIGH_BLOCK_NUM_SHIFT 10
+
+#define REG_CNT_BLOCK_NUM_MASK 0x3ff
+#define REG_CNT_BLOCK_NUM_SHIFT 22
+
+#define REG_CNT_PAGE_NUM_MASK 0x3f
+#define REG_CNT_PAGE_NUM_SHIFT 16
+
+#define REG_CNT_WRAP_MASK 0xf
+#define REG_CNT_WRAP_SHIFT 12
+
+#define REG_CNT_ECC_OFFSET_MASK 0xfff
+#define REG_CNT_ECC_8BIT_OFFSET 1054
+#define REG_CNT_ECC_16BIT_OFFSET 1056
+#define REG_CNT_ECC_24BIT_OFFSET 1082
+
+#define ERR_STR_DRIVER "Driver does not support this configure "
+#define ERR_STR_CHECK "Please make sure the hardware configuration is correct"
+
+/*****************************************************************************/
+#define FMC100_ADDR_CYCLE_MASK 0x2
+
+/*****************************************************************************/
+#define OP_STYPE_NONE 0x0
+#define OP_STYPE_READ 0x01
+#define OP_STYPE_WRITE 0x02
+#define OP_STYPE_ERASE 0x04
+#define CLK_FMC_TO_CRG_MHZ(_clk) ((_clk) * 2000000)
+
+/*****************************************************************************/
+#define MAX_SPI_OP 8
+
+/*****************************************************************************/
+/* SPI general operation parameter */
+struct spi_op {
+ unsigned char iftype;
+ unsigned char cmd;
+ unsigned char dummy;
+ unsigned int size;
+ unsigned int clock;
+};
+
+struct spi_drv;
+
+/* SPI interface all operation */
+struct fmc_spi {
+ char *name;
+ int chipselect;
+ unsigned long long chipsize;
+ unsigned int erasesize;
+#define SPI_NOR_3BYTE_ADDR_LEN 3 /* address len 3Bytes */
+#define SPI_NOR_4BYTE_ADDR_LEN 4 /* address len 4Bytes for 32MB */
+ unsigned int addrcycle;
+
+ struct spi_op read[1];
+ struct spi_op write[1];
+ struct spi_op erase[MAX_SPI_OP];
+
+ void *host;
+
+ struct spi_drv *driver;
+};
+
+/* SPI interface special operation function hook */
+struct spi_drv {
+ int (*wait_ready)(struct fmc_spi *spi);
+ int (*write_enable)(struct fmc_spi *spi);
+ int (*qe_enable)(struct fmc_spi *spi);
+ int (*bus_prepare)(struct fmc_spi *spi, int op);
+ int (*entry_4addr)(struct fmc_spi *spi, int en);
+};
+
+struct spi_nand_info {
+ char *name;
+ unsigned char id[MAX_SPI_NAND_ID_LEN];
+ unsigned char id_len;
+ unsigned long long chipsize;
+ unsigned int erasesize;
+ unsigned int pagesize;
+ unsigned int oobsize;
+#define BBP_LAST_PAGE 0x01
+#define BBP_FIRST_PAGE 0x02
+ unsigned int badblock_pos;
+ struct spi_op *read[MAX_SPI_OP];
+ struct spi_op *write[MAX_SPI_OP];
+ struct spi_op *erase[MAX_SPI_OP];
+ struct spi_drv *driver;
+};
+
+/*****************************************************************************/
+extern u_char spi_nand_feature_op(struct fmc_spi *spi, u_char op, u_char addr,
+ u_char val);
+
+/*****************************************************************************/
+struct fmc_host {
+ struct mtd_info *mtd;
+ struct nand_chip *chip;
+ struct fmc_spi spi[CONFIG_SPI_NAND_MAX_CHIP_NUM];
+ struct fmc_cmd_op cmd_op;
+
+ void __iomem *iobase;
+ void __iomem *regbase;
+ struct clk *clk;
+ u32 clkrate;
+
+ unsigned int fmc_cfg;
+ unsigned int fmc_cfg_ecc0;
+
+ unsigned int offset;
+
+ struct device *dev;
+ struct mutex *lock;
+
+ /* This is maybe an un-aligment address, only for malloc or free */
+ char *buforg;
+ char *buffer;
+
+#ifdef CONFIG_64BIT
+ unsigned long long dma_buffer;
+ unsigned long long dma_oob;
+#else
+ unsigned int dma_buffer;
+ unsigned int dma_oob;
+#endif
+
+ unsigned int addr_cycle;
+ unsigned int addr_value[2];
+ unsigned int cache_addr_value[2];
+
+ unsigned int column;
+ unsigned int block_page_mask;
+
+ unsigned int ecctype;
+ unsigned int pagesize;
+ unsigned int oobsize;
+
+ int add_partition;
+
+ int need_rr_data;
+#define FMC100_READ_RETRY_DATA_LEN 128
+ char rr_data[FMC100_READ_RETRY_DATA_LEN];
+ struct read_retry_t *read_retry;
+
+ int version;
+
+ /* BOOTROM read two bytes to detect the bad block flag */
+#define FMC_BAD_BLOCK_POS 0
+ unsigned char *bbm; /* nand bad block mark */
+ unsigned short *epm; /* nand empty page mark */
+
+ unsigned int uc_er;
+
+ void (*send_cmd_write)(struct fmc_host *host);
+ void (*send_cmd_status)(struct fmc_host *host);
+ void (*send_cmd_read)(struct fmc_host *host);
+ void (*send_cmd_erase)(struct fmc_host *host);
+ void (*send_cmd_readid)(struct fmc_host *host);
+ void (*send_cmd_reset)(struct fmc_host *host);
+#ifdef CONFIG_PM
+ int (*suspend)(struct platform_device *pltdev, pm_message_t state);
+ int (*resume)(struct platform_device *pltdev);
+#endif
+};
+
+/*****************************************************************************/
+void fmc100_ecc0_switch(struct fmc_host *host, unsigned char op);
+
+int fmc100_spi_nand_init(struct nand_chip *chip);
+
+/*****************************************************************************/
+extern void fmc_spi_nand_ids_register(void);
+
+extern void fmc_set_nand_system_clock(struct spi_op *op, int clk_en);
+
+/*****************************************************************************/
+#ifdef CONFIG_PM
+int fmc100_suspend(struct platform_device *pltdev, pm_message_t state);
+int fmc100_resume(struct platform_device *pltdev);
+void fmc100_spi_nand_config(struct fmc_host *host);
+#endif
+
+#endif /* End of __FMC100_H__ */
diff -urN linux-4.9.37/drivers/mtd/nand/gkfmc100/fmc100_os.c linux-4.9.y/drivers/mtd/nand/gkfmc100/fmc100_os.c
--- linux-4.9.37/drivers/mtd/nand/gkfmc100/fmc100_os.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/mtd/nand/gkfmc100/fmc100_os.c 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/of_platform.h>
+#include <asm/setup.h>
+
+#include "../../mtdcore.h"
+#include "fmc100.h"
+
+/*****************************************************************************/
+static int fmc100_spi_nand_pre_probe(struct nand_chip *chip)
+{
+ uint8_t nand_maf_id;
+ struct fmc_host *host = chip->priv;
+
+ /* Reset the chip first */
+ host->send_cmd_reset(host);
+ udelay(1000);
+
+ /* Check the ID */
+ host->offset = 0;
+ memset((unsigned char *)(chip->IO_ADDR_R), 0, 0x10);
+ host->send_cmd_readid(host);
+ nand_maf_id = fmc_readb(chip->IO_ADDR_R);
+
+ if (nand_maf_id == 0x00 || nand_maf_id == 0xff) {
+ printk("Cannot found a valid SPI Nand Device\n");
+ return 1;
+ }
+
+ return 0;
+}
+/*****************************************************************************/
+static int fmc_nand_scan(struct mtd_info *mtd)
+{
+ int result = 0;
+ unsigned char cs, chip_num = CONFIG_SPI_NAND_MAX_CHIP_NUM;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct fmc_host *host = chip->priv;
+
+ for (cs = 0; chip_num && (cs < FMC_MAX_CHIP_NUM); cs++) {
+ if (fmc_cs_user[cs]) {
+ FMC_PR(BT_DBG, "\t\t*-Current CS(%d) is occupied.\n",
+ cs);
+ continue;
+ }
+
+ host->cmd_op.cs = cs;
+
+ if (fmc100_spi_nand_pre_probe(chip)) {
+ return -ENODEV;
+ }
+
+ FMC_PR(BT_DBG, "\t\t*-Scan SPI nand flash on CS: %d\n", cs);
+ if (nand_scan(mtd, chip_num)) {
+ continue;
+ }
+ chip_num--;
+ }
+
+ if (chip_num == CONFIG_SPI_NAND_MAX_CHIP_NUM) {
+ result = -ENXIO;
+ } else {
+ result = 0;
+ }
+
+ return result;
+}
+
+/*****************************************************************************/
+static int bsp_spi_nand_probe(struct platform_device *pltdev)
+{
+ int len, result = 0;
+ struct fmc_host *host = NULL;
+ struct nand_chip *chip = NULL;
+ struct mtd_info *mtd = NULL;
+ struct device *dev = &pltdev->dev;
+ struct device_node *np = NULL;
+ struct bsp_fmc *fmc = dev_get_drvdata(dev->parent);
+
+ FMC_PR(BT_DBG, "\t*-Start SPI Nand flash driver probe\n");
+
+ if (!fmc) {
+ dev_err(dev, "get mfd fmc devices failed\n");
+ return -ENXIO;
+ }
+
+ len = sizeof(struct fmc_host) + sizeof(struct nand_chip)
+ + sizeof(struct mtd_info);
+ host = devm_kzalloc(dev, len, GFP_KERNEL);
+ if (!host) {
+ return -ENOMEM;
+ }
+ memset((char *)host, 0, len);
+
+ platform_set_drvdata(pltdev, host);
+ host->dev = &pltdev->dev;
+
+ host->chip = chip = (struct nand_chip *)&host[1];
+ host->mtd = mtd = nand_to_mtd(chip);
+
+ host->regbase = fmc->regbase;
+ host->iobase = fmc->iobase;
+ host->clk = fmc->clk;
+ host->lock = &fmc->lock;
+ host->buffer = fmc->buffer;
+ host->dma_buffer = fmc->dma_buffer;
+
+ memset((char *)host->iobase, 0xff, fmc->dma_len);
+ chip->IO_ADDR_R = chip->IO_ADDR_W = host->iobase;
+
+ chip->priv = host;
+ result = fmc100_spi_nand_init(chip);
+ if (result) {
+ FMC_PR(BT_DBG, "\t|-SPI Nand init failed, ret: %d\n", result);
+ result = -ENODEV;
+ goto fail;
+ }
+
+ np = of_get_next_available_child(dev->of_node, NULL);
+ mtd->name = np->name;
+ mtd->type = MTD_NANDFLASH;
+ mtd->priv = chip;
+ mtd->owner = THIS_MODULE;
+
+ result = of_property_read_u32(np, "spi-max-frequency", &host->clkrate);
+ if (result) {
+ goto fail;
+ }
+
+ result = fmc_nand_scan(mtd);
+ if (result) {
+ FMC_PR(BT_DBG, "\t|-Scan SPI Nand failed.\n");
+ goto fail;
+ }
+
+ result = mtd_device_register(mtd, NULL, 0);
+ if (!result) {
+ FMC_PR(BT_DBG, "\t*-End driver probe !!\n");
+ return 0;
+ }
+
+ result = -ENODEV;
+fail:
+ clk_disable_unprepare(host->clk);
+ nand_release(mtd);
+
+ DB_MSG("Error: driver probe, result: %d\n", result);
+ return result;
+}
+
+/*****************************************************************************/
+static int bsp_spi_nand_remove(struct platform_device *pltdev)
+{
+ struct fmc_host *host = platform_get_drvdata(pltdev);
+ if (host == NULL){
+ FMC_PR(BT_DBG, "\t*host is NULL ,remove err !!\n");
+ return 0;
+ }
+ clk_disable_unprepare(host->clk);
+ nand_release(host->mtd);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+/*****************************************************************************/
+static int fmc100_os_suspend(struct platform_device *pltdev,
+ pm_message_t state)
+{
+ struct fmc_host *host = platform_get_drvdata(pltdev);
+
+ if (host && host->suspend) {
+ return (host->suspend)(pltdev, state);
+ }
+
+ return 0;
+}
+
+/*****************************************************************************/
+static int fmc100_os_resume(struct platform_device *pltdev)
+{
+ struct fmc_host *host = platform_get_drvdata(pltdev);
+
+ if (host && host->resume) {
+ return (host->resume)(pltdev);
+ }
+
+ return 0;
+}
+#endif /* End of CONFIG_PM */
+/*****************************************************************************/
+static const struct of_device_id bsp_spi_nand_dt_ids[] = {
+ { .compatible = "goke,fmc-spi-nand"},
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, bsp_spi_nand_dt_ids);
+
+static struct platform_driver bsp_spi_nand_driver = {
+ .driver = {
+ .name = "bsp_spi_nand",
+ .of_match_table = bsp_spi_nand_dt_ids,
+ },
+ .probe = bsp_spi_nand_probe,
+ .remove = bsp_spi_nand_remove,
+#ifdef CONFIG_PM
+ .suspend = fmc100_os_suspend,
+ .resume = fmc100_os_resume,
+#endif
+};
+module_platform_driver(bsp_spi_nand_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Goke Flash Memory Controller V100 SPI Nand Driver");
diff -urN linux-4.9.37/drivers/mtd/nand/gkfmc100/fmc100_spi_general.c linux-4.9.y/drivers/mtd/nand/gkfmc100/fmc100_spi_general.c
--- linux-4.9.37/drivers/mtd/nand/gkfmc100/fmc100_spi_general.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/mtd/nand/gkfmc100/fmc100_spi_general.c 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+/*
+ Send set/get features command to SPI Nand flash
+*/
+u_char spi_nand_feature_op(struct fmc_spi *spi, u_char op, u_char addr,
+ u_char val)
+{
+ unsigned int reg;
+ const char *str[] = {"Get", "Set"};
+ struct fmc_host *host = (struct fmc_host *)spi->host;
+
+ if ((op == GET_OP) && (STATUS_ADDR == addr)) {
+ if (SR_DBG) {
+ pr_info("\n");
+ }
+ FMC_PR(SR_DBG, "\t\t|*-Start Get Status\n");
+
+ reg = OP_CFG_FM_CS(host->cmd_op.cs) | OP_CFG_OEN_EN;
+ fmc_writel(host, FMC_OP_CFG, reg);
+ FMC_PR(SR_DBG, "\t\t||-Set OP_CFG[%#x]%#x\n", FMC_OP_CFG, reg);
+
+ reg = FMC_OP_READ_STATUS_EN | FMC_OP_REG_OP_START;
+ fmc_writel(host, FMC_OP, reg);
+ FMC_PR(SR_DBG, "\t\t||-Set OP[%#x]%#x\n", FMC_OP, reg);
+
+ FMC_CMD_WAIT_CPU_FINISH(host);
+
+ val = fmc_readl(host, FMC_STATUS);
+ FMC_PR(SR_DBG, "\t\t|*-End Get Status, result: %#x\n", val);
+
+ return val;
+ }
+
+ FMC_PR(FT_DBG, "\t|||*-Start %s feature, addr[%#x]\n", str[op], addr);
+
+ fmc100_ecc0_switch(host, ENABLE);
+
+ reg = FMC_CMD_CMD1(op ? SPI_CMD_SET_FEATURE : SPI_CMD_GET_FEATURES);
+ fmc_writel(host, FMC_CMD, reg);
+ FMC_PR(FT_DBG, "\t||||-Set CMD[%#x]%#x\n", FMC_CMD, reg);
+
+ fmc_writel(host, FMC_ADDRL, addr);
+ FMC_PR(FT_DBG, "\t||||-Set ADDRL[%#x]%#x\n", FMC_ADDRL, addr);
+
+ reg = OP_CFG_FM_CS(host->cmd_op.cs)
+ | OP_CFG_ADDR_NUM(FEATURES_OP_ADDR_NUM)
+ | OP_CFG_OEN_EN;
+ fmc_writel(host, FMC_OP_CFG, reg);
+ FMC_PR(FT_DBG, "\t||||-Set OP_CFG[%#x]%#x\n", FMC_OP_CFG, reg);
+
+ reg = FMC_DATA_NUM_CNT(FEATURES_DATA_LEN);
+ fmc_writel(host, FMC_DATA_NUM, reg);
+ FMC_PR(FT_DBG, "\t||||-Set DATA_NUM[%#x]%#x\n", FMC_DATA_NUM, reg);
+
+ reg = FMC_OP_CMD1_EN
+ | FMC_OP_ADDR_EN
+ | FMC_OP_REG_OP_START;
+
+ if (op == SET_OP) {
+ reg |= FMC_OP_WRITE_DATA_EN;
+ fmc_writeb(val, host->iobase);
+ FMC_PR(FT_DBG, "\t||||-Write IO[%#lx]%#x\n", (long)host->iobase,
+ *(u_char *)host->iobase);
+ } else {
+ reg |= FMC_OP_READ_DATA_EN;
+ }
+
+ fmc_writel(host, FMC_OP, reg);
+ FMC_PR(FT_DBG, "\t||||-Set OP[%#x]%#x\n", FMC_OP, reg);
+
+ FMC_CMD_WAIT_CPU_FINISH(host);
+
+ if (op == GET_OP) {
+ val = fmc_readb(host->iobase);
+ FMC_PR(FT_DBG, "\t||||-Read IO[%#lx]%#x\n", (long)host->iobase,
+ *(u_char *)host->iobase);
+ }
+
+ fmc100_ecc0_switch(host, DISABLE);
+
+ FMC_PR(FT_DBG, "\t|||*-End %s Feature[%#x]:%#x\n", str[op], addr, val);
+
+ return val;
+}
+
+/*****************************************************************************/
+/*
+ Read status[C0H]:[0]bit OIP, judge whether the device is busy or not
+*/
+static int spi_general_wait_ready(struct fmc_spi *spi)
+{
+ unsigned char status;
+ unsigned long deadline = jiffies + FMC_MAX_READY_WAIT_JIFFIES;
+ struct fmc_host *host = (struct fmc_host *)spi->host;
+
+ do {
+ status = spi_nand_feature_op(spi, GET_OP, STATUS_ADDR, 0);
+ if (!(status & STATUS_OIP_MASK)) {
+ if ((host->cmd_op.l_cmd == NAND_CMD_ERASE2)
+ && (status & STATUS_E_FAIL_MASK)) {
+ return status;
+ }
+ if ((host->cmd_op.l_cmd == NAND_CMD_PAGEPROG)
+ && (status & STATUS_P_FAIL_MASK)) {
+ return status;
+ }
+ return 0;
+ }
+
+ cond_resched();
+
+ } while (!time_after_eq(jiffies, deadline));
+
+ DB_MSG("Error: SPI Nand wait ready timeout, status: %#x\n", status);
+
+ return 1;
+}
+
+/*****************************************************************************/
+/*
+ Send write enable cmd to SPI Nand, status[C0H]:[2]bit WEL must be set 1
+*/
+static int spi_general_write_enable(struct fmc_spi *spi)
+{
+ unsigned int reg;
+ struct fmc_host *host = (struct fmc_host *)spi->host;
+
+ if (WE_DBG) {
+ pr_info("\n");
+ }
+ FMC_PR(WE_DBG, "\t|*-Start Write Enable\n");
+
+ reg = spi_nand_feature_op(spi, GET_OP, STATUS_ADDR, 0);
+ if (reg & STATUS_WEL_MASK) {
+ FMC_PR(WE_DBG, "\t||-Write Enable was opened! reg: %#x\n",
+ reg);
+ return 0;
+ }
+
+ reg = fmc_readl(host, FMC_GLOBAL_CFG);
+ FMC_PR(WE_DBG, "\t||-Get GLOBAL_CFG[%#x]%#x\n", FMC_GLOBAL_CFG, reg);
+ if (reg & FMC_GLOBAL_CFG_WP_ENABLE) {
+ reg &= ~FMC_GLOBAL_CFG_WP_ENABLE;
+ fmc_writel(host, FMC_GLOBAL_CFG, reg);
+ FMC_PR(WE_DBG, "\t||-Set GLOBAL_CFG[%#x]%#x\n",
+ FMC_GLOBAL_CFG, reg);
+ }
+
+ reg = FMC_CMD_CMD1(SPI_CMD_WREN);
+ fmc_writel(host, FMC_CMD, reg);
+ FMC_PR(WE_DBG, "\t||-Set CMD[%#x]%#x\n", FMC_CMD, reg);
+
+ reg = OP_CFG_FM_CS(host->cmd_op.cs) | OP_CFG_OEN_EN;
+ fmc_writel(host, FMC_OP_CFG, reg);
+ FMC_PR(WE_DBG, "\t||-Set OP_CFG[%#x]%#x\n", FMC_OP_CFG, reg);
+
+ reg = FMC_OP_CMD1_EN | FMC_OP_REG_OP_START;
+ fmc_writel(host, FMC_OP, reg);
+ FMC_PR(WE_DBG, "\t||-Set OP[%#x]%#x\n", FMC_OP, reg);
+
+ FMC_CMD_WAIT_CPU_FINISH(host);
+
+#if WE_DBG
+ spi->driver->wait_ready(spi);
+
+ reg = spi_nand_feature_op(spi, GET_OP, STATUS_ADDR, 0);
+ if (reg & STATUS_WEL_MASK) {
+ FMC_PR(WE_DBG, "\t||-Write Enable success. reg: %#x\n", reg);
+ } else {
+ DB_MSG("Error: Write Enable failed! reg: %#x\n", reg);
+ return reg;
+ }
+#endif
+
+ FMC_PR(WE_DBG, "\t|*-End Write Enable\n");
+ return 0;
+}
+
+/*****************************************************************************/
+/*
+ judge whether SPI Nand support QUAD read/write or not
+*/
+static int spi_is_quad(struct fmc_spi *spi)
+{
+ const char *if_str[] = {"STD", "DUAL", "DIO", "QUAD", "QIO"};
+
+ FMC_PR(QE_DBG, "\t\t|||*-SPI read iftype: %s write iftype: %s\n",
+ if_str[spi->read->iftype], if_str[spi->write->iftype]);
+
+ if ((spi->read->iftype == IF_TYPE_QUAD)
+ || (spi->read->iftype == IF_TYPE_QIO)
+ || (spi->write->iftype == IF_TYPE_QUAD)
+ || (spi->write->iftype == IF_TYPE_QIO)) {
+ return 1;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************/
+/*
+ Send set features cmd to SPI Nand, feature[B0H]:[0]bit QE would be set
+*/
+static int spi_general_qe_enable(struct fmc_spi *spi)
+{
+ unsigned int reg, op;
+ const char *str[] = {"Disable", "Enable"};
+
+ FMC_PR(QE_DBG, "\t||*-Start SPI Nand flash QE\n");
+
+ op = spi_is_quad(spi);
+
+ FMC_PR(QE_DBG, "\t|||*-End Quad check, SPI Nand %s Quad.\n", str[op]);
+
+ reg = spi_nand_feature_op(spi, GET_OP, FEATURE_ADDR, 0);
+ FMC_PR(QE_DBG, "\t|||-Get [%#x]feature: %#x\n", FEATURE_ADDR, reg);
+ if ((reg & FEATURE_QE_ENABLE) == op) {
+ FMC_PR(QE_DBG, "\t||*-SPI Nand quad was %sd!\n", str[op]);
+ return op;
+ }
+
+ if (op == ENABLE) {
+ reg |= FEATURE_QE_ENABLE;
+ } else {
+ reg &= ~FEATURE_QE_ENABLE;
+ }
+
+ spi_nand_feature_op(spi, SET_OP, FEATURE_ADDR, reg);
+ FMC_PR(QE_DBG, "\t|||-SPI Nand %s Quad\n", str[op]);
+
+ spi->driver->wait_ready(spi);
+
+ reg = spi_nand_feature_op(spi, GET_OP, FEATURE_ADDR, 0);
+ if ((reg & FEATURE_QE_ENABLE) == op) {
+ FMC_PR(QE_DBG, "\t|||-SPI Nand %s Quad succeed!\n", str[op]);
+ } else {
+ DB_MSG("Error: %s Quad failed! reg: %#x\n", str[op], reg);
+ }
+
+ FMC_PR(QE_DBG, "\t||*-End SPI Nand %s Quad.\n", str[op]);
+
+ return op;
+}
diff -urN linux-4.9.37/drivers/mtd/nand/gkfmc100/fmc_spi_nand_ids.c linux-4.9.y/drivers/mtd/nand/gkfmc100/fmc_spi_nand_ids.c
--- linux-4.9.37/drivers/mtd/nand/gkfmc100/fmc_spi_nand_ids.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/mtd/nand/gkfmc100/fmc_spi_nand_ids.c 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,2270 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#include <asm/setup.h>
+#include <linux/types.h>
+#include <linux/io.h>
+#include <linux/sched.h>
+#include <linux/printk.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <mach/platform.h>
+
+#include "../nfc_gen.h"
+#include "fmc100.h"
+
+/*****************************************************************************/
+SET_READ_STD(1, INFINITE, 24);
+
+SET_READ_FAST(1, INFINITE, 80);
+SET_READ_FAST(1, INFINITE, 100);
+SET_READ_FAST(1, INFINITE, 104);
+SET_READ_FAST(1, INFINITE, 108);
+SET_READ_FAST(1, INFINITE, 120);
+SET_READ_FAST(1, INFINITE, 133);
+
+SET_READ_DUAL(1, INFINITE, 80);
+SET_READ_DUAL(1, INFINITE, 100);
+SET_READ_DUAL(1, INFINITE, 104);
+SET_READ_DUAL(1, INFINITE, 108);
+SET_READ_DUAL(1, INFINITE, 120);
+SET_READ_DUAL(1, INFINITE, 133);
+
+SET_READ_DUAL_ADDR(1, INFINITE, 40);
+SET_READ_DUAL_ADDR(1, INFINITE, 80);
+SET_READ_DUAL_ADDR(2, INFINITE, 80);
+SET_READ_DUAL_ADDR(1, INFINITE, 100);
+SET_READ_DUAL_ADDR(1, INFINITE, 104);
+SET_READ_DUAL_ADDR(1, INFINITE, 108);
+SET_READ_DUAL_ADDR(1, INFINITE, 120);
+SET_READ_DUAL_ADDR(2, INFINITE, 104);
+
+SET_READ_QUAD(1, INFINITE, 80);
+SET_READ_QUAD(1, INFINITE, 100);
+SET_READ_QUAD(1, INFINITE, 104);
+SET_READ_QUAD(1, INFINITE, 108);
+SET_READ_QUAD(1, INFINITE, 120);
+SET_READ_QUAD(1, INFINITE, 133);
+
+SET_READ_QUAD_ADDR(2, INFINITE, 40);
+SET_READ_QUAD_ADDR(1, INFINITE, 80);
+SET_READ_QUAD_ADDR(2, INFINITE, 80);
+SET_READ_QUAD_ADDR(4, INFINITE, 80);
+SET_READ_QUAD_ADDR(1, INFINITE, 100);
+SET_READ_QUAD_ADDR(1, INFINITE, 104);
+SET_READ_QUAD_ADDR(2, INFINITE, 104);
+SET_READ_QUAD_ADDR(1, INFINITE, 108);
+SET_READ_QUAD_ADDR(1, INFINITE, 120);
+SET_READ_QUAD_ADDR(4, INFINITE, 104);
+
+/*****************************************************************************/
+SET_WRITE_STD(0, 256, 24);
+SET_WRITE_STD(0, 256, 75);
+SET_WRITE_STD(0, 256, 80);
+SET_WRITE_STD(0, 256, 100);
+SET_WRITE_STD(0, 256, 104);
+SET_WRITE_STD(0, 256, 133);
+
+SET_WRITE_QUAD(0, 256, 80);
+SET_WRITE_QUAD(0, 256, 100);
+SET_WRITE_QUAD(0, 256, 104);
+SET_WRITE_QUAD(0, 256, 108);
+SET_WRITE_QUAD(0, 256, 120);
+SET_WRITE_QUAD(0, 256, 133);
+
+/*****************************************************************************/
+SET_ERASE_SECTOR_128K(0, _128K, 24);
+SET_ERASE_SECTOR_128K(0, _128K, 75);
+SET_ERASE_SECTOR_128K(0, _128K, 80);
+SET_ERASE_SECTOR_128K(0, _128K, 104);
+SET_ERASE_SECTOR_128K(0, _128K, 133);
+
+SET_ERASE_SECTOR_256K(0, _256K, 24);
+SET_ERASE_SECTOR_256K(0, _256K, 75);
+SET_ERASE_SECTOR_256K(0, _256K, 80);
+SET_ERASE_SECTOR_256K(0, _256K, 100);
+SET_ERASE_SECTOR_256K(0, _256K, 104);
+SET_ERASE_SECTOR_256K(0, _256K, 133);
+
+/*****************************************************************************/
+#include "fmc100_spi_general.c"
+static struct spi_drv spi_driver_general = {
+ .wait_ready = spi_general_wait_ready,
+ .write_enable = spi_general_write_enable,
+ .qe_enable = spi_general_qe_enable,
+};
+
+/* some spi nand flash default QUAD enable, needn't to set qe enable */
+static struct spi_drv spi_driver_no_qe = {
+ .wait_ready = spi_general_wait_ready,
+ .write_enable = spi_general_write_enable,
+};
+
+/*****************************************************************************/
+#define SPI_NAND_ID_TAB_VER "2.7"
+
+/******* SPI Nand ID Table ***************************************************
+ * Version Manufacturer Chip Name Size Operation
+ * 1.0 ESMT F50L512M41A 64MB Add 5 chip
+ * GD 5F1GQ4UAYIG 128MB
+ * GD 5F2GQ4UAYIG 256MB
+ * GD GD5F2GQ5UEYIG 256MB
+ * GD 5F4GQ4UAYIG 512MB
+ * GD 5F4GQ4UBYIG 512MB
+ * GD 5F1GQ4RB9IG 128MB
+ * GD 5F1GQ4UEYIHY 128MB
+ * 1.1 ESMT F50L1G41A 128MB Add 2 chip
+ * Winbond W25N01GV 128MB
+ * Winbond W25N02JWZEIF 256MB
+ * 1.2 GD 5F1GQ4UBYIG 128MB Add 2 chip
+ * GD 5F2GQ4U9IGR/BYIG 256MB
+ * GD 1.8V 5F4GQ6RE9IG 512MB
+ * 1.3 ATO ATO25D1GA 128MB Add 1 chip
+ * 1.4 MXIC MX35LF1GE4AB 128MB Add 2 chip
+ * MXIC MX35LF2GE4AB 256MB (SOP-16Pin)
+ * 1.5 Paragon PN26G01A 128MB Add 1 chip
+ * 1.6 All-flash AFS1GQ4UAC 128MB Add 1 chip
+ * 1.7 TOSHIBA TC58CVG0S3H 128MB Add 2 chip
+ * TOSHIBA TC58CVG2S0H 512MB
+ * 1.8 ALL-flash AFS2GQ4UAD 256MB Add 2 chip
+ * Paragon PN26G02A 256MB
+ * 1.9 TOSHIBA TC58CVG1S3H 256MB Add 1 chip
+ * 2.0 HeYangTek HYF1GQ4UAACAE 128MB Add 3 chip
+ * HeYangTek HYF2GQ4UAACAE 256MB
+ * HeYangTek HYF4GQ4UAACBE 512MB
+ * 2.1 Micron MT29F1G01ABA 128MB Add 5 chip
+ TOSHIBA 1.8V TC58CYG0S3H 128MB
+ TOSHIBA 1.8V TC58CYG1S3H 256MB
+ TOSHIBA 1.8V TC58CYG2S0H 512MB
+ Winbond 1.8V W25N01GWZEIG 128MB
+ * 2.2 Micron MT29F2G01ABA 256MB Add 1 chip
+ * 2.3 MXIC MX35LF2G14AC 256MB Add 1 chip
+ * 2.4 GD 1.8V 5F4GQ4RAYIG 512MB Add 1 chip
+ * 2.5 GD 1.8V 5F2GQ4RB9IGR 256MB Add 1 chip
+ * 2.6 MXIC 1.8V MX35UF1G14AC 128MB Add 4 chip
+ * MXIC 1.8V MX35UF2G14AC 256MB
+ * Micron 1.8V MT29F1G01ABB 128MB
+ * Micron 1.8V MT29F2G01ABB 256MB
+ * 2.7 Dosilicon DS35Q1GA-IB 128MB Add 2 chip
+ * Dosilicon DS35Q2GA-IB 256MB
+ * GD 5F1GQ4RB9IGR 128MB
+ * Micron MT29F4G01ADAG 512MB 3.3V Add 1 chip
+ * GD 1.8V 5F4GQ4RBYIG 512MB Add 1 chip
+ * Etron 1.8V EM78D044VCF-H 256MB
+ * Etron 3.3V EM73C044VCC-H 128MB
+ * XTX 3.3V XT26G01B 1Gbit 128MB
+ * Micron MT29F4G01ABBFDW 512MB 1.8V
+ * FM FM25S01-DND-A-G 128MB 3.3V
+ * FM FM25S01A 128MB 3.3V
+ ******************************************************************************/
+struct spi_nand_info fmc_spi_nand_flash_table[] = {
+ /* Micron MT29F1G01ABA 1GBit */
+ {
+ .name = "MT29F1G01ABA",
+ .id = {0x2C, 0x14},
+ .id_len = 2,
+ .chipsize = _128M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 128,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 80),
+ &READ_DUAL(1, INFINITE, 80),
+ &READ_DUAL_ADDR(1, INFINITE, 80),
+ &READ_QUAD(1, INFINITE, 80),
+ &READ_QUAD_ADDR(2, INFINITE, 80),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 80),
+ &WRITE_QUAD(0, 256, 80),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 80),
+ 0
+ },
+ .driver = &spi_driver_no_qe,
+ },
+
+ /* Micron MT29F1G01ABB 1GBit 1.8V */
+ {
+ .name = "MT29F1G01ABB",
+ .id = {0x2C, 0x15},
+ .id_len = 2,
+ .chipsize = _128M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 128,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 80),
+ &READ_DUAL(1, INFINITE, 80),
+ &READ_DUAL_ADDR(1, INFINITE, 80),
+ &READ_QUAD(1, INFINITE, 80),
+ &READ_QUAD_ADDR(2, INFINITE, 80),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 80),
+ &WRITE_QUAD(0, 256, 80),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 80),
+ 0
+ },
+ .driver = &spi_driver_no_qe,
+ },
+
+ /* Micron MT29F2G01ABA 2GBit */
+ {
+ .name = "MT29F2G01ABA",
+ .id = {0x2C, 0x24},
+ .id_len = 2,
+ .chipsize = _256M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 128,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 108),
+ &READ_DUAL(1, INFINITE, 108),
+ &READ_DUAL_ADDR(1, INFINITE, 108),
+ &READ_QUAD(1, INFINITE, 108),
+ &READ_QUAD_ADDR(2, INFINITE, 104),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 80),
+ &WRITE_QUAD(0, 256, 108),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 80),
+ 0
+ },
+ .driver = &spi_driver_no_qe,
+ },
+
+ /* Micron MT29F2G01ABB 2GBit 1.8V */
+ {
+ .name = "MT29F2G01ABB",
+ .id = {0x2C, 0x25},
+ .id_len = 2,
+ .chipsize = _256M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 128,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 80),
+ &READ_DUAL(1, INFINITE, 80),
+ &READ_DUAL_ADDR(1, INFINITE, 80),
+ &READ_QUAD(1, INFINITE, 80),
+ &READ_QUAD_ADDR(2, INFINITE, 80),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 80),
+ &WRITE_QUAD(0, 256, 80),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 80),
+ 0
+ },
+ .driver = &spi_driver_no_qe,
+ },
+
+ /* Micron MT29F4G01ADAG 4GBit 3.3V */
+ {
+ .name = "MT29F4G01ADAG",
+ .id = {0x2C, 0x36},
+ .id_len = 2,
+ .chipsize = _512M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 128,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 108),
+ &READ_DUAL(1, INFINITE, 108),
+ &READ_DUAL_ADDR(1, INFINITE, 108),
+ &READ_QUAD(1, INFINITE, 108),
+ &READ_QUAD_ADDR(2, INFINITE, 104),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 80),
+ &WRITE_QUAD(0, 256, 108),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 80),
+ 0
+ },
+ .driver = &spi_driver_no_qe,
+ },
+
+ /* ESMT F50L512M41A 512Mbit */
+ {
+ .name = "F50L512M41A",
+ .id = {0xC8, 0x20},
+ .id_len = 2,
+ .chipsize = _64M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 64,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 104),
+ &READ_DUAL(1, INFINITE, 104),
+ &READ_QUAD(1, INFINITE, 104),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 24),
+ &WRITE_QUAD(0, 256, 104),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 24),
+ 0
+ },
+ .driver = &spi_driver_no_qe,
+ },
+
+ /* ESMT F50L1G41A 1Gbit */
+ {
+ .name = "F50L1G41A",
+ .id = {0xC8, 0x21},
+ .id_len = 2,
+ .chipsize = _128M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 64,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 104),
+ &READ_DUAL(1, INFINITE, 104),
+ &READ_QUAD(1, INFINITE, 104),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 24),
+ &WRITE_QUAD(0, 256, 104),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 24),
+ 0
+ },
+ .driver = &spi_driver_no_qe,
+ },
+
+ /* ESMT F50L1G41LB-104YG2ME 1Gbit */
+ {
+ .name = "F50L1G41LB-104YG2ME",
+ .id = {0xC8, 0x01, 0X7F},
+ .id_len = 3,
+ .chipsize = _128M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 64,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 104),
+ &READ_DUAL(1, INFINITE, 104),
+ &READ_QUAD(1, INFINITE, 104),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 104),
+ &WRITE_QUAD(0, 256, 104),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 104),
+ 0
+ },
+ .driver = &spi_driver_no_qe,
+ },
+
+ /* GD 3.3v GD5F1GQ4UAYIG 1Gbit */
+ {
+ .name = "GD5F1GQ4UAYIG",
+ .id = {0xc8, 0xf1},
+ .id_len = 2,
+ .chipsize = _128M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 64,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 120),
+ &READ_DUAL(1, INFINITE, 120),
+ &READ_DUAL_ADDR(1, INFINITE, 120),
+ &READ_QUAD(1, INFINITE, 120),
+ &READ_QUAD_ADDR(1, INFINITE, 120),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 24),
+ &WRITE_QUAD(0, 256, 120),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 24),
+ 0
+ },
+ .driver = &spi_driver_general,
+ },
+
+ /* GD 3.3v GD5F1GQ4UEYIHY 1Gbit */
+ {
+ .name = "GD5F1GQ4UEYIHY",
+ .id = {0xc8, 0xd9},
+ .id_len = 2,
+ .chipsize = _128M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 64,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 120),
+ &READ_DUAL(1, INFINITE, 120),
+ &READ_DUAL_ADDR(1, INFINITE, 120),
+ &READ_QUAD(1, INFINITE, 120),
+ &READ_QUAD_ADDR(1, INFINITE, 120),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 104),
+ &WRITE_QUAD(0, 256, 120),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 104),
+ 0
+ },
+ .driver = &spi_driver_general,
+ },
+
+ /* GD 1.8v GD5F1GQ4RB9IG 1Gbit */
+ {
+ .name = "GD5F1GQ4RB9IG",
+ .id = {0xc8, 0xc1},
+ .id_len = 2,
+ .chipsize = _128M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 128,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 120),
+ &READ_DUAL(1, INFINITE, 120),
+ &READ_DUAL_ADDR(1, INFINITE, 120),
+ &READ_QUAD(1, INFINITE, 120),
+ &READ_QUAD_ADDR(1, INFINITE, 120),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 24),
+ &WRITE_QUAD(0, 256, 120),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 24),
+ 0
+ },
+ .driver = &spi_driver_general,
+ },
+
+ /* GD 3.3v GD5F1GQ4UBYIG 1Gbit */
+ {
+ .name = "GD5F1GQ4UBYIG",
+ .id = {0xc8, 0xd1},
+ .id_len = 2,
+ .chipsize = _128M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 128,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 120),
+ &READ_DUAL(1, INFINITE, 120),
+ &READ_DUAL_ADDR(1, INFINITE, 120),
+ &READ_QUAD(1, INFINITE, 120),
+ &READ_QUAD_ADDR(1, INFINITE, 120),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 24),
+ &WRITE_QUAD(0, 256, 120),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 24),
+ 0
+ },
+ .driver = &spi_driver_general,
+ },
+
+ /* GD 3.3v GD5F2GQ4UAYIG 2Gbit */
+ {
+ .name = "GD5F2GQ4UAYIG",
+ .id = {0xc8, 0xf2},
+ .id_len = 2,
+ .chipsize = _256M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 64,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 120),
+ &READ_DUAL(1, INFINITE, 120),
+ &READ_DUAL_ADDR(1, INFINITE, 120),
+ &READ_QUAD(1, INFINITE, 120),
+ &READ_QUAD_ADDR(1, INFINITE, 120),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 24),
+ &WRITE_QUAD(0, 256, 120),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 24),
+ 0
+ },
+ .driver = &spi_driver_general,
+ },
+
+ /* GD 3.3v GD5F2GQ4U9IGR/BYIG 2Gbit */
+ {
+ .name = "GD5F2GQ4U9IGR/BYIG",
+ .id = {0xc8, 0xd2},
+ .id_len = 2,
+ .chipsize = _256M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 128,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 120),
+ &READ_DUAL(1, INFINITE, 120),
+ &READ_DUAL_ADDR(1, INFINITE, 120),
+ &READ_QUAD(1, INFINITE, 120),
+ &READ_QUAD_ADDR(1, INFINITE, 120),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 24),
+ &WRITE_QUAD(0, 256, 120),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 24),
+ 0
+ },
+ .driver = &spi_driver_general,
+ },
+ /* GD 3.3v GD5F2GQ5UEYIG 2Gbit */
+ {
+ .name = "GD5F2GQ5UEYIG",
+ .id = {0xc8, 0x52},
+ .id_len = 2,
+ .chipsize = _256M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 128,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 104),
+ &READ_DUAL(1, INFINITE, 104),
+ &READ_DUAL_ADDR(2, INFINITE, 104),
+ &READ_QUAD(1, INFINITE, 104),
+ &READ_QUAD_ADDR(4, INFINITE, 104),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 104),
+ &WRITE_QUAD(0, 256, 120),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 104),
+ 0
+ },
+ .driver = &spi_driver_general,
+ },
+
+ /* GD 3.3v GD5F4GQ4UAYIG 4Gbit */
+ {
+ .name = "GD5F4GQ4UAYIG",
+ .id = {0xc8, 0xf4},
+ .id_len = 2,
+ .chipsize = _512M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 64,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 120),
+ &READ_DUAL(1, INFINITE, 120),
+ &READ_DUAL_ADDR(1, INFINITE, 120),
+ &READ_QUAD(1, INFINITE, 120),
+ &READ_QUAD_ADDR(1, INFINITE, 120),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 24),
+ &WRITE_QUAD(0, 256, 120),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 24),
+ 0
+ },
+ .driver = &spi_driver_general,
+ },
+
+ /* GD 3.3v GD5F4GQ4UBYIG 4Gbit */
+ {
+ .name = "GD5F4GQ4UBYIG",
+ .id = {0xc8, 0xd4},
+ .id_len = 2,
+ .chipsize = _512M,
+ .erasesize = _256K,
+ .pagesize = _4K,
+ .oobsize = 256,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 120),
+ &READ_DUAL(1, INFINITE, 120),
+ &READ_DUAL_ADDR(1, INFINITE, 120),
+ &READ_QUAD(1, INFINITE, 120),
+ &READ_QUAD_ADDR(1, INFINITE, 120),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 24),
+ &WRITE_QUAD(0, 256, 120),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_256K(0, _256K, 24),
+ 0
+ },
+ .driver = &spi_driver_general,
+ },
+
+ /* GD 3.3v GD5F4GQ6UEYIG 4Gbit */
+ {
+ .name = "GD5F4GQ6UEYIG",
+ .id = {0xc8, 0x55},
+ .id_len = 2,
+ .chipsize = _512M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 128,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24), /* 24MHz */
+ &READ_FAST(1, INFINITE, 104), /* 104MHz */
+ &READ_DUAL(1, INFINITE, 104), /* 104MHz */
+ &READ_DUAL_ADDR(2, INFINITE, 104), /* 104MHz */
+ &READ_QUAD(1, INFINITE, 104), /* 104MHz */
+ &READ_QUAD_ADDR(4, INFINITE, 104), /* 104MHz */
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 24), /* 24MHz */
+ &WRITE_QUAD(0, 256, 104), /* 104MHz */
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 104), /* 104MHz */
+ 0
+ },
+ .driver = &spi_driver_general,
+ },
+
+ /* GD 1.8V GD5F1GQ4RB9IGR 1Gbit */
+ {
+ .name = "GD5F1GQ4RB9IGR",
+ .id = {0xc8, 0xc1},
+ .id_len = 2,
+ .chipsize = _128M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 128,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 104),
+ &READ_DUAL(1, INFINITE, 104),
+ &READ_DUAL_ADDR(1, INFINITE, 104),
+ &READ_QUAD(1, INFINITE, 104),
+ &READ_QUAD_ADDR(1, INFINITE, 104),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 24),
+ &WRITE_QUAD(0, 256, 104),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 24),
+ 0
+ },
+ .driver = &spi_driver_general,
+ },
+
+ /* GD 1.8V GD5F2GQ4RB9IGR 2Gbit */
+ {
+ .name = "GD5F2GQ4RB9IGR",
+ .id = {0xc8, 0xc2},
+ .id_len = 2,
+ .chipsize = _256M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 128,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 104),
+ &READ_DUAL(1, INFINITE, 104),
+ &READ_DUAL_ADDR(1, INFINITE, 104),
+ &READ_QUAD(1, INFINITE, 104),
+ &READ_QUAD_ADDR(1, INFINITE, 104),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 24),
+ &WRITE_QUAD(0, 256, 104),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 24),
+ 0
+ },
+ .driver = &spi_driver_general,
+ },
+ /* GD 1.8V 5F4GQ6RE9IG 4Gbit */
+ {
+ .name = "GD5F4GQ6RE9IG",
+ .id = {0xc8, 0x45},
+ .id_len = 2,
+ .chipsize = _512M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 128,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 80),
+ &READ_DUAL(1, INFINITE, 80),
+ &READ_DUAL_ADDR(2, INFINITE, 80),
+ &READ_QUAD(1, INFINITE, 80),
+ &READ_QUAD_ADDR(4, INFINITE, 80),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 80),
+ &WRITE_QUAD(0, 256, 80),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 80),
+ 0
+ },
+ .driver = &spi_driver_general,
+ },
+ /* GD 1.8V GD5F4GQ4RAYIG 4Gbit */
+ {
+ .name = "GD5F4GQ4RAYIG",
+ .id = {0xc8, 0xe4},
+ .id_len = 2,
+ .chipsize = _512M,
+ .erasesize = _256K,
+ .pagesize = _4K,
+ .oobsize = 256,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 104),
+ &READ_DUAL(1, INFINITE, 104),
+ &READ_DUAL_ADDR(1, INFINITE, 104),
+ &READ_QUAD(1, INFINITE, 104),
+ &READ_QUAD_ADDR(1, INFINITE, 104),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 24),
+ &WRITE_QUAD(0, 256, 104),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_256K(0, _256K, 24),
+ 0
+ },
+ .driver = &spi_driver_general,
+ },
+
+ /* Winbond 1.8V W25N02JWZEIF 2Gbit */
+ {
+ .name = "W25N02JWZEIF",
+ .id = {0xef, 0xbf, 0x22},
+ .id_len = 3,
+ .chipsize = _256M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 64,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 120),
+ &READ_DUAL(1, INFINITE, 120),
+ &READ_DUAL_ADDR(1, INFINITE, 120),
+ &READ_QUAD(1, INFINITE, 120),
+ &READ_QUAD_ADDR(2, INFINITE, 104),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 104),
+ &WRITE_QUAD(0, 256, 104),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 104),
+ 0
+ },
+ .driver = &spi_driver_general,
+ },
+
+ /* GD 1.8V 5F4GQ4RBYIG 4Gbit */
+ {
+ .name = "5F4GQ4RBYIG",
+ .id = {0xc8, 0xc4},
+ .id_len = 2,
+ .chipsize = _512M,
+ .erasesize = _256K,
+ .pagesize = _4K,
+ .oobsize = 256,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 120),
+ &READ_DUAL(1, INFINITE, 120),
+ &READ_DUAL_ADDR(1, INFINITE, 120),
+ &READ_QUAD(1, INFINITE, 120),
+ &READ_QUAD_ADDR(1, INFINITE, 120),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 24),
+ &WRITE_QUAD(0, 256, 120),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_256K(0, _256K, 24),
+ 0
+ },
+ .driver = &spi_driver_general,
+ },
+
+ /* Winbond W25N01GV 1Gbit 3.3V */
+ {
+ .name = "W25N01GV",
+ .id = {0xef, 0xaa, 0x21},
+ .id_len = 3,
+ .chipsize = _128M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 64,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 104),
+ &READ_DUAL(1, INFINITE, 104),
+ &READ_DUAL_ADDR(1, INFINITE, 104),
+ &READ_QUAD(1, INFINITE, 104),
+ &READ_QUAD_ADDR(2, INFINITE, 104),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 24),
+ &WRITE_QUAD(0, 256, 104),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 24),
+ 0
+ },
+ .driver = &spi_driver_no_qe,
+ },
+
+ /* Winbond W25N01GWZEIG 1Gbit 1.8V */
+ {
+ .name = "W25N01GWZEIG",
+ .id = {0xef, 0xba, 0x21},
+ .id_len = 3,
+ .chipsize = _128M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 64,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 104),
+ &READ_DUAL(1, INFINITE, 104),
+ &READ_DUAL_ADDR(1, INFINITE, 104),
+ &READ_QUAD(1, INFINITE, 104),
+ &READ_QUAD_ADDR(2, INFINITE, 104),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 24),
+ &WRITE_QUAD(0, 256, 80),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 24),
+ 0
+ },
+ .driver = &spi_driver_no_qe,
+ },
+
+ /* ATO ATO25D1GA 1Gbit */
+ {
+ .name = "ATO25D1GA",
+ .id = {0x9b, 0x12},
+ .id_len = 2,
+ .chipsize = _128M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 64,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 104),
+ &READ_QUAD(1, INFINITE, 104),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 24),
+ &WRITE_QUAD(0, 256, 104),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 24),
+ 0
+ },
+ .driver = &spi_driver_general,
+ },
+
+ /* MXIC MX35LF1GE4AB 1Gbit */
+ {
+ .name = "MX35LF1GE4AB",
+ .id = {0xc2, 0x12},
+ .id_len = 2,
+ .chipsize = _128M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 64,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 104),
+ &READ_QUAD(1, INFINITE, 104),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 24),
+ &WRITE_QUAD(0, 256, 104),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 24),
+ 0
+ },
+ .driver = &spi_driver_general,
+ },
+
+ /* MXIC MX35UF1G14AC 1Gbit 1.8V */
+ {
+ .name = "MX35UF1G14AC",
+ .id = {0xc2, 0x90},
+ .id_len = 2,
+ .chipsize = _128M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 64,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 104),
+ &READ_QUAD(1, INFINITE, 104),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 24),
+ &WRITE_QUAD(0, 256, 104),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 104),
+ 0
+ },
+ .driver = &spi_driver_general,
+ },
+
+ /* MXIC MX35LF2GE4AB 2Gbit SOP-16Pin */
+ {
+ .name = "MX35LF2GE4AB",
+ .id = {0xc2, 0x22},
+ .id_len = 2,
+ .chipsize = _256M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 64,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 104),
+ &READ_QUAD(1, INFINITE, 104),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 24),
+ &WRITE_QUAD(0, 256, 104),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 24),
+ 0
+ },
+ .driver = &spi_driver_general,
+ },
+
+ /* MXIC MX35LF2G14AC 2GBit */
+ {
+ .name = "MX35LF2G14AC",
+ .id = {0xc2, 0x20},
+ .id_len = 2,
+ .chipsize = _256M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 64,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 104),
+ &READ_QUAD(1, INFINITE, 104),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 24),
+ &WRITE_QUAD(0, 256, 104),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 24),
+ 0
+ },
+ .driver = &spi_driver_general,
+ },
+
+ /* MXIC MX35UF2G14AC 2Gbit 1.8V */
+ {
+ .name = "MX35UF2G14AC",
+ .id = {0xc2, 0xa0},
+ .id_len = 2,
+ .chipsize = _256M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 64,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 104),
+ &READ_QUAD(1, INFINITE, 104),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 24),
+ &WRITE_QUAD(0, 256, 104),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 104),
+ 0
+ },
+ .driver = &spi_driver_general,
+ },
+
+ /* Paragon PN26G01A 1Gbit */
+ {
+ .name = "PN26G01A",
+ .id = {0xa1, 0xe1},
+ .id_len = 2,
+ .chipsize = _128M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 128,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 108),
+ &READ_DUAL(1, INFINITE, 108),
+ &READ_DUAL_ADDR(1, INFINITE, 108),
+ &READ_QUAD(1, INFINITE, 108),
+ &READ_QUAD_ADDR(1, INFINITE, 108),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 24),
+ &WRITE_QUAD(0, 256, 108),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 24),
+ 0
+ },
+ .driver = &spi_driver_general,
+ },
+
+ /* Paragon PN26G02A 2Gbit */
+ {
+ .name = "PN26G02A",
+ .id = {0xa1, 0xe2},
+ .id_len = 2,
+ .chipsize = _256M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 128,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 108),
+ &READ_DUAL(1, INFINITE, 108),
+ &READ_DUAL_ADDR(1, INFINITE, 108),
+ &READ_QUAD(1, INFINITE, 108),
+ &READ_QUAD_ADDR(1, INFINITE, 108),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 24),
+ &WRITE_QUAD(0, 256, 108),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 24),
+ 0
+ },
+ .driver = &spi_driver_general,
+ },
+
+ /* All-flash AFS1GQ4UAC 1Gbit */
+ {
+ .name = "AFS1GQ4UAC",
+ .id = {0xc1, 0x51},
+ .id_len = 2,
+ .chipsize = _128M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 128,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 80),
+ &READ_DUAL(1, INFINITE, 80),
+ &READ_DUAL_ADDR(1, INFINITE, 80),
+ &READ_QUAD(1, INFINITE, 80),
+ &READ_QUAD_ADDR(1, INFINITE, 80),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 24),
+ &WRITE_QUAD(0, 256, 80),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 24),
+ 0
+ },
+ .driver = &spi_driver_general,
+ },
+
+ /* All-flash AFS2GQ4UAD 2Gbit */
+ {
+ .name = "AFS2GQ4UAD",
+ .id = {0xc1, 0x52},
+ .id_len = 2,
+ .chipsize = _256M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 128,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 80),
+ &READ_DUAL(1, INFINITE, 80),
+ &READ_DUAL_ADDR(1, INFINITE, 80),
+ &READ_QUAD(1, INFINITE, 80),
+ &READ_QUAD_ADDR(1, INFINITE, 80),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 24),
+ &WRITE_QUAD(0, 256, 80),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 24),
+ 0
+ },
+ .driver = &spi_driver_general,
+ },
+
+ /* TOSHIBA TC58CVG0S3H 1Gbit */
+ {
+ .name = "TC58CVG0S3H",
+ .id = {0x98, 0xc2},
+ .id_len = 2,
+ .chipsize = _128M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 128,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 104),
+ &READ_DUAL(1, INFINITE, 104),
+ &READ_QUAD(1, INFINITE, 104),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 104),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 104),
+ 0
+ },
+ .driver = &spi_driver_no_qe,
+ },
+
+ /* TOSHIBA TC58CVG0S3HRAIJ 1Gbit */
+ {
+ .name = "TC58CVG0S3HRAIJ",
+ .id = {0x98, 0xe2, 0x40},
+ .id_len = 3,
+ .chipsize = _128M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 128,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 133),
+ &READ_DUAL(1, INFINITE, 133),
+ &READ_QUAD(1, INFINITE, 133),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 133),
+ &WRITE_QUAD(0, 256, 133),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 133),
+ 0
+ },
+ .driver = &spi_driver_no_qe,
+ },
+
+ /* TOSHIBA TC58CYG0S3H 1.8V 1Gbit */
+ {
+ .name = "TC58CYG0S3H",
+ .id = {0x98, 0xb2},
+ .id_len = 2,
+ .chipsize = _128M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 128,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 104),
+ &READ_DUAL(1, INFINITE, 104),
+ &READ_QUAD(1, INFINITE, 104),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 104),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 104),
+ 0
+ },
+ .driver = &spi_driver_no_qe,
+ },
+
+ /* TOSHIBA TC58CYG0S3HRAIJ 1.8V 1Gbit */
+ {
+ .name = "TC58CYG0S3HRAIJ",
+ .id = {0x98, 0xD2, 0x40},
+ .id_len = 3,
+ .chipsize = _128M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 128,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 133),
+ &READ_DUAL(1, INFINITE, 133),
+ &READ_QUAD(1, INFINITE, 133),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 133),
+ &WRITE_QUAD(0, 256, 133),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 133),
+ 0
+ },
+ .driver = &spi_driver_no_qe,
+ },
+
+ /* TOSHIBA TC58CVG1S3H 2Gbit */
+ {
+ .name = "TC58CVG1S3H",
+ .id = {0x98, 0xcb},
+ .id_len = 2,
+ .chipsize = _256M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 128,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 104),
+ &READ_DUAL(1, INFINITE, 104),
+ &READ_QUAD(1, INFINITE, 104),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 104),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 104),
+ 0
+ },
+ .driver = &spi_driver_no_qe,
+ },
+
+ /* TOSHIBA TC58CVG1S3HRAIJ 2Gbit */
+ {
+ .name = "TC58CVG1S3HRAIJ",
+ .id = {0x98, 0xeb, 0x40},
+ .id_len = 3,
+ .chipsize = _256M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 128,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 133),
+ &READ_DUAL(1, INFINITE, 133),
+ &READ_QUAD(1, INFINITE, 133),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 133),
+ &WRITE_QUAD(0, 256, 133),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 133),
+ 0
+ },
+ .driver = &spi_driver_no_qe,
+ },
+
+ /* TOSHIBA TC58CYG1S3H 1.8V 2Gbit */
+ {
+ .name = "TC58CYG1S3H",
+ .id = {0x98, 0xbb},
+ .id_len = 2,
+ .chipsize = _256M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 128,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 104),
+ &READ_DUAL(1, INFINITE, 104),
+ &READ_QUAD(1, INFINITE, 104),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 75),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 75),
+ 0
+ },
+ .driver = &spi_driver_no_qe,
+ },
+
+ /* TOSHIBA TC58CVG2S0H 4Gbit */
+ {
+ .name = "TC58CVG2S0H",
+ .id = {0x98, 0xcd},
+ .id_len = 2,
+ .chipsize = _512M,
+ .erasesize = _256K,
+ .pagesize = _4K,
+ .oobsize = 256,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 104),
+ &READ_DUAL(1, INFINITE, 104),
+ &READ_QUAD(1, INFINITE, 104),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 104),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_256K(0, _256K, 104),
+ 0
+ },
+ .driver = &spi_driver_no_qe,
+ },
+
+ /* TOSHIBA TC58CVG2S0HRAIJ 4Gbit */
+ {
+ .name = "TC58CVG2S0HRAIJ",
+ .id = {0x98, 0xed, 0x51},
+ .id_len = 3,
+ .chipsize = _512M,
+ .erasesize = _256K,
+ .pagesize = _4K,
+ .oobsize = 256,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 133),
+ &READ_DUAL(1, INFINITE, 133),
+ &READ_QUAD(1, INFINITE, 133),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 133),
+ &WRITE_QUAD(0, 256, 133),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_256K(0, _256K, 133),
+ 0
+ },
+ .driver = &spi_driver_no_qe,
+ },
+
+ /* TOSHIBA TC58CYG2S0H 1.8V 4Gbit */
+ {
+ .name = "TC58CYG2S0H",
+ .id = {0x98, 0xbd},
+ .id_len = 2,
+ .chipsize = _512M,
+ .erasesize = _256K,
+ .pagesize = _4K,
+ .oobsize = 256,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 104),
+ &READ_DUAL(1, INFINITE, 104),
+ &READ_QUAD(1, INFINITE, 104),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 75),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_256K(0, _256K, 75),
+ 0
+ },
+ .driver = &spi_driver_no_qe,
+ },
+
+ /* KIOXIA TC58CYG2S0HRAIJ 1.8V 4Gbit */
+ {
+ .name = "TC58CYG2S0HRAIJ",
+ .id = {0x98, 0xdd, 0x51},
+ .id_len = 3,
+ .chipsize = _512M,
+ .erasesize = _256K,
+ .pagesize = _4K,
+ .oobsize = 256,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24), /* 24MHz */
+ &READ_FAST(1, INFINITE, 133), /* 133MHz */
+ &READ_DUAL(1, INFINITE, 133), /* 133MHz */
+ &READ_QUAD(1, INFINITE, 133), /* 133MHz */
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 133), /* 133MHz */
+ &WRITE_QUAD(0, 256, 133), /* 133MHz */
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_256K(0, _256K, 133), /* 133MHz */
+ 0
+ },
+ .driver = &spi_driver_no_qe,
+ },
+ /* KIOXIA TH58CYG3S0H 1.8V 8Gbit */
+ {
+ .name = "TH58CYG3S0H",
+ .id = {0x98, 0xd4, 0x51},
+ .id_len = 3,
+ .chipsize = _1G,
+ .erasesize = _256K,
+ .pagesize = _4K,
+ .oobsize = 256,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24), /* 24MHz */
+ &READ_FAST(1, INFINITE, 133), /* 133MHz */
+ &READ_DUAL(1, INFINITE, 133), /* 133MHz */
+ &READ_QUAD(1, INFINITE, 133), /* 133MHz */
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 133), /* 133MHz */
+ &WRITE_QUAD(0, 256, 133), /* 133MHz */
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_256K(0, _256K, 133), /* 133MHz */
+ 0
+ },
+ .driver = &spi_driver_no_qe,
+ },
+
+ /* HeYangTek HYF1GQ4UAACAE 1Gbit */
+ {
+ .name = "HYF1GQ4UAACAE",
+ .id = {0xc9, 0x51},
+ .id_len = 2,
+ .chipsize = _128M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 128,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 80),
+ &READ_DUAL(1, INFINITE, 80),
+ &READ_DUAL_ADDR(1, INFINITE, 80),
+ &READ_QUAD(1, INFINITE, 80),
+ &READ_QUAD_ADDR(1, INFINITE, 80),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 80),
+ &WRITE_QUAD(0, 256, 80),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 80),
+ 0
+ },
+ .driver = &spi_driver_general,
+ },
+
+ /* HeYangTek HYF2GQ4UAACAE 2Gbit */
+ {
+ .name = "HYF2GQ4UAACAE",
+ .id = {0xc9, 0x52},
+ .id_len = 2,
+ .chipsize = _256M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 128,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 80),
+ &READ_DUAL(1, INFINITE, 80),
+ &READ_DUAL_ADDR(1, INFINITE, 80),
+ &READ_QUAD(1, INFINITE, 80),
+ &READ_QUAD_ADDR(1, INFINITE, 80),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 80),
+ &WRITE_QUAD(0, 256, 80),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 80),
+ 0
+ },
+ .driver = &spi_driver_general,
+ },
+
+ /* HeYangTek HYF4GQ4UAACBE 4Gbit */
+ {
+ .name = "HYF4GQ4UAACBE",
+ .id = {0xc9, 0xd4},
+ .id_len = 2,
+ .chipsize = _512M,
+ .erasesize = _256K,
+ .pagesize = _4K,
+ .oobsize = 256,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 80),
+ &READ_DUAL(1, INFINITE, 80),
+ &READ_DUAL_ADDR(1, INFINITE, 80),
+ &READ_QUAD(1, INFINITE, 80),
+ &READ_QUAD_ADDR(1, INFINITE, 80),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 80),
+ &WRITE_QUAD(0, 256, 80),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_256K(0, _256K, 80),
+ 0
+ },
+ .driver = &spi_driver_general,
+ },
+
+ /* Dosilicon 3.3V DS35Q1GA-IB 1Gbit */
+ {
+ .name = "DS35Q1GA-IB",
+ .id = {0xe5, 0x71},
+ .id_len = 2,
+ .chipsize = _128M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 64,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 104),
+ &READ_DUAL(1, INFINITE, 104),
+ &READ_QUAD(1, INFINITE, 104),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 80),
+ &WRITE_QUAD(0, 256, 104),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 104),
+ 0
+ },
+ .driver = &spi_driver_general,
+ },
+
+ /* XTX 3.3V XT26G01B 1Gbit */
+ {
+ .name = "XT26G01B",
+ .id = {0x0B, 0xF1},
+ .id_len = 2,
+ .chipsize = _128M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 64,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 80),
+ &READ_DUAL(1, INFINITE, 80),
+ &READ_DUAL_ADDR(1, INFINITE, 80),
+ &READ_QUAD(1, INFINITE, 80),
+ &READ_QUAD_ADDR(1, INFINITE, 80),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 80),
+ &WRITE_QUAD(0, 256, 80),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 80),
+ 0
+ },
+ .driver = &spi_driver_general,
+ },
+
+ /* Etron 1.8V EM78F044VCA-H 8Gbit */
+ {
+ .name = "EM78F044VCA-H",
+ .id = {0xD5, 0x8D},
+ .id_len = 2,
+ .chipsize = _512M*2,
+ .erasesize = _256K,
+ .pagesize = _4K,
+ .oobsize = 256,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 100),
+ &READ_DUAL(1, INFINITE, 100),
+ &READ_DUAL_ADDR(1, INFINITE, 100),
+ &READ_QUAD(1, INFINITE, 100),
+ &READ_QUAD_ADDR(1, INFINITE, 100),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 100),
+ &WRITE_QUAD(0, 256, 100),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_256K(0, _256K, 100),
+ 0
+ },
+ .driver = &spi_driver_general,
+ },
+
+ /* Etron 1.8V EM78E044VCA-H 4Gbit */
+ {
+ .name = "EM78E044VCA-H",
+ .id = {0xD5, 0x8C},
+ .id_len = 2,
+ .chipsize = _512M,
+ .erasesize = _256K,
+ .pagesize = _4K,
+ .oobsize = 256,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 100),
+ &READ_DUAL(1, INFINITE, 100),
+ &READ_DUAL_ADDR(1, INFINITE, 100),
+ &READ_QUAD(1, INFINITE, 100),
+ &READ_QUAD_ADDR(1, INFINITE, 100),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 100),
+ &WRITE_QUAD(0, 256, 100),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_256K(0, _256K, 100),
+ 0
+ },
+ .driver = &spi_driver_general,
+ },
+
+ /* Etron 1.8V EM78D044VCF-H 2Gbit */
+ {
+ .name = "EM78D044VCF-H",
+ .id = {0xd5, 0x81},
+ .id_len = 2,
+ .chipsize = _256M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 64,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 104),
+ &READ_DUAL(1, INFINITE, 104),
+ &READ_DUAL_ADDR(1, INFINITE, 104),
+ &READ_QUAD(1, INFINITE, 104),
+ &READ_QUAD_ADDR(1, INFINITE, 104),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 80),
+ &WRITE_QUAD(0, 256, 104),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 104),
+ 0
+ },
+ .driver = &spi_driver_general,
+ },
+
+ /* Etron 3.3V EM73C044VCC-H 1Gbit */
+ {
+ .name = "EM73C044VCC-H",
+ .id = {0xd5, 0x22},
+ .id_len = 2,
+ .chipsize = _128M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 64,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 120),
+ &READ_DUAL(1, INFINITE, 120),
+ &READ_DUAL_ADDR(1, INFINITE, 120),
+ &READ_QUAD(1, INFINITE, 120),
+ &READ_QUAD_ADDR(1, INFINITE, 120),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 104),
+ &WRITE_QUAD(0, 256, 120),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 104),
+ 0
+ },
+ .driver = &spi_driver_general,
+ },
+
+ /* Micron MT29F4G01ABBFDWB 4GBit 1.8V */
+ {
+ .name = "MT29F4G01ABBFDWB",
+ .id = {0x2C, 0x35},
+ .id_len = 2,
+ .chipsize = _512M,
+ .erasesize = _256K,
+ .pagesize = _4K,
+ .oobsize = 256,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 80),
+ &READ_DUAL(1, INFINITE, 80),
+ &READ_QUAD(1, INFINITE, 80),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 80),
+ &WRITE_QUAD(0, 256, 80),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_256K(0, _256K, 80),
+ 0
+ },
+ .driver = &spi_driver_no_qe,
+ },
+
+ /* Dosilicon 3.3V DS35Q2GA-IB 1Gb */
+ {
+ .name = "DS35Q2GA-IB",
+ .id = {0xe5, 0x72},
+ .id_len = 2,
+ .chipsize = _256M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 64,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24),
+ &READ_FAST(1, INFINITE, 104),
+ &READ_DUAL(1, INFINITE, 104),
+ &READ_QUAD(1, INFINITE, 104),
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 80),
+ &WRITE_QUAD(0, 256, 104),
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 104),
+ 0
+ },
+ .driver = &spi_driver_general,
+ },
+
+ /* FM 3.3v FM25S01-DND-A-G 1Gbit */
+ {
+ .name = "FM25S01-DND-A-G",
+ .id = {0xa1, 0xa1},
+ .id_len = 2,
+ .chipsize = _128M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 128,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24), /* 24MHz */
+ &READ_FAST(1, INFINITE, 104), /* 104MHz */
+ &READ_DUAL(1, INFINITE, 104), /* 104MHz */
+ &READ_DUAL_ADDR(1, INFINITE, 40), /* 40MHz */
+ &READ_QUAD(1, INFINITE, 104), /* 104MHz */
+ &READ_QUAD_ADDR(2, INFINITE, 40), /* 40MHz */
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 104), /* 104MHz */
+ &WRITE_QUAD(0, 256, 104), /* 104MHz */
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 104), /* 104MHz */
+ 0
+ },
+ .driver = &spi_driver_no_qe,
+ },
+
+ /* FM 3.3v FM25S01A 1Gbit */
+ {
+ .name = "FM25S01A",
+ .id = {0xa1, 0xe4},
+ .id_len = 2,
+ .chipsize = _128M,
+ .erasesize = _128K,
+ .pagesize = _2K,
+ .oobsize = 64,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .read = {
+ &READ_STD(1, INFINITE, 24), /* 104MHz */
+ &READ_FAST(1, INFINITE, 104), /* 104MHz */
+ &READ_DUAL(1, INFINITE, 104), /* 104MHz */
+ &READ_DUAL_ADDR(1, INFINITE, 40), /* 70MHz */
+ &READ_QUAD(1, INFINITE, 104), /* 104MHz */
+ &READ_QUAD_ADDR(2, INFINITE, 40), /* 70MHz */
+ 0
+ },
+ .write = {
+ &WRITE_STD(0, 256, 104), /* 104MHz */
+ &WRITE_QUAD(0, 256, 104), /* 104MHz */
+ 0
+ },
+ .erase = {
+ &ERASE_SECTOR_128K(0, _128K, 104), /* 104MHz */
+ 0
+ },
+ .driver = &spi_driver_no_qe,
+ },
+
+ { .id_len = 0, },
+};
+
+/*****************************************************************************/
+static void fmc100_spi_nand_search_rw(struct spi_nand_info *spiinfo,
+ struct spi_op *spiop_rw, u_int iftype, u_int max_dummy, int rw_type)
+{
+ int ix = 0;
+ struct spi_op **spiop, **fitspiop;
+
+ for (fitspiop = spiop = (rw_type ? spiinfo->write : spiinfo->read);
+ (*spiop) && ix < MAX_SPI_OP; spiop++, ix++) {
+ if (((*spiop)->iftype & iftype)
+ && ((*spiop)->dummy <= max_dummy)
+ && (*fitspiop)->iftype < (*spiop)->iftype) {
+ fitspiop = spiop;
+ }
+ }
+ memcpy(spiop_rw, (*fitspiop), sizeof(struct spi_op));
+}
+
+/*****************************************************************************/
+static void fmc100_spi_nand_get_erase(struct spi_nand_info *spiinfo,
+ struct spi_op *spiop_erase)
+{
+ int ix;
+
+ spiop_erase->size = 0;
+ for (ix = 0; ix < MAX_SPI_OP; ix++) {
+ if (spiinfo->erase[ix] == NULL) {
+ break;
+ }
+ if (spiinfo->erasesize == spiinfo->erase[ix]->size) {
+ memcpy(&spiop_erase[ix], spiinfo->erase[ix],
+ sizeof(struct spi_op));
+ break;
+ }
+ }
+}
+
+/*****************************************************************************/
+static void fmc100_map_spi_op(struct fmc_spi *spi)
+{
+ unsigned char ix;
+ const int iftype_read[] = {
+ SPI_IF_READ_STD, IF_TYPE_STD,
+ SPI_IF_READ_FAST, IF_TYPE_STD,
+ SPI_IF_READ_DUAL, IF_TYPE_DUAL,
+ SPI_IF_READ_DUAL_ADDR, IF_TYPE_DIO,
+ SPI_IF_READ_QUAD, IF_TYPE_QUAD,
+ SPI_IF_READ_QUAD_ADDR, IF_TYPE_QIO,
+ 0, 0,
+ };
+ const int iftype_write[] = {
+ SPI_IF_WRITE_STD, IF_TYPE_STD,
+ SPI_IF_WRITE_QUAD, IF_TYPE_QUAD,
+ 0, 0,
+ };
+ const char *if_str[] = {"STD", "DUAL", "DIO", "QUAD", "QIO"};
+
+ FMC_PR(BT_DBG, "\t||*-Start Get SPI operation iftype\n");
+
+ for (ix = 0; iftype_write[ix]; ix += 2) {
+ if (spi->write->iftype == iftype_write[ix]) {
+ spi->write->iftype = iftype_write[ix + 1];
+ break;
+ }
+ }
+ FMC_PR(BT_DBG, "\t|||-Get best write iftype: %s \n",
+ if_str[spi->write->iftype]);
+
+ for (ix = 0; iftype_read[ix]; ix += 2) {
+ if (spi->read->iftype == iftype_read[ix]) {
+ spi->read->iftype = iftype_read[ix + 1];
+ break;
+ }
+ }
+ FMC_PR(BT_DBG, "\t|||-Get best read iftype: %s \n",
+ if_str[spi->read->iftype]);
+
+ spi->erase->iftype = IF_TYPE_STD;
+ FMC_PR(BT_DBG, "\t|||-Get best erase iftype: %s \n",
+ if_str[spi->erase->iftype]);
+
+ FMC_PR(BT_DBG, "\t||*-End Get SPI operation iftype \n");
+}
+
+/*****************************************************************************/
+static void fmc100_spi_ids_probe(struct mtd_info *mtd,
+ struct spi_nand_info *spi_dev)
+{
+ unsigned int reg;
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct fmc_host *host = chip->priv;
+ struct fmc_spi *spi = host->spi;
+
+ FMC_PR(BT_DBG, "\t|*-Start match SPI operation & chip init\n");
+
+ spi->host = host;
+ spi->name = spi_dev->name;
+ spi->driver = spi_dev->driver;
+
+ fmc100_spi_nand_search_rw(spi_dev, spi->read,
+ FMC_SPI_NAND_SUPPORT_READ,
+ FMC_SPI_NAND_SUPPORT_MAX_DUMMY, RW_OP_READ);
+ FMC_PR(BT_DBG, "\t||-Save spi->read op cmd:%#x\n", spi->read->cmd);
+
+ fmc100_spi_nand_search_rw(spi_dev, spi->write,
+ FMC_SPI_NAND_SUPPORT_WRITE,
+ FMC_SPI_NAND_SUPPORT_MAX_DUMMY, RW_OP_WRITE);
+ FMC_PR(BT_DBG, "\t||-Save spi->write op cmd:%#x\n", spi->write->cmd);
+
+ fmc100_spi_nand_get_erase(spi_dev, spi->erase);
+ FMC_PR(BT_DBG, "\t||-Save spi->erase op cmd:%#x\n", spi->erase->cmd);
+
+ fmc100_map_spi_op(spi);
+
+ if (spi->driver->qe_enable) {
+ spi->driver->qe_enable(spi);
+ }
+
+ /* Disable write protection */
+ reg = spi_nand_feature_op(spi, GET_OP, PROTECT_ADDR, 0);
+ FMC_PR(BT_DBG, "\t||-Get protect status[%#x]: %#x\n", PROTECT_ADDR,
+ reg);
+ if (ANY_BP_ENABLE(reg)) {
+ reg &= ~ALL_BP_MASK;
+ spi_nand_feature_op(spi, SET_OP, PROTECT_ADDR, reg);
+ FMC_PR(BT_DBG, "\t||-Set [%#x]FT %#x\n", PROTECT_ADDR, reg);
+
+ spi->driver->wait_ready(spi);
+
+ reg = spi_nand_feature_op(spi, GET_OP, PROTECT_ADDR, 0);
+ FMC_PR(BT_DBG, "\t||-Check BP disable result: %#x\n", reg);
+ if (ANY_BP_ENABLE(reg)) {
+ DB_MSG("Error: Write protection disable failed!\n");
+ }
+ }
+
+ /* Disable chip internal ECC */
+ reg = spi_nand_feature_op(spi, GET_OP, FEATURE_ADDR, 0);
+ FMC_PR(BT_DBG, "\t||-Get feature status[%#x]: %#x\n", FEATURE_ADDR,
+ reg);
+ if (reg & FEATURE_ECC_ENABLE) {
+ reg &= ~FEATURE_ECC_ENABLE;
+ spi_nand_feature_op(spi, SET_OP, FEATURE_ADDR, reg);
+ FMC_PR(BT_DBG, "\t||-Set [%#x]FT: %#x\n", FEATURE_ADDR, reg);
+
+ spi->driver->wait_ready(spi);
+
+ reg = spi_nand_feature_op(spi, GET_OP, FEATURE_ADDR, 0);
+ FMC_PR(BT_DBG, "\t||-Check internal ECC disable result: %#x\n",
+ reg);
+ if (reg & FEATURE_ECC_ENABLE) {
+ DB_MSG("Error: Chip internal ECC disable failed!\n");
+ }
+ }
+
+ fmc_cs_user[host->cmd_op.cs]++;
+
+ FMC_PR(BT_DBG, "\t|*-End match SPI operation & chip init\n");
+}
+
+static struct nand_flash_dev spi_nand_dev;
+/*****************************************************************************/
+static struct nand_flash_dev *spi_nand_get_flash_info(struct mtd_info *mtd,
+ unsigned char *id)
+{
+ unsigned char ix, len = 0;
+ char buffer[100];
+ struct nand_chip *chip = mtd_to_nand(mtd);
+ struct fmc_host *host = chip->priv;
+ struct spi_nand_info *spi_dev = fmc_spi_nand_flash_table;
+ struct nand_flash_dev *type = &spi_nand_dev;
+
+ FMC_PR(BT_DBG, "\t*-Start find SPI Nand flash\n");
+
+ len = sprintf(buffer, "SPI Nand(cs %d) ID: %#x %#x",
+ host->cmd_op.cs, id[0], id[1]);
+
+ for (; spi_dev->id_len; spi_dev++) {
+ if (memcmp(id, spi_dev->id, spi_dev->id_len)) {
+ continue;
+ }
+
+ for (ix = 2; ix < spi_dev->id_len; ix++) {
+ len += sprintf(buffer + len, " %#x", id[ix]);
+ }
+ pr_info("%s\n", buffer);
+
+ FMC_PR(BT_DBG, "\t||-CS(%d) found SPI Nand: %s\n",
+ host->cmd_op.cs, spi_dev->name);
+
+ type->name = spi_dev->name;
+ memcpy(type->id, spi_dev->id, spi_dev->id_len);
+ type->pagesize = spi_dev->pagesize;
+ type->chipsize = spi_dev->chipsize >> 20;
+ type->erasesize = spi_dev->erasesize;
+ type->id_len = spi_dev->id_len;
+ type->oobsize = spi_dev->oobsize;
+ FMC_PR(BT_DBG, "\t|-Save struct nand_flash_dev info\n");
+
+ mtd->oobsize = spi_dev->oobsize;
+ mtd->erasesize = spi_dev->erasesize;
+ mtd->writesize = spi_dev->pagesize;
+ chip->chipsize = spi_dev->chipsize;
+
+ fmc100_spi_ids_probe(mtd, spi_dev);
+
+ FMC_PR(BT_DBG, "\t*-Found SPI nand: %s\n", spi_dev->name);
+
+ return type;
+ }
+
+ FMC_PR(BT_DBG, "\t*-Not found SPI nand flash, %s\n", buffer);
+
+ return NULL;
+}
+
+/*****************************************************************************/
+void fmc_spi_nand_ids_register(void)
+{
+ pr_info("SPI Nand ID Table Version %s\n", SPI_NAND_ID_TAB_VER);
+ get_spi_nand_flash_type_hook = spi_nand_get_flash_info;
+}
+
+#ifdef CONFIG_PM
+/*****************************************************************************/
+void fmc100_spi_nand_config(struct fmc_host *host)
+{
+ unsigned int reg;
+ struct fmc_spi *spi = host->spi;
+ static const char *str[] = {"STD", "DUAL", "DIO", "QUAD", "QIO"};
+
+ /* judge whether support QUAD read/write or not, set it if yes */
+ FMC_PR(PM_DBG, "\t|-SPI read iftype: %s write iftype: %s\n",
+ str[spi->read->iftype], str[spi->write->iftype]);
+
+ if (spi->driver->qe_enable) {
+ spi->driver->qe_enable(spi);
+ }
+
+ /* Disable write protection */
+ reg = spi_nand_feature_op(spi, GET_OP, PROTECT_ADDR, 0);
+ FMC_PR(PM_DBG, "\t|-Get protect status[%#x]: %#x\n", PROTECT_ADDR,
+ reg);
+ if (ANY_BP_ENABLE(reg)) {
+ reg &= ~ALL_BP_MASK;
+ spi_nand_feature_op(spi, SET_OP, PROTECT_ADDR, reg);
+ FMC_PR(PM_DBG, "\t|-Set [%#x]FT %#x\n", PROTECT_ADDR, reg);
+
+ spi->driver->wait_ready(spi);
+
+ reg = spi_nand_feature_op(spi, GET_OP, PROTECT_ADDR, 0);
+ FMC_PR(PM_DBG, "\t|-Check BP disable result: %#x\n", reg);
+ if (ANY_BP_ENABLE(reg)) {
+ DB_MSG("Error: Write protection disable failed!\n");
+ }
+ }
+
+ /* Disable chip internal ECC */
+ reg = spi_nand_feature_op(spi, GET_OP, FEATURE_ADDR, 0);
+ FMC_PR(PM_DBG, "\t|-Get feature status[%#x]: %#x\n", FEATURE_ADDR,
+ reg);
+ if (reg & FEATURE_ECC_ENABLE) {
+ reg &= ~FEATURE_ECC_ENABLE;
+ spi_nand_feature_op(spi, SET_OP, FEATURE_ADDR, reg);
+ FMC_PR(PM_DBG, "\t|-Set [%#x]FT: %#x\n", FEATURE_ADDR, reg);
+
+ spi->driver->wait_ready(spi);
+
+ reg = spi_nand_feature_op(spi, GET_OP, FEATURE_ADDR, 0);
+ FMC_PR(PM_DBG, "\t|-Check internal ECC disable result: %#x\n",
+ reg);
+ if (reg & FEATURE_ECC_ENABLE) {
+ DB_MSG("Error: Chip internal ECC disable failed!\n");
+ }
+ }
+}
+/*****************************************************************************/
+#endif /* CONFIG_PM */
diff -urN linux-4.9.37/drivers/mtd/nand/gkfmc100/Kconfig linux-4.9.y/drivers/mtd/nand/gkfmc100/Kconfig
--- linux-4.9.37/drivers/mtd/nand/gkfmc100/Kconfig 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/mtd/nand/gkfmc100/Kconfig 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,17 @@
+#
+# goke flash memory controller SPI nand device driver version 100
+# drivers/mtd/nand/gkfmc100/Kconfig
+# add by goke 2017.8.7
+#
+
+config MTD_SPI_NAND_FMC100
+ bool "Goke Flash Memory Controller v100 SPI Nand devices support"
+ depends on MFD_GOKE_FMC && MTD_SPI_NAND_GOKE
+ select MISC_FILESYSTEMS
+ select MTD_BLOCK
+ select YAFFS_FS
+ select YAFFS_YAFFS2
+ help
+ Goke Flash Memory Controller version 100 is called fmc100 for
+ short. The controller driver support registers and DMA transfers
+ while reading or writing the SPI nand flash.
diff -urN linux-4.9.37/drivers/mtd/nand/gkfmc100/Makefile linux-4.9.y/drivers/mtd/nand/gkfmc100/Makefile
--- linux-4.9.37/drivers/mtd/nand/gkfmc100/Makefile 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/mtd/nand/gkfmc100/Makefile 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,26 @@
+#
+# The Flash Memory Controller v100 Device Driver for goke
+#
+# Copyright (c) 2016-2017 Goke Technologies Co., Ltd.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+#
+
+#
+# drivers/mtd/nand/gkfmc100/Makefile
+#
+
+obj-y += fmc_spi_nand_ids.o
+obj-y += fmc100.o fmc100_os.o
diff -urN linux-4.9.37/drivers/mtd/nand/Kconfig linux-4.9.y/drivers/mtd/nand/Kconfig
--- linux-4.9.37/drivers/mtd/nand/Kconfig 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/mtd/nand/Kconfig 2021-06-07 13:01:33.000000000 +0300
@@ -569,4 +569,28 @@
Enables support for NAND controller on MTK SoCs.
This controller is found on mt27xx, mt81xx, mt65xx SoCs.
+config MTD_SPI_NAND_GOKE
+ tristate "Support for SPI NAND controller on Goke SoCs"
+ depends on MTD_NAND
+ help
+ Enables support for the SPI NAND device drivers.
+
+config GOKE_NAND_ECC_STATUS_REPORT
+ tristate "Report the ecc status to MTD for Goke Nand Driver"
+ depends on MTD_NAND && ARCH_GOKE
+ default n
+ help
+ Flash Memory Controller reports the ecc status include ECC error
+ and ECC corrected to MTD to monitor the aging of devices.
+
+config GOKE_NAND_FS_MAY_NO_YAFFS2
+ bool "Remove the restraintion of 16bit ecc type on yaffs2 to Goke"
+ depends on MFD_GOKE_FMC
+ default n
+ help
+ The ecc type: 16bit is limited by the Goke flash memory controller,
+ as the yaffs2 tag of goke rootfs limits the min size of CTRL len is 28.
+
+source "drivers/mtd/nand/gkfmc100/Kconfig"
+
endif # MTD_NAND
diff -urN linux-4.9.37/drivers/mtd/nand/Makefile linux-4.9.y/drivers/mtd/nand/Makefile
--- linux-4.9.37/drivers/mtd/nand/Makefile 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/mtd/nand/Makefile 2021-06-07 13:01:33.000000000 +0300
@@ -8,6 +8,7 @@
obj-$(CONFIG_MTD_NAND_IDS) += nand_ids.o
obj-$(CONFIG_MTD_SM_COMMON) += sm_common.o
+obj-$(CONFIG_MTD_SPI_NAND_FMC100) += gkfmc100/
obj-$(CONFIG_MTD_NAND_CAFE) += cafe_nand.o
obj-$(CONFIG_MTD_NAND_AMS_DELTA) += ams-delta.o
obj-$(CONFIG_MTD_NAND_DENALI) += denali.o
@@ -59,4 +60,4 @@
obj-$(CONFIG_MTD_NAND_QCOM) += qcom_nandc.o
obj-$(CONFIG_MTD_NAND_MTK) += mtk_nand.o mtk_ecc.o
-nand-objs := nand_base.o nand_bbt.o nand_timings.o
+nand-objs := nand_base.o nand_bbt.o nand_timings.o nfc_gen.o nfc_spl_ids.o match_table.o
diff -urN linux-4.9.37/drivers/mtd/nand/match_table.c linux-4.9.y/drivers/mtd/nand/match_table.c
--- linux-4.9.37/drivers/mtd/nand/match_table.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/mtd/nand/match_table.c 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#include <linux/string.h>
+#include "match_table.h"
+
+/*****************************************************************************/
+int reg2type(struct match_reg_type *table, int length, int reg, int def)
+{
+ while (length-- > 0) {
+ if (table->reg == reg) {
+ return table->type;
+ }
+ table++;
+ }
+ return def;
+}
+
+int type2reg(struct match_reg_type *table, int length, int type, int def)
+{
+ while (length-- > 0) {
+ if (table->type == type) {
+ return table->reg;
+ }
+ table++;
+ }
+ return def;
+}
+
+int str2type(struct match_type_str *table, int length, const char *str,
+ int size, int def)
+{
+ while (length-- > 0) {
+ if (!strncmp(table->str, str, size)) {
+ return table->type;
+ }
+ table++;
+ }
+ return def;
+}
+
+const char *type2str(struct match_type_str *table, int length, int type,
+ const char *def)
+{
+ while (length-- > 0) {
+ if (table->type == type) {
+ return table->str;
+ }
+ table++;
+ }
+ return def;
+}
+
+int match_reg_to_type(struct match_t *table, int nr_table, int reg, int def)
+{
+ while (nr_table-- > 0) {
+ if (table->reg == reg) {
+ return table->type;
+ }
+ table++;
+ }
+ return def;
+}
+
+int match_type_to_reg(struct match_t *table, int nr_table, int type, int def)
+{
+ while (nr_table-- > 0) {
+ if (table->type == type) {
+ return table->reg;
+ }
+ table++;
+ }
+ return def;
+}
+
+int match_data_to_type(struct match_t *table, int nr_table,const char *data,
+ int size, int def)
+{
+ while (nr_table-- > 0) {
+ if (!memcmp(table->data, data, size)) {
+ return table->type;
+ }
+ table++;
+ }
+ return def;
+}
+
+void *match_type_to_data(struct match_t *table, int nr_table, int type,
+ const void *def)
+{
+ while (nr_table-- > 0) {
+ if (table->type == type) {
+ return table->data;
+ }
+ table++;
+ }
+ return (void *)def;
+}
diff -urN linux-4.9.37/drivers/mtd/nand/match_table.h linux-4.9.y/drivers/mtd/nand/match_table.h
--- linux-4.9.37/drivers/mtd/nand/match_table.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/mtd/nand/match_table.h 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#ifndef __MATCH_TABLE_H__
+#define __MATCH_TABLE_H__
+
+/*****************************************************************************/
+struct match_reg_type {
+ int reg;
+ int type;
+};
+
+struct match_type_str {
+ int type;
+ const char *str;
+};
+
+struct match_t {
+ int type;
+ int reg;
+ void *data;
+};
+
+/*****************************************************************************/
+#define MATCH_SET_TYPE_REG(_type, _reg) {(_type), (_reg), (void *)0}
+#define MATCH_SET_TYPE_DATA(_type, _data) {(_type), 0, (void *)(_data)}
+#define MATCH_SET(_type, _reg, _data) {(_type), (_reg), (void *)(_data)}
+
+/*****************************************************************************/
+int reg2type(struct match_reg_type *table, int length, int reg, int def);
+
+int type2reg(struct match_reg_type *table, int length, int type, int def);
+
+int str2type(struct match_type_str *table, int length, const char *str,
+ int size, int def);
+
+const char *type2str(struct match_type_str *table, int length, int type,
+ const char *def);
+
+int match_reg_to_type(struct match_t *table, int nr_table, int reg, int def);
+
+int match_type_to_reg(struct match_t *table, int nr_table, int type, int def);
+
+int match_data_to_type(struct match_t *table, int nr_table,const char *data,
+ int size, int def);
+
+void *match_type_to_data(struct match_t *table, int nr_table, int type,
+ const void *def);
+
+/*****************************************************************************/
+
+#endif /* End of __MATCH_TABLE_H__ */
diff -urN linux-4.9.37/drivers/mtd/nand/nand_base.c linux-4.9.y/drivers/mtd/nand/nand_base.c
--- linux-4.9.37/drivers/mtd/nand/nand_base.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/mtd/nand/nand_base.c 2021-06-07 13:01:33.000000000 +0300
@@ -47,6 +47,8 @@
#include <linux/mtd/partitions.h>
#include <linux/of.h>
+#include "nfc_gen.h"
+
static int nand_get_device(struct mtd_info *mtd, int new_state);
static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
@@ -2808,6 +2810,10 @@
int ret;
int oob_required = oob ? 1 : 0;
+#ifdef CONFIG_ARCH_GOKE
+ oob_required = 1;
+#endif
+
ops->retlen = 0;
if (!writelen)
return 0;
@@ -4058,7 +4064,7 @@
int *maf_id, int *dev_id,
struct nand_flash_dev *type)
{
- int busw;
+ int busw = 0;
int i, maf_idx;
u8 id_data[8];
@@ -4097,6 +4103,30 @@
return ERR_PTR(-ENODEV);
}
+#ifdef CONFIG_ARCH_GOKE
+
+#ifndef CONFIG_MTD_SPI_NAND_GOKE
+ /* Parallel Nand Flash */
+
+ /* The 3rd id byte holds MLC / multichip data */
+ chip->bits_per_cell = nand_get_bits_per_cell(id_data[2]);
+#endif
+
+ if (get_spi_nand_flash_type_hook)
+ type = get_spi_nand_flash_type_hook(mtd, id_data);
+
+ if (type)
+ goto ident_done;
+#ifdef CONFIG_MTD_SPI_NAND_GOKE
+ else {
+ pr_info("This device[%02x,%02x] cannot found in spi nand id table!!\n",
+ *maf_id, *dev_id);
+ return ERR_PTR(-ENODEV);
+ }
+#endif
+
+#endif /* endif CONFIG_ARCH_GOKE */
+
if (!type)
type = nand_flash_ids;
@@ -4144,6 +4174,9 @@
if (*maf_id != NAND_MFR_SAMSUNG && !type->pagesize)
chip->options &= ~NAND_SAMSUNG_LP_OPTIONS;
ident_done:
+#ifdef CONFIG_ARCH_GOKE
+ nfc_nand_param_adjust(mtd, chip);
+#endif
/* Try to identify manufacturer */
for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_idx++) {
@@ -4205,9 +4238,13 @@
pr_info("%s %s\n", nand_manuf_ids[maf_idx].name,
type->name);
- pr_info("%d MiB, %s, erase size: %d KiB, page size: %d, OOB size: %d\n",
+ pr_info("%dMiB, %s, page size: %d\n",
(int)(chip->chipsize >> 20), nand_is_slc(chip) ? "SLC" : "MLC",
- mtd->erasesize >> 10, mtd->writesize, mtd->oobsize);
+ mtd->writesize);
+
+ /* Print ecc type and ecc mode about goke flash controller */
+ nfc_show_info(mtd, nand_manuf_ids[maf_idx].name, type->name);
+
return type;
}
@@ -4727,7 +4764,7 @@
break;
case NAND_ECC_NONE:
- pr_warn("NAND_ECC_NONE selected by board driver. This is not recommended!\n");
+ pr_warn(" ECC provided by Flash Memory Controller\n");
ecc->read_page = nand_read_page_raw;
ecc->write_page = nand_write_page_raw;
ecc->read_oob = nand_read_oob_std;
@@ -4814,8 +4851,13 @@
break;
}
+#ifdef CONFIG_MTD_UBI
+ /* mtd->type = MTD_MLCNANDFLASH isn't support by mtd_util ubi tools jet */
+ mtd->type = MTD_NANDFLASH;
+#else
/* Fill in remaining MTD driver data */
mtd->type = nand_is_slc(chip) ? MTD_NANDFLASH : MTD_MLCNANDFLASH;
+#endif
mtd->flags = (chip->options & NAND_ROM) ? MTD_CAP_ROM :
MTD_CAP_NANDFLASH;
mtd->_erase = nand_erase;
diff -urN linux-4.9.37/drivers/mtd/nand/nand_ids.c linux-4.9.y/drivers/mtd/nand/nand_ids.c
--- linux-4.9.37/drivers/mtd/nand/nand_ids.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/mtd/nand/nand_ids.c 2021-06-07 13:01:33.000000000 +0300
@@ -168,7 +168,7 @@
/* Manufacturer IDs */
struct nand_manufacturers nand_manuf_ids[] = {
{NAND_MFR_TOSHIBA, "Toshiba"},
- {NAND_MFR_ESMT, "ESMT"},
+ {NAND_MFR_GD_ESMT, "GD/ESMT"},
{NAND_MFR_SAMSUNG, "Samsung"},
{NAND_MFR_FUJITSU, "Fujitsu"},
{NAND_MFR_NATIONAL, "National"},
@@ -179,9 +179,17 @@
{NAND_MFR_AMD, "AMD/Spansion"},
{NAND_MFR_MACRONIX, "Macronix"},
{NAND_MFR_EON, "Eon"},
+ {NAND_MFR_WINBOND, "Winbond"},
+ {NAND_MFR_ATO, "ATO"},
+ {NAND_MFR_MXIC, "MXIC"},
+ {NAND_MFR_ALL_FLASH, "All-flash"},
+ {NAND_MFR_PARAGON, "Paragon"},
{NAND_MFR_SANDISK, "SanDisk"},
{NAND_MFR_INTEL, "Intel"},
{NAND_MFR_ATO, "ATO"},
+ {NAND_MFR_HEYANGTEK, "HeYangTek"},
+ {NAND_MFR_DOSILICON, "Dosilicon"},
+ {NAND_MFR_FIDELIX, "Fidelix/Dosi"}, /* Fidelix was purchased by Dosilicon */
{0x0, "Unknown"}
};
diff -urN linux-4.9.37/drivers/mtd/nand/nfc_gen.c linux-4.9.y/drivers/mtd/nand/nfc_gen.c
--- linux-4.9.37/drivers/mtd/nand/nfc_gen.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/mtd/nand/nfc_gen.c 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#include <linux/mfd/goke_fmc.h>
+#include "match_table.h"
+#include "nfc_gen.h"
+
+/*****************************************************************************/
+struct nand_flash_dev *(*get_spi_nand_flash_type_hook)(struct mtd_info *mtd,
+ unsigned char *id) = NULL;
+
+/*****************************************************************************/
+static struct match_t match_ecc[] = {
+ MATCH_SET_TYPE_DATA(NAND_ECC_NONE, "none"),
+ MATCH_SET_TYPE_DATA(NAND_ECC_0BIT, "none"),
+ MATCH_SET_TYPE_DATA(NAND_ECC_1BIT_512, "1bit/512"),
+ MATCH_SET_TYPE_DATA(NAND_ECC_4BIT, "4bit/512"),
+ MATCH_SET_TYPE_DATA(NAND_ECC_4BIT_512, "4bit/512"),
+ MATCH_SET_TYPE_DATA(NAND_ECC_4BYTE, "4byte/1k"),
+ MATCH_SET_TYPE_DATA(NAND_ECC_8BIT, "4bit/512"),
+ MATCH_SET_TYPE_DATA(NAND_ECC_8BIT_512, "8bit/512"),
+ MATCH_SET_TYPE_DATA(NAND_ECC_8BYTE, "8byte/1k"),
+ MATCH_SET_TYPE_DATA(NAND_ECC_13BIT, "13bit/1k"),
+ MATCH_SET_TYPE_DATA(NAND_ECC_16BIT, "8bit/512"),
+ MATCH_SET_TYPE_DATA(NAND_ECC_18BIT, "18bit/1k"),
+ MATCH_SET_TYPE_DATA(NAND_ECC_24BIT, "24bit/1k"),
+ MATCH_SET_TYPE_DATA(NAND_ECC_27BIT, "27bit/1k"),
+ MATCH_SET_TYPE_DATA(NAND_ECC_32BIT, "32bit/1k"),
+ MATCH_SET_TYPE_DATA(NAND_ECC_40BIT, "40bit/1k"),
+ MATCH_SET_TYPE_DATA(NAND_ECC_41BIT, "41bit/1k"),
+ MATCH_SET_TYPE_DATA(NAND_ECC_48BIT, "48bit/1k"),
+ MATCH_SET_TYPE_DATA(NAND_ECC_60BIT, "60bit/1k"),
+ MATCH_SET_TYPE_DATA(NAND_ECC_72BIT, "72bit/1k"),
+ MATCH_SET_TYPE_DATA(NAND_ECC_80BIT, "80bit/1k"),
+};
+
+const char *nand_ecc_name(int type)
+{
+ return (char *)match_type_to_data(match_ecc, ARRAY_SIZE(match_ecc),
+ type, "unknown");
+}
+
+char *get_ecctype_str(enum ecc_type ecctype)
+{
+ static char *ecctype_string[] = {
+ "None", "1bit/512Byte", "4bits/512Byte", "8bits/512Byte",
+ "24bits/1K", "40bits/1K", "unknown", "unknown"
+ };
+ return ecctype_string[((unsigned int)ecctype & 0x07)];
+}
+
+/*****************************************************************************/
+static struct match_type_str page2name[] = {
+ { NAND_PAGE_512B, "512" },
+ { NAND_PAGE_2K, "2K" },
+ { NAND_PAGE_4K, "4K" },
+ { NAND_PAGE_8K, "8K" },
+ { NAND_PAGE_16K, "16K" },
+ { NAND_PAGE_32K, "32K" },
+};
+
+const char *nand_page_name(int type)
+{
+ return type2str(page2name, ARRAY_SIZE(page2name), type, "unknown");
+}
+
+char *get_pagesize_str(enum page_type pagetype)
+{
+ static char *pagesize_str[] = {
+ "512", "2K", "4K", "8K", "16K", "unknown",
+ "unknown", "unknown"
+ };
+ return pagesize_str[((unsigned int)pagetype & 0x07)];
+}
+
+/*****************************************************************************/
+static struct match_reg_type page2size[] = {
+ { _512B, NAND_PAGE_512B },
+ { _2K, NAND_PAGE_2K },
+ { _4K, NAND_PAGE_4K },
+ { _8K, NAND_PAGE_8K },
+ { _16K, NAND_PAGE_16K },
+ { _32K, NAND_PAGE_32K },
+};
+
+unsigned int get_pagesize(enum page_type pagetype)
+{
+ unsigned int pagesize[] = {
+ _512B, _2K, _4K, _8K, _16K, 0, 0, 0
+ };
+ return pagesize[((unsigned int)pagetype & 0x07)];
+}
+
+int nandpage_size2type(int size)
+{
+ return reg2type(page2size, ARRAY_SIZE(page2size), size, NAND_PAGE_2K);
+}
+
+int nandpage_type2size(int size)
+{
+ return type2reg(page2size, ARRAY_SIZE(page2size), size, NAND_PAGE_2K);
+}
+
+char *nand_dbgfs_options;
+
+static int __init dbgfs_options_setup(char *s)
+{
+ nand_dbgfs_options = s;
+ return 1;
+}
+__setup("nanddbgfs=", dbgfs_options_setup);
+
+/*****************************************************************************/
+
+int get_bits(unsigned int n)
+{
+ int loop;
+ int ret = 0;
+
+ if (!n)
+ return 0;
+
+ if (n > 0xFFFF)
+ loop = n > 0xFFFFFF ? 32 : 24;
+ else
+ loop = n > 0xFF ? 16 : 8;
+
+ while (loop-- > 0 && n) {
+ if (n & 1)
+ ret++;
+ n >>= 1;
+ }
+ return ret;
+}
+
+/*****************************************************************************/
+#define et_ecc_none 0x00
+#define et_ecc_4bit 0x02
+#define et_ecc_8bit 0x03
+#define et_ecc_24bit1k 0x04
+#define et_ecc_40bit1k 0x05
+#define et_ecc_64bit1k 0x06
+
+static struct match_reg_type ecc_yaffs_type_t[] = {
+ {et_ecc_none, NAND_ECC_0BIT},
+ {et_ecc_4bit, NAND_ECC_8BIT},
+ {et_ecc_8bit, NAND_ECC_16BIT},
+ {et_ecc_24bit1k, NAND_ECC_24BIT},
+ {et_ecc_40bit1k, NAND_ECC_40BIT},
+ {et_ecc_64bit1k, NAND_ECC_64BIT}
+};
+
+unsigned char match_ecc_type_to_yaffs(unsigned char type)
+{
+ return type2reg(ecc_yaffs_type_t, ARRAY_SIZE(ecc_yaffs_type_t), type,
+ et_ecc_4bit);
+}
+
+/*****************************************************************************/
+static struct match_t page_table[] = {
+ {NAND_PAGE_2K, PAGE_SIZE_2KB, "2K"},
+ {NAND_PAGE_4K, PAGE_SIZE_4KB, "4K"},
+ {NAND_PAGE_8K, PAGE_SIZE_8KB, "8K"},
+ {NAND_PAGE_16K, PAGE_SIZE_16KB, "16K"},
+};
+
+unsigned char match_page_reg_to_type(unsigned char reg)
+{
+ return match_reg_to_type(page_table, ARRAY_SIZE(page_table), reg,
+ NAND_PAGE_2K);
+}
+
+unsigned char match_page_type_to_reg(unsigned char type)
+{
+ return match_type_to_reg(page_table, ARRAY_SIZE(page_table), type,
+ PAGE_SIZE_2KB);
+}
+
+const char *match_page_type_to_str(unsigned char type)
+{
+ return match_type_to_data(page_table, ARRAY_SIZE(page_table), type,
+ "unknown");
+}
+
+/*****************************************************************************/
+static struct match_t ecc_table[] = {
+ {NAND_ECC_0BIT, ECC_TYPE_0BIT, "none"},
+ {NAND_ECC_8BIT, ECC_TYPE_8BIT, "4bit/512"},
+ {NAND_ECC_16BIT, ECC_TYPE_16BIT, "8bit/512"},
+ {NAND_ECC_24BIT, ECC_TYPE_24BIT, "24bit/1K"},
+ {NAND_ECC_28BIT, ECC_TYPE_28BIT, "28bit/1K"},
+ {NAND_ECC_40BIT, ECC_TYPE_40BIT, "40bit/1K"},
+ {NAND_ECC_64BIT, ECC_TYPE_64BIT, "64bit/1K"},
+};
+
+unsigned char match_ecc_reg_to_type(unsigned char reg)
+{
+ return match_reg_to_type(ecc_table, ARRAY_SIZE(ecc_table), reg,
+ NAND_ECC_8BIT);
+}
+
+unsigned char match_ecc_type_to_reg(unsigned char type)
+{
+ return match_type_to_reg(ecc_table, ARRAY_SIZE(ecc_table), type,
+ ECC_TYPE_8BIT);
+}
+
+const char *match_ecc_type_to_str(unsigned char type)
+{
+ return match_type_to_data(ecc_table, ARRAY_SIZE(ecc_table), type,
+ "unknown");
+}
+
+/*****************************************************************************/
+static struct match_t page_type_size_table[] = {
+ {NAND_PAGE_2K, _2K, NULL},
+ {NAND_PAGE_4K, _4K, NULL},
+ {NAND_PAGE_8K, _8K, NULL},
+ {NAND_PAGE_16K, _16K, NULL},
+};
+
+unsigned char match_page_size_to_type(unsigned int size)
+{
+ return match_reg_to_type(page_type_size_table,
+ ARRAY_SIZE(page_type_size_table), size, NAND_PAGE_2K);
+}
+
+unsigned int match_page_type_to_size(unsigned char type)
+{
+ return match_type_to_reg(page_type_size_table,
+ ARRAY_SIZE(page_type_size_table), type, _2K);
+}
diff -urN linux-4.9.37/drivers/mtd/nand/nfc_gen.h linux-4.9.y/drivers/mtd/nand/nfc_gen.h
--- linux-4.9.37/drivers/mtd/nand/nfc_gen.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/mtd/nand/nfc_gen.h 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,280 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#ifndef __NFC_GEN_H__
+#define __NFC_GEN_H__
+
+/*****************************************************************************/
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/string_helpers.h>
+#include <asm/setup.h>
+#include <linux/module.h>
+
+/*****************************************************************************/
+#define NFC_VER_300 (0x300)
+#define NFC_VER_301 (0x301)
+#define NFC_VER_310 (0x310)
+#define NFC_VER_504 (0x504)
+#define NFC_VER_505 (0x505)
+#define NFC_VER_600 (0x600)
+#define NFC_VER_610 (0x610)
+#define NFC_VER_620 (0x620)
+
+#define SNFC_VER_100 (0x400)
+
+/*****************************************************************************/
+#define NAND_PAGE_512B 0
+#define NAND_PAGE_1K 1
+#define NAND_PAGE_2K 2
+#define NAND_PAGE_4K 3
+#define NAND_PAGE_8K 4
+#define NAND_PAGE_16K 5
+#define NAND_PAGE_32K 6
+
+/*****************************************************************************/
+#define NAND_ECC_NONE 0
+#define NAND_ECC_0BIT 0
+#define NAND_ECC_1BIT 1
+#define NAND_ECC_1BIT_512 1
+#define NAND_ECC_4BIT 2
+#define NAND_ECC_4BIT_512 2
+#define NAND_ECC_4BYTE 2
+#define NAND_ECC_8BIT 2
+#define NAND_ECC_8BIT_512 3
+#define NAND_ECC_8BYTE 3
+#define NAND_ECC_13BIT 4
+#define NAND_ECC_16BIT 5
+#define NAND_ECC_18BIT 6
+#define NAND_ECC_24BIT 7
+#define NAND_ECC_27BIT 8
+#define NAND_ECC_28BIT 9
+#define NAND_ECC_32BIT 10
+#define NAND_ECC_40BIT 11
+#define NAND_ECC_41BIT 12
+#define NAND_ECC_42BIT 13
+#define NAND_ECC_48BIT 14
+#define NAND_ECC_60BIT 15
+#define NAND_ECC_64BIT 16
+#define NAND_ECC_72BIT 17
+#define NAND_ECC_80BIT 18
+
+enum ecc_type {
+ et_ecc_none = 0x00,
+ et_ecc_1bit = 0x01,
+ et_ecc_4bit = 0x02,
+ et_ecc_8bit = 0x03,
+ et_ecc_24bit1k = 0x04,
+ et_ecc_40bit1k = 0x05,
+ et_ecc_64bit1k = 0x06,
+};
+
+enum page_type {
+ pt_pagesize_512 = 0x00,
+ pt_pagesize_2K = 0x01,
+ pt_pagesize_4K = 0x02,
+ pt_pagesize_8K = 0x03,
+ pt_pagesize_16K = 0x04,
+};
+
+/*****************************************************************************/
+struct nand_config_info {
+ unsigned int pagetype;
+ unsigned int ecctype;
+ unsigned int ecc_strength;
+ unsigned int oobsize;
+ struct mtd_ooblayout_ops *ooblayout_ops;
+};
+
+struct nfc_host;
+
+struct nand_sync {
+
+#define SET_NAND_SYNC_TYPE(_mfr, _onfi, _version) \
+ ((((_mfr) & 0xFF) << 16) | (((_version) & 0xFF) << 8) \
+ | ((_onfi) & 0xFF))
+
+#define GET_NAND_SYNC_TYPE_MFR(_type) (((_type) >> 16) & 0xFF)
+#define GET_NAND_SYNC_TYPE_VER(_type) (((_type) >> 8) & 0xFF)
+#define GET_NAND_SYNC_TYPE_INF(_type) ((_type) & 0xFF)
+
+#define NAND_TYPE_ONFI_23_MICRON \
+ SET_NAND_SYNC_TYPE(NAND_MFR_MICRON, NAND_IS_ONFI, 0x23)
+#define NAND_TYPE_ONFI_30_MICRON \
+ SET_NAND_SYNC_TYPE(NAND_MFR_MICRON, NAND_IS_ONFI, 0x30)
+#define NAND_TYPE_TOGGLE_TOSHIBA \
+ SET_NAND_SYNC_TYPE(NAND_MFR_TOSHIBA, 0, 0)
+#define NAND_TYPE_TOGGLE_SAMSUNG \
+ SET_NAND_SYNC_TYPE(NAND_MFR_SAMSUNG, 0, 0)
+
+#define NAND_TYPE_TOGGLE_10 SET_NAND_SYNC_TYPE(0, 0, 0x10)
+#define NAND_TYPE_ONFI_30 SET_NAND_SYNC_TYPE(0, NAND_IS_ONFI, 0x30)
+#define NAND_TYPE_ONFI_23 SET_NAND_SYNC_TYPE(0, NAND_IS_ONFI, 0x23)
+
+ int type;
+ int (*enable)(struct nand_chip *chip);
+ int (*disable)(struct nand_chip *chip);
+};
+
+struct read_retry_t {
+ int type;
+ int count;
+ int (*set_rr_param)(struct nfc_host *host, int param);
+ int (*get_rr_param)(struct nfc_host *host);
+ int (*reset_rr_param)(struct nfc_host *host);
+};
+
+struct ecc_info_t {
+ int pagesize;
+ int ecctype;
+ int threshold;
+ int section;
+ void (*dump)(struct nfc_host *host, unsigned char ecc[],
+ int *max_bitsflag);
+};
+
+struct nand_dev_t {
+ struct nand_flash_dev flash_dev;
+
+ char *start_type;
+ unsigned char ids[8];
+ int oobsize;
+ int ecctype;
+
+ /* (Controller) support ecc/page detect, driver don't need detect */
+#define NANDC_HW_AUTO 0x01
+ /* (Controller) support ecc/page detect,
+ * and current ecc/page config finish */
+#define NANDC_CONFIG_DONE 0x02
+ /* (Controller) is sync, default is async */
+#define NANDC_IS_SYNC_BOOT 0x04
+
+ /* (NAND) need randomizer */
+#define NAND_RANDOMIZER 0x10
+ /* (NAND) is ONFI interface, combine with sync/async symble */
+#define NAND_IS_ONFI 0x20
+ /* (NAND) support async and sync, such micron onfi, toshiba toggle 1.0 */
+#define NAND_MODE_SYNC_ASYNC 0x40
+ /* (NAND) support only sync, such samsung sync. */
+#define NAND_MODE_ONLY_SYNC 0x80
+
+#define NAND_CHIP_MICRON (NAND_MODE_SYNC_ASYNC | NAND_IS_ONFI)
+ /* This NAND is async, or sync/async, default is async mode,
+ * toggle1.0 interface */
+#define NAND_CHIP_TOSHIBA_TOGGLE_10 (NAND_MODE_SYNC_ASYNC)
+ /* This NAND is only sync mode, toggle2.0 interface */
+#define NAND_CHIP_TOSHIBA_TOGGLE_20 (NAND_MODE_ONLY_SYNC)
+ /* This NAND is only sync mode */
+#define NAND_CHIP_SAMSUNG (NAND_MODE_ONLY_SYNC)
+
+ unsigned int flags;
+
+#define NAND_RR_NONE 0x00
+#define NAND_RR_HYNIX_BG_BDIE 0x10
+#define NAND_RR_HYNIX_BG_CDIE 0x11
+#define NAND_RR_HYNIX_CG_ADIE 0x12
+#define NAND_RR_MICRON 0x20
+#define NAND_RR_SAMSUNG 0x30
+#define NAND_RR_TOSHIBA_24nm 0x40
+#define NAND_RR_TOSHIBA_19nm 0x41
+ int read_retry_type;
+};
+
+/*****************************************************************************/
+
+#define IS_NANDC_HW_AUTO(_host) ((_host)->flags & NANDC_HW_AUTO)
+#define IS_NANDC_CONFIG_DONE(_host) ((_host)->flags & NANDC_CONFIG_DONE)
+#define IS_NANDC_SYNC_BOOT(_host) ((_host)->flags & NANDC_IS_SYNC_BOOT)
+
+#define IS_NAND_RANDOM(_dev) ((_dev)->flags & NAND_RANDOMIZER)
+#define IS_NAND_ONLY_SYNC(_dev) ((_dev)->flags & NAND_MODE_ONLY_SYNC)
+#define IS_NAND_SYNC_ASYNC(_dev) ((_dev)->flags & NAND_MODE_SYNC_ASYNC)
+#define IS_NAND_ONFI(_dev) ((_dev)->flags & NAND_IS_ONFI)
+
+#define ERSTR_HARDWARE "Hardware configuration error. "
+#define ERSTR_DRIVER "Driver does not support. "
+
+#define ENABLE 1
+#define DISABLE 0
+
+/*****************************************************************************/
+
+char *get_ecctype_str(enum ecc_type ecctype);
+
+char *get_pagesize_str(enum page_type pagetype);
+
+unsigned int get_pagesize(enum page_type pagetype);
+
+const char *nand_ecc_name(int type);
+
+const char *nand_page_name(int type);
+
+int nandpage_size2type(int size);
+
+int nandpage_type2size(int size);
+
+/*****************************************************************************/
+extern int (*nfc_param_adjust)(struct mtd_info *mtd, struct nand_chip *chip,
+ struct nand_dev_t *nand_dev);
+
+extern struct nand_flash_dev *(*nand_get_flash_type_func)(struct mtd_info *mtd,
+ struct nand_chip *chip, struct nand_dev_t *spinand_dev_t);
+
+extern struct nand_flash_dev *(*get_spi_nand_flash_type_hook)
+(struct mtd_info *mtd, unsigned char *id);
+
+extern int (*nfc_param_adjust)(struct mtd_info *,
+ struct nand_chip *, struct nand_dev_t *);
+
+/*****************************************************************************/
+struct nand_flash_dev *nfc_get_flash_type(struct mtd_info *mtd,
+ struct nand_chip *chip, u8 *id_data, int *busw);
+
+extern struct nand_flash_dev *(*get_spi_nand_flash_type_hook)
+(struct mtd_info *mtd, unsigned char *id);
+
+void nfc_nand_param_adjust(struct mtd_info *mtd, struct nand_chip *chip);
+
+void nfc_show_info(struct mtd_info *mtd, char *goke, char *chipname);
+
+void nfc_show_chipsize(struct nand_chip *chip);
+
+int get_bits(unsigned int n);
+
+/*****************************************************************************/
+#define nfc_pr_msg(_fmt, arg...) printk(_fmt, ##arg)
+
+#define nfc_pr_bug(fmt, args...) do { \
+ printk("%s(%d): bug " fmt, __FILE__, __LINE__, ##args); \
+ while (1) \
+ ; \
+} while (0)
+
+#define PR_MSG(_fmt, arg...) \
+ printk(_fmt, ##arg)
+
+extern char *nand_dbgfs_options;
+/*****************************************************************************/
+extern unsigned char match_page_reg_to_type(unsigned char reg);
+
+extern unsigned char match_page_type_to_reg(unsigned char type);
+
+extern const char *match_page_type_to_str(unsigned char type);
+
+/*****************************************************************************/
+extern unsigned char match_ecc_reg_to_type(unsigned char reg);
+
+extern unsigned char match_ecc_type_to_reg(unsigned char type);
+
+extern const char *match_ecc_type_to_str(unsigned char type);
+
+/*****************************************************************************/
+extern unsigned char match_page_size_to_type(unsigned int size);
+
+extern unsigned int match_page_type_to_size(unsigned char type);
+
+const char *nand_ecc_name(int type);
+/*****************************************************************************/
+
+#endif /* End of __NFC_GEN_H__ */
diff -urN linux-4.9.37/drivers/mtd/nand/nfc_spl_ids.c linux-4.9.y/drivers/mtd/nand/nfc_spl_ids.c
--- linux-4.9.37/drivers/mtd/nand/nfc_spl_ids.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/mtd/nand/nfc_spl_ids.c 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,966 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#include <linux/mtd/mtd.h>
+#include <linux/mfd/goke_fmc.h>
+#include "nfc_gen.h"
+
+/*****************************************************************************/
+
+struct nand_flash_special_dev {
+ unsigned char id[8];
+ int length; /* length of id. */
+ unsigned long long chipsize;
+ struct nand_flash_dev *(*probe)(struct nand_dev_t *nand_dev);
+ char *name;
+
+ unsigned long pagesize;
+ unsigned long erasesize;
+ unsigned long oobsize;
+ unsigned long options;
+ unsigned int read_retry_type;
+
+#define BBP_LAST_PAGE 0x01
+#define BBP_FIRST_PAGE 0x02
+ unsigned int badblock_pos;
+ unsigned int flags;
+};
+
+/*****************************************************************************/
+/* this is nand probe function. */
+/*****************************************************************************/
+
+static struct nand_flash_dev *hynix_probe_v02(
+ struct nand_dev_t *nand_dev)
+{
+ unsigned char *id = nand_dev->ids;
+ struct nand_flash_dev *type = &nand_dev->flash_dev;
+
+ int pagesizes[] = {SZ_2K, SZ_4K, SZ_8K, 0};
+ int oobsizes[] = {128, 224, 448, 0, 0, 0, 0, 0};
+ int blocksizes[] = {SZ_128K, SZ_256K, SZ_512K,
+ (SZ_256K + SZ_512K), SZ_1M, SZ_2M, 0, 0
+ };
+
+ int blocktype = (((id[3] >> 5) & 0x04) | ((id[3] >> 4) & 0x03));
+ int oobtype = (((id[3] >> 2) & 0x03) | ((id[3] >> 4) & 0x04));
+
+ type->options = 0;
+ type->pagesize = pagesizes[(id[3] & 0x03)];
+ type->erasesize = blocksizes[blocktype];
+ nand_dev->oobsize = oobsizes[oobtype];
+
+ return type;
+}
+/*****************************************************************************/
+
+static struct nand_flash_dev *samsung_probe_v02(
+ struct nand_dev_t *nand_dev)
+{
+ unsigned char *id = nand_dev->ids;
+ struct nand_flash_dev *type = &nand_dev->flash_dev;
+
+ int pagesizes[] = {SZ_2K, SZ_4K, SZ_8K, 0};
+ int oobsizes[] = {0, 128, 218, 400, 436, 0, 0, 0};
+ int blocksizes[] = {SZ_128K, SZ_256K, SZ_512K, SZ_1M, 0, 0, 0, 0};
+
+ int blocktype = (((id[3] >> 5) & 0x04) | ((id[3] >> 4) & 0x03));
+ int oobtype = (((id[3] >> 4) & 0x04) | ((id[3] >> 2) & 0x03));
+
+ type->options = 0;
+ type->pagesize = pagesizes[(id[3] & 0x03)];
+ type->erasesize = blocksizes[blocktype];
+ nand_dev->oobsize = oobsizes[oobtype];
+
+ return type;
+}
+/*****************************************************************************/
+
+#define DRV_VERSION "1.38"
+
+/*****************************************************************************/
+/*
+ * samsung: 27nm need randomizer, 21nm need read retry;
+ * micron: 25nm need read retry, datasheet will explain read retry.
+ * toshaba 32nm need randomizer, 24nm need read retry.
+ * hynix: 2xnm need read retry.
+ *
+ * The special nand flash ID table version 1.37
+ *
+ * manufactory | type | name | ecc_type | version_tag
+ * Micron | MLC | MT29F64G08CBABA | 40bit/1k | 1.36
+ * Micron | MLC | MT29F32G08CBADA | 40bit/1k |
+ * Micron | SLC | MT29F8G08ABxBA | 4bit/512 |
+ * Micron | MLC | MT29F16G08CBABx | 12bit/512 |
+ * Micron | MLC | MT29F16G08CBACA | 24bit/1k |
+ * Micron | MLC | MT29F32G08CBACA | 24bit/1k |
+ * Micron | MLC | MT29F64G08CxxAA | 24bit/1k |
+ * Micron | MLC | MT29F256G08CJAAA | 24bit/1k | 2CE
+ * Micron | MLC | MT29F256G08CMCBB | 24bit/1k |
+ * Micron | SLC | MT29F8G08ABACA | 8bit/512 |
+ * Micron | SLC | MT29F4G08ABAEA | 8bit/512 |
+ * Micron | SLC | MT29F2G08ABAFA | 8bit/512 |
+ * Micron | SLC | MT29F16G08ABACA | 8bit/512 |
+ * Toshiba | MLC | TC58NVG4D2FTA00 | 24bit/1k |
+ * Toshiba | MLC | TH58NVG6D2FTA20 | 24bit/1k | 2CE
+ * Toshiba | MLC | TC58NVG5D2HTA00 | 40bit/1k |
+ * Toshiba | MLC | TC58NVG6D2GTA00 | 40bit/1k |
+ * Toshiba | MLC | TC58NVG6DCJTA00 | |
+ * Toshiba | MLC | TC58TEG5DCJTA00 | |
+ * Toshiba | SLC | TC58NVG0S3HTA00 | 8bit/512 |
+ * Toshiba | SLC | TC58NVG1S3HTA00 | 8bit/512 |
+ * Toshiba | SLC | TC58NVG1S3ETA00 | 4bit/512 |
+ * Toshiba | SLC | TC58NVG3S0FTA00 | 4bit/512 |
+ * Toshiba | SLC | TC58NVG2S0FTA00 | 4bit/512 |
+ * Toshiba | SLC | TH58NVG2S3HTA00 | 4bit/512 |
+ * Toshiba | TLC | TC58NVG5T2JTA00 | 60bit/1k |
+ * Toshiba | TLC | TC58TEG5DCKTAx0 | 60bit/1k |
+ * Toshiba | MLC | Tx58TEGxDDKTAx0 | |
+ * Samsung | MLC | K9LB(HC/PD/MD)G08U0(1)D | 8bit/512B |
+ * Samsung | MLC | K9GAG08U0E | 24bit/1KB |
+ * Samsung | MLC | K9LBG08U0E | 24bit/1KB |
+ * Samsung | MLC | K9G8G08U0C | 24bit/1KB |
+ * Samsung | MLC | K9GAG08U0F | 24bit/1KB |
+ * Samsung | MLC | K9LBG08U0M | |
+ * Samsung | MLC | K9GBG08U0A | 24bit/1KB |
+ * Samsung | MLC | K9GBG08U0B | 40bit/1KB |
+ * Hynix | MLC | H27UAG8T2A | |
+ * Hynix | MLC | H27UAG8T2B | |
+ * Hynix | MLC | H27UBG8T2A | |
+ * Hynix | MLC | H27UBG8T2BTR | 24bit/1KB |
+ * Hynix | MLC | H27UCG8T2A | 40bit/1KB |
+ * Hynix | MLC | H27UBG8T2C | 40bit/1KB |
+ * MISC | MLC | P1UAGA30AT-GCA | 8bit/512 |
+ * MISC | MLC | PSU8GA30AT-GIA/ASU8GA30IT-G30CA | 4bit/512 |
+ * MISC | SLC | PSU2GA30AT | 1bit/512 | 1.36
+ * Toshiba | SLC | TC58NVG2S0HTA00 | 24bit/1K | 1.37
+ * Toshiba | SLC | TC58NVG3S0HTA00 | 24bit/1K | 1.37
+ * Micron | SLC | MT29F2G08ABAEA | 4bit/512 |
+ * Spansion | SLC | S34ML02G200TFI000 | 24bit/1K |
+ * Spansion | SLC | S34ML04G200TFI000 | 24bit/1K | 1.38
+ *
+ */
+
+static struct nand_flash_special_dev nand_flash_special_dev[] = {
+
+ /****************************** Spansion *******************************/
+
+ { /* SLC S34ML02G200TFI000 */
+ .name = "S34ML02G200TFI000",
+ .id = {0x01, 0xDA, 0x90, 0x95, 0x46, 0x00, 0x00, 0x00},
+ .length = 5,
+ .chipsize = _256M,
+ .probe = NULL,
+ .pagesize = SZ_2K,
+ .erasesize = SZ_128K,
+ .oobsize = 128,
+ .options = 0,
+ .read_retry_type = NAND_RR_NONE,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .flags = 0,
+ },
+
+ { /* SLC S34ML04G200TFI000 */
+ .name = "S34ML04G200TFI000",
+ .id = {0x01, 0xDC, 0x90, 0x95, 0x56, 0x00, 0x00, 0x00},
+ .length = 5,
+ .chipsize = _512M,
+ .probe = NULL,
+ .pagesize = SZ_2K,
+ .erasesize = SZ_128K,
+ .oobsize = 128,
+ .options = 0,
+ .read_retry_type = NAND_RR_NONE,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .flags = 0,
+ },
+
+ /****************************** Micron *******************************/
+ { /* MLC 40bit/1k */
+ .name = "MT29F64G08CBABA",
+ .id = {0x2C, 0x64, 0x44, 0x4B, 0xA9, 0x00, 0x00, 0x00},
+ .length = 8,
+ .chipsize = _8G,
+ .probe = NULL,
+ .pagesize = SZ_8K,
+ .erasesize = SZ_2M,
+ .oobsize = 744,
+ .options = 0,
+ .read_retry_type = NAND_RR_MICRON,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .flags = NAND_RANDOMIZER | NAND_CHIP_MICRON,
+ },
+ { /* MLC 40bit/1k */
+ .name = "MT29F32G08CBADA",
+ .id = {0x2C, 0x44, 0x44, 0x4B, 0xA9, 0x00, 0x00, 0x00},
+ .length = 8,
+ .chipsize = _4G,
+ .probe = NULL,
+ .pagesize = SZ_8K,
+ .erasesize = SZ_2M,
+ .oobsize = 744,
+ .options = 0,
+ .read_retry_type = NAND_RR_MICRON,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .flags = NAND_RANDOMIZER,
+ },
+ { /* SLC 4bit/512 */
+ .name = "MT29F8G08ABxBA",
+ .id = {0x2C, 0x38, 0x00, 0x26, 0x85, 0x00, 0x00, 0x00},
+ .length = 8,
+ .chipsize = SZ_1G,
+ .probe = NULL,
+ .pagesize = SZ_4K,
+ .erasesize = SZ_512K,
+ .oobsize = 224,
+ .options = 0,
+ .read_retry_type = NAND_RR_NONE,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .flags = 0,
+ },
+ { /* MLC 12bit/512 */
+ .name = "MT29F16G08CBABx",
+ .id = {0x2C, 0x48, 0x04, 0x46, 0x85, 0x00, 0x00, 0x00},
+ .length = 8,
+ .chipsize = SZ_2G,
+ .probe = NULL,
+ .pagesize = SZ_4K,
+ .erasesize = SZ_1M,
+ .oobsize = 224,
+ .options = 0,
+ .read_retry_type = NAND_RR_NONE,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .flags = 0,
+ },
+ { /* MLC 24bit/1k */
+ .name = "MT29F16G08CBACA",
+ .id = {0x2C, 0x48, 0x04, 0x4A, 0xA5, 0x00, 0x00, 0x00},
+ .length = 8,
+ .chipsize = SZ_2G,
+ .probe = NULL,
+ .pagesize = SZ_4K,
+ .erasesize = SZ_1M,
+ .oobsize = 224,
+ .options = 0,
+ .read_retry_type = NAND_RR_NONE,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .flags = 0,
+ },
+ { /* MLC 24bit/1k */
+ .name = "MT29F32G08CBACA",
+ .id = {0x2C, 0x68, 0x04, 0x4A, 0xA9, 0x00, 0x00, 0x00},
+ .length = 8,
+ .chipsize = _4G,
+ .probe = NULL,
+ .pagesize = SZ_4K,
+ .erasesize = SZ_1M,
+ .oobsize = 224,
+ .options = 0,
+ .read_retry_type = NAND_RR_NONE,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .flags = 0,
+ },
+ { /* MLC 24bit/1k */
+ .name = "MT29F64G08CxxAA",
+ .id = {0x2C, 0x88, 0x04, 0x4B, 0xA9, 0x00, 0x00, 0x00},
+ .length = 8,
+ .chipsize = _8G,
+ .probe = NULL,
+ .pagesize = SZ_8K,
+ .erasesize = SZ_2M,
+ .oobsize = 448,
+ .options = 0,
+ .read_retry_type = NAND_RR_NONE,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .flags = 0,
+ },
+ { /* MLC 24bit/1k 2CE */
+ .name = "MT29F256G08CJAAA",
+ .id = {0x2C, 0xA8, 0x05, 0xCB, 0xA9, 0x00, 0x00, 0x00},
+ .length = 8,
+ .chipsize = _16G,
+ .probe = NULL,
+ .pagesize = SZ_8K,
+ .erasesize = SZ_2M,
+ .oobsize = 448,
+ .options = 0,
+ .read_retry_type = NAND_RR_NONE,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .flags = 0,
+ },
+ { /* MLC 40bit/1k */
+ .name = "MT29F256G08CMCBB",
+ .id = {0x2C, 0x64, 0x44, 0x4B, 0xA9, 0x00, 0x00, 0x00},
+ .length = 8,
+ .chipsize = _8G,
+ .probe = NULL,
+ .pagesize = SZ_8K,
+ .erasesize = SZ_2M,
+ .oobsize = 744,
+ .options = 0,
+ .read_retry_type = NAND_RR_NONE,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .flags = 0,
+ },
+ { /* SLC 8bit/512 */
+ .name = "MT29F8G08ABACA",
+ .id = {0x2C, 0xD3, 0x90, 0xA6, 0x64, 0x00, 0x00, 0x00},
+ .length = 5,
+ .chipsize = SZ_1G,
+ .probe = NULL,
+ .pagesize = SZ_4K,
+ .erasesize = SZ_256K,
+ .oobsize = 224,
+ .options = 0,
+ .read_retry_type = NAND_RR_NONE,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .flags = 0,
+ },
+ { /* SLC 8bit/512 */
+ .name = "MT29F4G08ABAEA",
+ .id = {0x2C, 0xDC, 0x90, 0xA6, 0x54, 0x00, 0x00, 0x00},
+ .length = 5,
+ .chipsize = SZ_512M,
+ .probe = NULL,
+ .pagesize = SZ_4K,
+ .erasesize = SZ_256K,
+ .oobsize = 224,
+ .options = 0,
+ .read_retry_type = NAND_RR_NONE,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .flags = 0,
+ },
+ { /* SLC 8bit/512 */
+ .name = "MT29F2G08ABAFA",
+ .id = {0x2C, 0xDA, 0x90, 0x95, 0x04, 0x00, 0x00, 0x00},
+ .length = 5,
+ .chipsize = SZ_256M,
+ .probe = NULL,
+ .pagesize = SZ_2K,
+ .erasesize = SZ_128K,
+ .oobsize = 224,
+ .options = 0,
+ .read_retry_type = NAND_RR_NONE,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .flags = 0,
+ },
+ { /* SLC MT29F2G08ABAEA */
+ .name = "MT29F2G08ABAEA",
+ .id = {0x2C, 0xDA, 0x90, 0x95, 0x06, 0x00, 0x00, 0x00},
+ .length = 5,
+ .chipsize = _256M,
+ .probe = NULL,
+ .pagesize = SZ_2K,
+ .erasesize = SZ_128K,
+ .oobsize = 64,
+ .options = 0,
+ .read_retry_type = NAND_RR_NONE,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .flags = 0,
+ },
+ { /* SLC 8bit/512 */
+ .name = "MT29F16G08ABACA",
+ .id = {0x2C, 0x48, 0x00, 0x26, 0xA9, 0x00, 0x00, 0x00},
+ .length = 5,
+ .chipsize = SZ_2G,
+ .probe = NULL,
+ .pagesize = SZ_4K,
+ .erasesize = SZ_512K,
+ .oobsize = 224,
+ .options = 0,
+ .read_retry_type = NAND_RR_NONE,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .flags = 0,
+ },
+
+ /****************************** Toshaba *******************************/
+
+ { /* MLC 24bit/1k 32nm */
+ .name = "TC58NVG4D2FTA00",
+ .id = {0x98, 0xD5, 0x94, 0x32, 0x76, 0x55, 0x00, 0x00},
+ .length = 6,
+ .chipsize = SZ_2G,
+ .probe = NULL,
+ .pagesize = SZ_8K,
+ .erasesize = SZ_1M,
+ .oobsize = 448,
+ .options = 0,
+ .read_retry_type = NAND_RR_NONE,
+ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE,
+ .flags = 0,
+ },
+ { /* MLC 24bit/1k 32nm 2CE*/
+ .name = "TH58NVG6D2FTA20",
+ .id = {0x98, 0xD7, 0x94, 0x32, 0x76, 0x55, 0x00, 0x00},
+ .length = 6,
+ .chipsize = _4G,
+ .probe = NULL,
+ .pagesize = SZ_8K,
+ .erasesize = SZ_1M,
+ .oobsize = 448,
+ .options = 0,
+ .read_retry_type = NAND_RR_NONE,
+ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE,
+ .flags = 0,
+ },
+ { /* MLC 40bit/1k 24nm */
+ .name = "TC58NVG5D2HTA00 24nm",
+ .id = {0x98, 0xD7, 0x94, 0x32, 0x76, 0x56, 0x08, 0x00},
+ .length = 6,
+ .chipsize = _4G,
+ .probe = NULL,
+ .pagesize = SZ_8K,
+ .erasesize = SZ_1M,
+ .oobsize = 640,
+ .options = 0,
+ .read_retry_type = NAND_RR_TOSHIBA_24nm,
+ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE,
+ .flags = NAND_RANDOMIZER,
+ },
+ { /* MLC 40bit/1k */
+ .name = "TC58NVG6D2GTA00",
+ .id = {0x98, 0xDE, 0x94, 0x82, 0x76, 0x00, 0x00, 0x00},
+ .length = 5,
+ .chipsize = _8G,
+ .probe = NULL,
+ .pagesize = SZ_8K,
+ .erasesize = SZ_2M,
+ .oobsize = 640,
+ .options = 0,
+ .read_retry_type = NAND_RR_NONE,
+ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE,
+ .flags = 0,
+ },
+ { /* MLC 19nm */
+ .name = "TC58NVG6DCJTA00 19nm",
+ .id = {0x98, 0xDE, 0x84, 0x93, 0x72, 0x57, 0x08, 0x04},
+ .length = 8,
+ .chipsize = _8G,
+ .probe = NULL,
+ .pagesize = SZ_16K,
+ .erasesize = SZ_4M,
+ .oobsize = 1280,
+ .options = 0,
+ .read_retry_type = NAND_RR_TOSHIBA_24nm,
+ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE,
+ .flags = NAND_RANDOMIZER,
+ },
+ { /* MLC 19nm */
+ .name = "TC58TEG5DCJTA00 19nm",
+ .id = {0x98, 0xD7, 0x84, 0x93, 0x72, 0x57, 0x08, 0x04},
+ .length = 6,
+ .chipsize = _4G,
+ .probe = NULL,
+ .pagesize = SZ_16K,
+ .erasesize = SZ_4M,
+ .oobsize = 1280,
+ .options = 0,
+ .read_retry_type = NAND_RR_TOSHIBA_24nm,
+ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE,
+ .flags = NAND_RANDOMIZER | NAND_CHIP_TOSHIBA_TOGGLE_10,
+ },
+ { /* SLC 8bit/512 */
+ .name = "TC58NVG0S3HTA00",
+ .id = {0x98, 0xF1, 0x80, 0x15, 0x72, 0x00, 0x00, 0x00},
+ .length = 5,
+ .chipsize = SZ_128M,
+ .probe = NULL,
+ .pagesize = SZ_2K,
+ .erasesize = SZ_128K,
+ .oobsize = 128,
+ .options = 0,
+ .read_retry_type = NAND_RR_NONE,
+ /*
+ * Datasheet: read one column of any page in each block. If the
+ * data of the column is 00 (Hex), define the block as a bad
+ * block.
+ */
+ .badblock_pos = BBP_FIRST_PAGE,
+ .flags = 0,
+ },
+ { /* SLC 8bit/512 */
+ .name = "TC58NVG1S3HTA00",
+ .id = {0x98, 0xDA, 0x90, 0x15, 0x76, 0x16, 0x08, 0x00},
+ .length = 7,
+ .chipsize = SZ_256M,
+ .probe = NULL,
+ .pagesize = SZ_2K,
+ .erasesize = SZ_128K,
+ .oobsize = 128,
+ .options = 0,
+ .read_retry_type = NAND_RR_NONE,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .flags = 0,
+ },
+ { /* SLC 4bit/512 */
+ .name = "TC58NVG1S3ETA00",
+ .id = {0x98, 0xDA, 0x90, 0x15, 0x76, 0x14, 0x03, 0x00},
+ .length = 7,
+ .chipsize = SZ_256M,
+ .probe = NULL,
+ .pagesize = SZ_2K,
+ .erasesize = SZ_128K,
+ .oobsize = 64,
+ .options = 0,
+ .read_retry_type = NAND_RR_NONE,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .flags = 0,
+ },
+ { /* SLC 4bit/512 */
+ .name = "TC58NVG3S0FTA00",
+ .id = {0x98, 0xD3, 0x90, 0x26, 0x76, 0x15, 0x02, 0x08},
+ .length = 8,
+ .chipsize = SZ_1G,
+ .probe = NULL,
+ .pagesize = SZ_4K,
+ .erasesize = SZ_256K,
+ .oobsize = 232,
+ .options = 0,
+ .read_retry_type = NAND_RR_NONE,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .flags = 0,
+ },
+ { /* SLC 4bit/512 */
+ .name = "TC58NVG3S0HTA00",
+ .id = {0x98, 0xD3, 0x91, 0x26, 0x76, 0x16, 0x08, 0x00},
+ .length = 8,
+ .chipsize = SZ_1G,
+ .probe = NULL,
+ .pagesize = SZ_4K,
+ .erasesize = SZ_256K,
+ .oobsize = 256,
+ .options = 0,
+ .read_retry_type = NAND_RR_NONE,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .flags = 0,
+ },
+ { /* SLC 24bit/1k */
+ .name = "TC58NVG2S0HTA00",
+ .id = {0x98, 0xDC, 0x90, 0x26, 0x76, 0x16, 0x08, 0x00},
+ .length = 8,
+ .chipsize = SZ_512M,
+ .probe = NULL,
+ .pagesize = SZ_4K,
+ .erasesize = SZ_256K,
+ .oobsize = 256,
+ .options = 0,
+ .read_retry_type = NAND_RR_NONE,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .flags = 0,
+ },
+ { /* SLC 4bit/512 */
+ .name = "TC58NVG2S0FTA00",
+ .id = {0x98, 0xDC, 0x90, 0x26, 0x76, 0x15, 0x01, 0x08},
+ .length = 8,
+ .chipsize = SZ_512M,
+ .probe = NULL,
+ .pagesize = SZ_4K,
+ .erasesize = SZ_256K,
+ .oobsize = 224,
+ .options = 0,
+ .read_retry_type = NAND_RR_NONE,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .flags = 0,
+ },
+ { /* SLC 4bit/512 */
+ .name = "TH58NVG2S3HTA00",
+ .id = {0x98, 0xDC, 0x91, 0x15, 0x76},
+ .length = 5,
+ .chipsize = SZ_512M,
+ .probe = NULL,
+ .pagesize = SZ_2K,
+ .erasesize = SZ_128K,
+ .oobsize = 128,
+ .options = 0,
+ .read_retry_type = NAND_RR_NONE,
+ .badblock_pos = BBP_FIRST_PAGE,
+ .flags = 0,
+ },
+ { /* TLC 60bit/1k 19nm */
+ .name = "TC58NVG5T2JTA00 19nm TLC",
+ .id = {0x98, 0xD7, 0x98, 0x92, 0x72, 0x57, 0x08, 0x10},
+ .length = 6,
+ .chipsize = _4G,
+ .probe = NULL,
+ .pagesize = SZ_8K,
+ .erasesize = SZ_4M,
+ .oobsize = 1024,
+ .options = 0,
+ .read_retry_type = NAND_RR_TOSHIBA_24nm,
+ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE,
+ .flags = NAND_RANDOMIZER,
+ },
+ { /* TLC 60bit/1k 19nm */
+ .name = "TC58TEG5DCKTAx0 19nm MLC",
+ /* datasheet says 6 ids id data, but really has 8 ids. */
+ .id = {0x98, 0xD7, 0x84, 0x93, 0x72, 0x50, 0x08, 0x04},
+ .length = 6,
+ .chipsize = _4G,
+ .probe = NULL,
+ .pagesize = SZ_16K,
+ .erasesize = SZ_4M,
+ .oobsize = 1280,
+ .options = 0,
+ .read_retry_type = NAND_RR_TOSHIBA_19nm,
+ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE,
+ .flags = NAND_RANDOMIZER,
+ },
+ {
+ .name = "Tx58TEGxDDKTAx0 19nm MLC",
+ .id = {0x98, 0xDE, 0x94, 0x93, 0x76, 0x50},
+ .length = 6,
+ .chipsize = _4G,
+ .probe = NULL,
+ .pagesize = SZ_16K,
+ .erasesize = SZ_4M,
+ .oobsize = 1280,
+ .options = 0,
+ .read_retry_type = NAND_RR_TOSHIBA_19nm,
+ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE,
+ .flags = NAND_RANDOMIZER,
+ },
+ /******************************* Samsung ******************************/
+ { /* MLC 8bit/512B */
+ .name = "K9LB(HC/PD/MD)G08U0(1)D",
+ .id = {0xEC, 0xD7, 0xD5, 0x29, 0x38, 0x41, 0x00, 0x00},
+ .length = 6,
+ .chipsize = _4G,
+ .probe = samsung_probe_v02,
+ .read_retry_type = NAND_RR_NONE,
+ .badblock_pos = BBP_LAST_PAGE,
+ .flags = 0,
+ },
+ { /* MLC 24bit/1KB */
+ .name = "K9GAG08U0E",
+ .id = {0xEC, 0xD5, 0x84, 0x72, 0x50, 0x42, 0x00, 0x00},
+ .length = 6,
+ .chipsize = SZ_2G,
+ .probe = samsung_probe_v02,
+ .read_retry_type = NAND_RR_NONE,
+ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE,
+ .flags = 0,
+ },
+ { /* MLC 24bit/1KB */
+ .name = "K9LBG08U0E",
+ .id = {0xEC, 0xD7, 0xC5, 0x72, 0x54, 0x42, 0x00, 0x00},
+ .length = 6,
+ .chipsize = _4G,
+ .probe = samsung_probe_v02,
+ .read_retry_type = NAND_RR_NONE,
+ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE,
+ .flags = 0,
+ },
+ { /* MLC 24bit/1KB */
+ .name = "K9G8G08U0C",
+ .id = {0xEC, 0xD3, 0x84, 0x72, 0x50, 0x42, 0x00, 0x00},
+ .length = 6,
+ .chipsize = SZ_1G,
+ .probe = samsung_probe_v02,
+ .read_retry_type = NAND_RR_NONE,
+ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE,
+ .flags = 0,
+ },
+ { /* MLC 24bit/1k */
+ .name = "K9GAG08U0F",
+ .id = {0xEC, 0xD5, 0x94, 0x76, 0x54, 0x43, 0x00, 0x00},
+ .length = 6,
+ .chipsize = SZ_2G,
+ .probe = NULL,
+ .pagesize = SZ_8K,
+ .erasesize = SZ_1M,
+ .oobsize = 512,
+ .options = 0,
+ .read_retry_type = NAND_RR_NONE,
+ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE,
+ .flags = 0,
+ },
+ { /* MLC */
+ .name = "K9LBG08U0M",
+ .id = {0xEC, 0xD7, 0x55, 0xB6, 0x78, 0x00, 0x00, 0x00},
+ .length = 5,
+ .chipsize = _4G,
+ .probe = NULL,
+ .pagesize = SZ_4K,
+ .erasesize = SZ_512K,
+ .oobsize = 128,
+ .options = 0,
+ .read_retry_type = NAND_RR_NONE,
+ .badblock_pos = BBP_LAST_PAGE,
+ .flags = 0,
+ },
+ { /* MLC 24bit/1k */
+ .name = "K9GBG08U0A 20nm",
+ .id = {0xEC, 0xD7, 0x94, 0x7A, 0x54, 0x43, 0x00, 0x00},
+ .length = 6,
+ .chipsize = _4G,
+ .probe = NULL,
+ .pagesize = SZ_8K,
+ .erasesize = SZ_1M,
+ .oobsize = 640,
+ .options = 0,
+ .read_retry_type = NAND_RR_SAMSUNG,
+ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE,
+ .flags = NAND_RANDOMIZER,
+ },
+ { /* MLC 40bit/1k */
+ .name = "K9GBG08U0B",
+ .id = {0xEC, 0xD7, 0x94, 0x7E, 0x64, 0x44, 0x00, 0x00},
+ .length = 6,
+ .chipsize = _4G,
+ .probe = NULL,
+ .pagesize = SZ_8K,
+ .erasesize = SZ_1M,
+ .oobsize = 1024,
+ .options = 0,
+ .read_retry_type = NAND_RR_SAMSUNG,
+ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE,
+ .flags = NAND_RANDOMIZER,
+ },
+
+ /*********************************** Hynix ****************************/
+ { /* MLC */
+ .name = "H27UAG8T2A",
+ .id = {0xAD, 0xD5, 0x94, 0x25, 0x44, 0x41, },
+ .length = 6,
+ .chipsize = SZ_2G,
+ .probe = hynix_probe_v02,
+ .read_retry_type = NAND_RR_NONE,
+ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE,
+ .flags = 0,
+ },
+ { /* MLC */
+ .name = "H27UAG8T2B",
+ .id = {0xAD, 0xD5, 0x94, 0x9A, 0x74, 0x42, },
+ .length = 6,
+ .chipsize = SZ_2G,
+ .probe = hynix_probe_v02,
+ .read_retry_type = NAND_RR_NONE,
+ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE,
+ .flags = 0,
+ },
+ { /* MLC */
+ .name = "H27UBG8T2A",
+ .id = {0xAD, 0xD7, 0x94, 0x9A, 0x74, 0x42, },
+ .length = 6,
+ .chipsize = _4G,
+ .probe = hynix_probe_v02,
+ .read_retry_type = NAND_RR_NONE,
+ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE,
+ .flags = 0,
+ },
+ { /* MLC 24bit/1K, 26nm TODO: Need read retry, chip is EOS */
+ .name = "H27UBG8T2BTR 26nm",
+ .id = {0xAD, 0xD7, 0x94, 0xDA, 0x74, 0xC3, },
+ .length = 6,
+ .chipsize = _4G,
+ .probe = NULL,
+ .pagesize = SZ_8K,
+ .erasesize = SZ_2M,
+ .oobsize = 640,
+ .options = 0,
+ .read_retry_type = NAND_RR_HYNIX_BG_BDIE,
+ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE,
+ .flags = NAND_RANDOMIZER,
+ },
+ { /* MLC 40bit/1k */
+ .name = "H27UCG8T2A",
+ .id = {0xAD, 0xDE, 0x94, 0xDA, 0x74, 0xC4, },
+ .length = 6,
+ .chipsize = _8G,
+ .probe = NULL,
+ .pagesize = SZ_8K,
+ .erasesize = SZ_2M,
+ .oobsize = 640,
+ .options = 0,
+ .read_retry_type = NAND_RR_HYNIX_CG_ADIE,
+ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE,
+ .flags = NAND_RANDOMIZER,
+ },
+ { /* MLC 40bit/1k */
+ .name = "H27UBG8T2C",
+ .id = {0xAD, 0xD7, 0x94, 0x91, 0x60, 0x44, },
+ .length = 6,
+ .chipsize = _4G,
+ .probe = NULL,
+ .pagesize = SZ_8K,
+ .erasesize = SZ_2M,
+ .oobsize = 640,
+ .options = 0,
+ .read_retry_type = NAND_RR_HYNIX_BG_CDIE,
+ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE,
+ .flags = NAND_RANDOMIZER,
+ },
+
+ /********************** MISC ******************************************/
+ { /* MLC 8bit/512 */
+ .name = "P1UAGA30AT-GCA",
+ .id = {0xC8, 0xD5, 0x14, 0x29, 0x34, 0x01, },
+ .length = 6,
+ .chipsize = SZ_2G,
+ .probe = NULL,
+ .pagesize = SZ_4K,
+ .erasesize = SZ_512K,
+ .oobsize = 218,
+ .options = 0,
+ .read_retry_type = NAND_RR_NONE,
+ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE,
+ .flags = 0,
+ },
+ { /* MLC 4bit/512 */
+ /*
+ * PowerFlash ASU8GA30IT-G30CA ID and MIRA PSU8GA30AT-GIA ID are
+ * the same ID
+ */
+ .name = "PSU8GA30AT-GIA/ASU8GA30IT-G30CA",
+ .id = {0xC8, 0xD3, 0x90, 0x19, 0x34, 0x01, },
+ .length = 6,
+ .chipsize = SZ_1G,
+ .probe = NULL,
+ .pagesize = SZ_4K,
+ .erasesize = SZ_256K,
+ .oobsize = 218,
+ .options = 0,
+ .read_retry_type = NAND_RR_NONE,
+ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE,
+ .flags = 0,
+ },
+ { /* SLC 1bit/512 */
+ .name = "PSU2GA30AT",
+ .id = {0x7F, 0x7F, 0x7F, 0x7F, 0xC8, 0xDA, 0x00, 0x15, },
+ .length = 8,
+ .chipsize = SZ_256M,
+ .probe = NULL,
+ .pagesize = SZ_2K,
+ .erasesize = SZ_128K,
+ .oobsize = 64,
+ .options = 0,
+ .read_retry_type = NAND_RR_NONE,
+ .badblock_pos = BBP_FIRST_PAGE | BBP_LAST_PAGE,
+ .flags = 0,
+ },
+ {{0}, 0, 0, 0, 0, 0, 0, 0, 0},
+};
+
+#define NUM_OF_SPECIAL_DEVICE \
+ (sizeof(nand_flash_special_dev)/sizeof(struct nand_flash_special_dev))
+
+int (*nfc_param_adjust)(struct mtd_info *, struct nand_chip *,
+ struct nand_dev_t *) = NULL;
+
+static struct nand_dev_t __nand_dev;
+/*****************************************************************************/
+
+static struct nand_flash_dev *nfc_nand_probe(struct mtd_info *mtd,
+ struct nand_chip *chip,
+ struct nand_dev_t *nand_dev)
+{
+ struct nand_flash_special_dev *spl_dev = NULL;
+ unsigned char *byte = nand_dev->ids;
+ struct nand_flash_dev *type = &nand_dev->flash_dev;
+
+ nfc_pr_msg("Nand ID: 0x%02X 0x%02X 0x%02X 0x%02X",
+ byte[0], byte[1], byte[2], byte[3]);
+ nfc_pr_msg(" 0x%02X 0x%02X 0x%02X 0x%02X\n",
+ byte[4], byte[5], byte[6], byte[7]);
+
+ for (spl_dev = nand_flash_special_dev; spl_dev->length; spl_dev++) {
+ if (memcmp(byte, spl_dev->id, spl_dev->length))
+ continue;
+
+ nfc_pr_msg("The Special NAND id table Version: %s\n", DRV_VERSION);
+
+ if (spl_dev->probe) {
+ type = spl_dev->probe(nand_dev);
+ } else {
+ type->options = spl_dev->options;
+ type->pagesize = spl_dev->pagesize;
+ type->erasesize = spl_dev->erasesize;
+ nand_dev->oobsize = spl_dev->oobsize;
+ }
+
+ nand_dev->read_retry_type = spl_dev->read_retry_type;
+ nand_dev->flags = spl_dev->flags;
+
+ type->id[1] = byte[1];
+ type->chipsize = (unsigned long)(spl_dev->chipsize >> 20);
+ type->name = spl_dev->name;
+ return type;
+ }
+ nand_dev->read_retry_type = NAND_RR_NONE;
+
+ return NULL;
+}
+/*****************************************************************************/
+
+struct nand_flash_dev *nfc_get_flash_type(struct mtd_info *mtd,
+ struct nand_chip *chip,
+ u8 *id_data, int *busw)
+{
+ struct nand_flash_dev *type = NULL;
+ struct nand_dev_t *nand_dev = &__nand_dev;
+
+ memset(nand_dev, 0, sizeof(struct nand_dev_t));
+ memcpy(nand_dev->ids, id_data, 8);
+
+ if (!nfc_nand_probe(mtd, chip, nand_dev))
+ return NULL;
+
+ type = &nand_dev->flash_dev;
+
+ if (!mtd->name)
+ mtd->name = type->name;
+
+ chip->chipsize = (uint64_t)type->chipsize << 20;
+ mtd->erasesize = type->erasesize;
+ mtd->writesize = type->pagesize;
+ mtd->oobsize = nand_dev->oobsize;
+ *busw = (type->options & NAND_BUSWIDTH_16);
+
+ return type;
+}
+/*****************************************************************************/
+
+void nfc_nand_param_adjust(struct mtd_info *mtd, struct nand_chip *chip)
+{
+ struct nand_dev_t *nand_dev = &__nand_dev;
+
+ if (!nand_dev->oobsize)
+ nand_dev->oobsize = mtd->oobsize;
+
+ if (nfc_param_adjust)
+ nfc_param_adjust(mtd, chip, nand_dev);
+}
+/*****************************************************************************/
+
+void nfc_show_info(struct mtd_info *mtd, char *goke, char *chipname)
+{
+ /* char buf[20]; */
+ struct nand_dev_t *nand_dev = &__nand_dev;
+
+ /* nfc_pr_msg("Nand: %s %s ", goke, chipname); */
+
+ if (IS_NAND_RANDOM(nand_dev))
+ nfc_pr_msg("Randomizer \n");
+
+ if (nand_dev->read_retry_type != NAND_RR_NONE)
+ nfc_pr_msg("Read-Retry \n");
+
+ if (nand_dev->start_type)
+ nfc_pr_msg("Nand(%s): ", nand_dev->start_type);
+ else
+ nfc_pr_msg("Nand: ");
+
+ nfc_pr_msg("OOB:%dB ", nand_dev->oobsize);
+ nfc_pr_msg("ECC:%s ", nand_ecc_name(nand_dev->ecctype));
+}
+/*****************************************************************************/
+
+void nfc_show_chipsize(struct nand_chip *chip)
+{
+ /*char buf[20];*/
+
+ /*nfc_pr_msg("Chip:%sB*%d\n",
+ ultohstr(chip->chipsize, buf, sizeof(buf)),
+ chip->numchips);*/
+}
diff -urN linux-4.9.37/drivers/mtd/spi-nor/goke-sfc.c linux-4.9.y/drivers/mtd/spi-nor/goke-sfc.c
--- linux-4.9.37/drivers/mtd/spi-nor/goke-sfc.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/mtd/spi-nor/goke-sfc.c 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,592 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/mfd/goke_fmc.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/spi-nor.h>
+#include <linux/mtd/partitions.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "../mtdcore.h"
+
+#define FMC_OP_DMA 0x68
+
+struct fmc_priv {
+ u32 chipselect;
+ u32 clkrate;
+ struct fmc_host *host;
+};
+
+struct fmc_host {
+ struct device *dev;
+ struct mutex *lock;
+
+ void __iomem *regbase;
+ void __iomem *iobase;
+ struct clk *clk;
+ void *buffer;
+ dma_addr_t dma_buffer;
+
+ struct spi_nor *nor[FMC_MAX_CHIP_NUM];
+ struct fmc_priv priv[FMC_MAX_CHIP_NUM];
+ u32 num_chip;
+ unsigned int dma_len;
+};
+
+/******************************************************************************/
+static inline int wait_op_finish(struct fmc_host *host)
+{
+ u32 reg;
+
+ return readl_poll_timeout(host->regbase + FMC_INT, reg,
+ (reg & FMC_INT_OP_DONE), 0, FMC_WAIT_TIMEOUT);
+}
+
+static int get_if_type(enum spi_nor_protocol mode)
+{
+ enum fmc_iftype if_type;
+
+ switch (mode) {
+ case SNOR_PROTO_1_1_2:
+ if_type = IF_TYPE_DUAL;
+ break;
+ case SNOR_PROTO_1_2_2:
+ if_type = IF_TYPE_DIO;
+ break;
+ case SNOR_PROTO_1_1_4:
+ if_type = IF_TYPE_QUAD;
+ break;
+ case SNOR_PROTO_1_4_4:
+ if_type = IF_TYPE_QIO;
+ break;
+ case SNOR_PROTO_1_1_1:
+ default:
+ if_type = IF_TYPE_STD;
+ break;
+ }
+
+ return if_type;
+}
+
+/******************************************************************************/
+static void spi_nor_switch_spi_type(struct fmc_host *host)
+{
+ unsigned int reg;
+
+ reg = fmc_readl(host, FMC_CFG);
+ reg &= ~FLASH_TYPE_SEL_MASK;
+ reg |= FMC_CFG_FLASH_SEL(0);
+ fmc_writel(host, FMC_CFG, reg);
+}
+
+/******************************************************************************/
+static void bsp_spi_nor_init(struct fmc_host *host)
+{
+ unsigned int reg;
+
+ /* switch the flash type to spi nor */
+ spi_nor_switch_spi_type(host);
+
+ /* set the boot mode to normal */
+ reg = fmc_readl(host, FMC_CFG);
+ if ((reg & FMC_CFG_OP_MODE_MASK) == FMC_CFG_OP_MODE_BOOT) {
+ reg |= FMC_CFG_OP_MODE(FMC_CFG_OP_MODE_NORMAL);
+ fmc_writel(host, FMC_CFG, reg);
+ }
+
+ /* hold on STR mode */
+ reg = fmc_readl(host, FMC_GLOBAL_CFG);
+ reg &= (~FMC_GLOBAL_CFG_DTR_MODE);
+ fmc_writel(host, FMC_GLOBAL_CFG, reg);
+
+ /* set timming */
+ reg = TIMING_CFG_TCSH(CS_HOLD_TIME)
+ | TIMING_CFG_TCSS(CS_SETUP_TIME)
+ | TIMING_CFG_TSHSL(CS_DESELECT_TIME);
+ fmc_writel(host, FMC_SPI_TIMING_CFG, reg);
+}
+
+/******************************************************************************/
+static int bsp_spi_nor_prep(struct spi_nor *nor, enum spi_nor_ops ops)
+{
+ struct fmc_priv *priv = nor->priv;
+ struct fmc_host *host = priv->host;
+ u32 clkrate;
+ int ret;
+
+ mutex_lock(&fmc_switch_mutex);
+ mutex_lock(host->lock);
+
+ clkrate = min_t(u32, priv->clkrate, nor->clkrate);
+ ret = clk_set_rate(host->clk, clkrate);
+ if (ret)
+ goto out;
+
+ ret = clk_prepare_enable(host->clk);
+ if (ret)
+ goto out;
+
+ spi_nor_switch_spi_type(host);
+
+ return 0;
+
+out:
+ mutex_unlock(host->lock);
+ return ret;
+}
+
+/******************************************************************************/
+static void bsp_spi_nor_unprep(struct spi_nor *nor, enum spi_nor_ops ops)
+{
+ struct fmc_priv *priv = nor->priv;
+ struct fmc_host *host = priv->host;
+
+ clk_disable_unprepare(host->clk);
+ mutex_unlock(host->lock);
+ mutex_unlock(&fmc_switch_mutex);
+}
+
+/******************************************************************************/
+static int bsp_spi_nor_op_reg(struct spi_nor *nor,
+ u8 opcode, u32 len, u8 optype)
+{
+ struct fmc_priv *priv = nor->priv;
+ struct fmc_host *host = priv->host;
+ u32 reg;
+
+ reg = FMC_CMD_CMD1(opcode);
+ fmc_writel(host, FMC_CMD, reg);
+
+ reg = FMC_DATA_NUM_CNT(len);
+ fmc_writel(host, FMC_DATA_NUM, reg);
+
+ reg = OP_CFG_FM_CS(priv->chipselect) | OP_CFG_OEN_EN;
+ fmc_writel(host, FMC_OP_CFG, reg);
+
+ fmc_writel(host, FMC_INT_CLR, 0xff);
+ reg = FMC_OP_CMD1_EN | FMC_OP_REG_OP_START | optype;
+ fmc_writel(host, FMC_OP, reg);
+
+ return wait_op_finish(host);
+}
+
+/******************************************************************************/
+static int bsp_spi_nor_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf,
+ int len)
+{
+ struct fmc_priv *priv = nor->priv;
+ struct fmc_host *host = priv->host;
+ int ret;
+
+ ret = bsp_spi_nor_op_reg(nor, opcode, len, FMC_OP_READ_DATA_EN);
+ if (ret)
+ return ret;
+
+ memcpy_fromio(buf, host->iobase, len);
+ return 0;
+}
+
+/******************************************************************************/
+static int bsp_spi_nor_write_reg(struct spi_nor *nor, u8 opcode,
+ u8 *buf, int len)
+{
+ struct fmc_priv *priv = nor->priv;
+ struct fmc_host *host = priv->host;
+
+ if (len)
+ memcpy_toio(host->iobase, buf, len);
+
+ return bsp_spi_nor_op_reg(nor, opcode, len, FMC_OP_WRITE_DATA_EN);
+}
+
+/******************************************************************************/
+static int bsp_spi_nor_dma_transfer(struct spi_nor *nor, loff_t start_off,
+ dma_addr_t dma_buf, size_t len, u8 op_type)
+{
+ struct fmc_priv *priv = nor->priv;
+ struct fmc_host *host = priv->host;
+ u8 if_type = 0, dummy = 0;
+ u32 reg;
+
+ reg = fmc_readl(host, FMC_CFG);
+ reg &= ~(FMC_CFG_OP_MODE_MASK | SPI_NOR_ADDR_MODE_MASK);
+ reg |= FMC_CFG_OP_MODE_NORMAL;
+ reg |= (nor->addr_width == 4) ? SPI_NOR_ADDR_MODE_4BYTES
+ : SPI_NOR_ADDR_MODE_3BYTES;
+ fmc_writel(host, FMC_CFG, reg);
+
+ fmc_writel(host, FMC_ADDRL, start_off);
+
+ reg = (unsigned int)dma_buf;
+ fmc_writel(host, FMC_DMA_SADDR_D0, reg);
+
+#ifdef CONFIG_64BIT
+ reg = (dma_buf & FMC_DMA_SADDRH_MASK) >> 32;
+ fmc_writel(host, FMC_DMA_SADDRH_D0, reg);
+#endif
+
+ fmc_writel(host, FMC_DMA_LEN, FMC_DMA_LEN_SET(len));
+
+ reg = OP_CFG_FM_CS(priv->chipselect);
+ if (op_type == FMC_OP_READ) {
+ if_type = get_if_type(nor->read_proto);
+ dummy = nor->read_dummy >> 3;
+ } else {
+ if_type = get_if_type(nor->write_proto);
+ }
+ reg |= OP_CFG_MEM_IF_TYPE(if_type)
+ | OP_CFG_DUMMY_NUM(dummy)
+ | OP_CFG_OEN_EN;
+ fmc_writel(host, FMC_OP_CFG, reg);
+
+ fmc_writel(host, FMC_INT_CLR, 0xff);
+ reg = OP_CTRL_RW_OP(op_type) | OP_CTRL_DMA_OP_READY;
+ reg |= (op_type == FMC_OP_READ)
+ ? OP_CTRL_RD_OPCODE(nor->read_opcode)
+ : OP_CTRL_WR_OPCODE(nor->program_opcode);
+ fmc_writel(host, FMC_OP_DMA, reg);
+
+ return wait_op_finish(host);
+}
+
+static ssize_t bsp_spi_nor_read(struct spi_nor *nor, loff_t from, size_t len,
+ u_char *read_buf)
+{
+ struct fmc_priv *priv = nor->priv;
+ struct fmc_host *host = priv->host;
+ size_t offset;
+ int ret;
+
+ for (offset = 0; offset < len; offset += host->dma_len) {
+ size_t trans = min_t(size_t, host->dma_len, len - offset);
+
+ ret = bsp_spi_nor_dma_transfer(nor,
+ from + offset, host->dma_buffer, trans, FMC_OP_READ);
+ if (ret) {
+ dev_warn(nor->dev, "DMA read timeout\n");
+ return ret;
+ }
+ memcpy(read_buf + offset, host->buffer, trans);
+ }
+
+ return len;
+}
+
+static ssize_t bsp_spi_nor_write(struct spi_nor *nor, loff_t to,
+ size_t len, const u_char *write_buf)
+{
+ struct fmc_priv *priv = nor->priv;
+ struct fmc_host *host = priv->host;
+ size_t offset;
+ int ret;
+
+ for (offset = 0; offset < len; offset += host->dma_len) {
+ size_t trans = min_t(size_t, host->dma_len, len - offset);
+
+ memcpy(host->buffer, write_buf + offset, trans);
+ ret = bsp_spi_nor_dma_transfer(nor,
+ to + offset, host->dma_buffer, trans, FMC_OP_WRITE);
+ if (ret) {
+ dev_warn(nor->dev, "DMA write timeout\n");
+ return ret;
+ }
+ }
+
+ return len;
+}
+
+/**
+ * parse partitions info and register spi flash device as mtd device.
+ */
+static int bsp_snor_device_register(struct mtd_info *mtd)
+{
+ int ret;
+ struct mtd_partitions parsed;
+
+ /*
+ * We do not add the whole spi flash as a mtdblock device,
+ * To avoid the number of nand partition +1.
+ */
+ memset(&parsed, 0, sizeof(parsed));
+ ret = parse_mtd_partitions(mtd, NULL, &parsed, NULL);
+ if (ret)
+ return ret;
+
+ return parsed.nr_parts ? mtd_device_register(mtd, NULL, 0) : parsed.nr_parts;
+}
+
+/**
+ * Get spi flash device information and register it as a mtd device.
+ */
+static int bsp_spi_nor_register(struct device_node *np,
+ struct fmc_host *host)
+{
+ struct device *dev = host->dev;
+ struct spi_nor *nor;
+ struct fmc_priv *priv = &host->priv[host->num_chip];
+ struct mtd_info *mtd;
+ int ret;
+ struct spi_nor_modes modes = {
+ .rd_modes = SNOR_MODE_SLOW,
+ .wr_modes = SNOR_MODE_1_1_1,
+ };
+
+ nor = devm_kzalloc(dev, sizeof(*nor), GFP_KERNEL);
+ if (!nor)
+ return -ENOMEM;
+
+ nor->dev = dev;
+ spi_nor_set_flash_node(nor, np);
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ ret = of_property_read_u32(np, "reg", &priv->chipselect);
+ if (ret) {
+ dev_err(dev, "There's no reg property for %s\n",
+ np->full_name);
+ return ret;
+ }
+
+ if (priv->chipselect != host->num_chip) {
+ dev_warn(dev, " The CS: %d states in device trees isn't real " \
+ "chipselect on board\n, using CS: %d instead. ",
+ priv->chipselect, host->num_chip);
+ priv->chipselect = host->num_chip;
+ }
+
+ ret = of_property_read_u32(np, "spi-max-frequency",
+ &priv->clkrate);
+ if (ret) {
+ dev_err(dev, "There's no spi-max-frequency property for %s\n",
+ np->full_name);
+ return ret;
+ }
+ priv->host = host;
+ nor->priv = priv;
+
+ nor->prepare = bsp_spi_nor_prep;
+ nor->unprepare = bsp_spi_nor_unprep;
+ nor->read_reg = bsp_spi_nor_read_reg;
+ nor->write_reg = bsp_spi_nor_write_reg;
+ nor->read = bsp_spi_nor_read;
+ nor->write = bsp_spi_nor_write;
+
+ modes.rd_modes |= SNOR_MODE_1_1_1
+ | SNOR_MODE_1_1_2
+ | SNOR_MODE_1_2_2;
+#ifndef CONFIG_CLOSE_SPI_8PIN_4IO
+ modes.rd_modes |= SNOR_MODE_1_1_4 | SNOR_MODE_1_4_4;
+ modes.wr_modes |= SNOR_MODE_1_1_4 | SNOR_MODE_1_4_4;
+#endif
+ ret = spi_nor_scan(nor, NULL, &modes);
+ if (ret)
+ return ret;
+
+ mtd = &nor->mtd;
+ mtd->name = np->name;
+ ret = bsp_snor_device_register(mtd);
+ if (ret)
+ return ret;
+
+ /* current chipselect has scanned, to detect next chipselect */
+ fmc_cs_user[host->num_chip]++;
+ host->nor[host->num_chip] = nor;
+ return 0;
+}
+
+static void bsp_spi_nor_unregister_all(struct fmc_host *host)
+{
+ int i;
+
+ for (i = 0; i < host->num_chip; i++)
+ mtd_device_unregister(&host->nor[i]->mtd);
+}
+
+static int bsp_spi_nor_register_all(struct fmc_host *host)
+{
+ struct device *dev = host->dev;
+ struct device_node *np = NULL;
+ int ret;
+
+ for_each_available_child_of_node(dev->of_node, np) {
+ if (fmc_cs_user[host->num_chip]) {
+ dev_warn(dev, "Current CS(%d) is occupied.\n",
+ host->num_chip);
+ continue;
+ }
+ ret = bsp_spi_nor_register(np, host);
+ if (ret)
+ goto fail;
+
+ if (host->num_chip == FMC_MAX_CHIP_NUM) {
+ dev_warn(dev, "Flash device number exceeds the "
+ "maximum chipselect number\n");
+ break;
+ }
+
+ host->num_chip++;
+
+ }
+
+ return 0;
+
+fail:
+ bsp_spi_nor_unregister_all(host);
+ return ret;
+}
+
+/******************************************************************************/
+static int bsp_spi_nor_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct bsp_fmc *fmc = dev_get_drvdata(dev->parent);
+ struct fmc_host *host;
+ int ret;
+
+ if (!fmc) {
+ dev_err(&pdev->dev, "get mfd fmc devices failed\n");
+ return -ENXIO;
+ }
+
+ host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL);
+ if (!host)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, host);
+ host->dev = dev;
+
+ host->regbase = fmc->regbase;
+ host->iobase = fmc->iobase;
+ host->clk = fmc->clk;
+ host->lock = &fmc->lock;
+ host->buffer = fmc->buffer;
+ host->dma_buffer = fmc->dma_buffer;
+ host->dma_len = fmc->dma_len;
+
+ clk_prepare_enable(host->clk);
+ bsp_spi_nor_init(host);
+ ret = bsp_spi_nor_register_all(host);
+ if (ret)
+ dev_warn(dev, "spi nor register fail!\n");
+
+ clk_disable_unprepare(host->clk);
+
+ return ret;
+}
+
+/******************************************************************************/
+static int bsp_spi_nor_remove(struct platform_device *pdev)
+{
+ struct fmc_host *host = platform_get_drvdata(pdev);
+ if (host == NULL){
+ dev_err(&pdev->dev, "host is NULL ,remove err !!\n");
+ return 0;
+ }
+
+ bsp_spi_nor_unregister_all(host);
+ clk_disable_unprepare(host->clk);
+ return 0;
+}
+
+/******************************************************************************/
+static void bsp_spi_nor_driver_shutdown(struct platform_device *pdev)
+{
+ int i;
+ struct fmc_host *host = platform_get_drvdata(pdev);
+
+ if (!host)
+ return;
+
+ mutex_lock(host->lock);
+ clk_prepare_enable(host->clk);
+
+ spi_nor_switch_spi_type(host);
+ for (i = 0; i < host->num_chip; i++)
+ spi_nor_driver_shutdown(host->nor[i]);
+
+ clk_disable_unprepare(host->clk);
+ mutex_unlock(host->lock);
+ dev_dbg(host->dev, "End of driver shutdown\n");
+}
+
+#ifdef CONFIG_PM
+/******************************************************************************/
+static int bsp_spi_nor_driver_suspend(struct platform_device *pdev,
+ pm_message_t state)
+{
+ int i;
+ struct fmc_host *host = platform_get_drvdata(pdev);
+
+ if (!host)
+ return 0;
+
+ mutex_lock(host->lock);
+ clk_prepare_enable(host->clk);
+
+ spi_nor_switch_spi_type(host);
+ for (i = 0; i < host->num_chip; i++)
+ spi_nor_suspend(host->nor[i], state);
+
+ clk_disable_unprepare(host->clk);
+ mutex_unlock(host->lock);
+ dev_dbg(host->dev, "End of suspend\n");
+
+ return 0;
+}
+
+/******************************************************************************/
+static int bsp_spi_nor_driver_resume(struct platform_device *pdev)
+{
+ int i;
+ struct fmc_host *host = platform_get_drvdata(pdev);
+
+ if (!host)
+ return 0;
+
+ mutex_lock(host->lock);
+ clk_prepare_enable(host->clk);
+
+ spi_nor_switch_spi_type(host);
+ for (i = 0; i < host->num_chip; i++)
+ spi_nor_resume(host->nor[i]);
+
+ mutex_unlock(host->lock);
+ dev_dbg(host->dev, "End of resume\n");
+
+ return 0;
+}
+#endif /* End of CONFIG_PM */
+
+/******************************************************************************/
+static const struct of_device_id bsp_spi_nor_dt_ids[] = {
+ { .compatible = "goke,fmc-spi-nor"},
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, bsp_spi_nor_dt_ids);
+
+/******************************************************************************/
+static struct platform_driver bsp_spi_nor_driver = {
+ .driver = {
+ .name = "bsp-sfc",
+ .of_match_table = bsp_spi_nor_dt_ids,
+ },
+ .probe = bsp_spi_nor_probe,
+ .remove = bsp_spi_nor_remove,
+ .shutdown = bsp_spi_nor_driver_shutdown,
+#ifdef CONFIG_PM
+ .suspend = bsp_spi_nor_driver_suspend,
+ .resume = bsp_spi_nor_driver_resume,
+#endif
+};
+module_platform_driver(bsp_spi_nor_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Goke SPI Nor Flash Controller Driver");
diff -urN linux-4.9.37/drivers/mtd/spi-nor/Kconfig linux-4.9.y/drivers/mtd/spi-nor/Kconfig
--- linux-4.9.37/drivers/mtd/spi-nor/Kconfig 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/mtd/spi-nor/Kconfig 2021-06-07 13:01:33.000000000 +0300
@@ -65,6 +65,34 @@
help
This enables support for hisilicon SPI-NOR flash controller.
+config SPI_GOKE_SFC
+ tristate "Goke FMCV100 SPI-NOR Flash Controller(SFC)"
+ depends on ARCH_GOKE || ARCH_GOKE || COMPILE_TEST
+ depends on HAS_IOMEM && HAS_DMA
+ help
+ This enables support for goke flash memory contrller ver100
+ (FMCV100)- SPI-NOR flash controller.
+
+config CLOSE_SPI_8PIN_4IO
+ bool "Close SPI device Quad SPI mode for some 8PIN chip"
+ default y if ARCH_GOKE
+ help
+ fmcv100 and sfcv350 support Quad SPI mode and Quad&addr SPI mode.
+ But some 8PIN chip does not support this mode when HOLD/IO3 PIN
+ was used by reset operation.
+ Usually, your should not config this option.
+
+config GOKE_SPI_BLOCK_PROTECT
+ bool "Goke Spi Nor Device BP(Block Protect) Support"
+ depends on SPI_GOKE_SFC
+ default y if SPI_GOKE_SFC
+ help
+ GOKE SFC supports BP(Block Protect) feature to preestablish a series
+ area to avoid writing and erasing, except to reading. With this macro
+ definition we can get the BP info which was setted before. The
+ BOTTOM/TOP bit is setted to BOTTOM, it means the lock area starts
+ from 0 address.
+
config SPI_NXP_SPIFI
tristate "NXP SPI Flash Interface (SPIFI)"
depends on OF && (ARCH_LPC18XX || COMPILE_TEST)
diff -urN linux-4.9.37/drivers/mtd/spi-nor/Makefile linux-4.9.y/drivers/mtd/spi-nor/Makefile
--- linux-4.9.37/drivers/mtd/spi-nor/Makefile 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/mtd/spi-nor/Makefile 2021-06-07 13:01:33.000000000 +0300
@@ -2,6 +2,7 @@
obj-$(CONFIG_SPI_ATMEL_QUADSPI) += atmel-quadspi.o
obj-$(CONFIG_SPI_CADENCE_QUADSPI) += cadence-quadspi.o
obj-$(CONFIG_SPI_FSL_QUADSPI) += fsl-quadspi.o
+obj-$(CONFIG_SPI_GOKE_SFC) += goke-sfc.o
obj-$(CONFIG_SPI_HISI_SFC) += hisi-sfc.o
obj-$(CONFIG_MTD_MT81xx_NOR) += mtk-quadspi.o
obj-$(CONFIG_SPI_NXP_SPIFI) += nxp-spifi.o
diff -urN linux-4.9.37/drivers/mtd/spi-nor/spi-nor.c linux-4.9.y/drivers/mtd/spi-nor/spi-nor.c
--- linux-4.9.37/drivers/mtd/spi-nor/spi-nor.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/mtd/spi-nor/spi-nor.c 2021-06-07 13:01:33.000000000 +0300
@@ -75,6 +75,13 @@
* bit. Must be used with
* SPI_NOR_HAS_LOCK.
*/
+#define SPI_NOR_4B_OPCODES BIT(10) /*
+ * Use dedicated 4byte address op codes
+ * to support memory size above 128Mib.
+ */
+
+ const struct spi_nor_basic_flash_parameter *params;
+ u32 clkrate;
};
#define JEDEC_MFR(info) ((info)->id[0])
@@ -139,31 +146,24 @@
}
/*
- * Dummy Cycle calculation for different type of read.
- * It can be used to support more commands with
- * different dummy cycle requirements.
+ * Write status register 1 byte
+ * Returns negative if error occurred.
*/
-static inline int spi_nor_read_dummy_cycles(struct spi_nor *nor)
+static inline int write_sr(struct spi_nor *nor, u8 val)
{
- switch (nor->flash_read) {
- case SPI_NOR_FAST:
- case SPI_NOR_DUAL:
- case SPI_NOR_QUAD:
- return 8;
- case SPI_NOR_NORMAL:
- return 0;
- }
- return 0;
+ nor->cmd_buf[0] = val;
+ return nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 1);
}
+
/*
- * Write status register 1 byte
+ * Write status register-2 1 byte
* Returns negative if error occurred.
*/
-static inline int write_sr(struct spi_nor *nor, u8 val)
+static inline int write_sr2(struct spi_nor *nor, u8 val)
{
nor->cmd_buf[0] = val;
- return nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 1);
+ return nor->write_reg(nor, SPINOR_OP_WRSR2, nor->cmd_buf, 1);
}
/*
@@ -188,9 +188,83 @@
return mtd->priv;
}
+struct spi_nor_address_entry {
+ u8 src_opcode;
+ u8 dst_opcode;
+};
+
+static u8 spi_nor_convert_opcode(u8 opcode,
+ const struct spi_nor_address_entry *entries,
+ size_t num_entries)
+{
+ unsigned int min, max;
+
+ min = 0;
+ max = num_entries - 1;
+ while (min <= max) {
+ int mid = (min + max) >> 1;
+ const struct spi_nor_address_entry *entry = &entries[mid];
+
+ if (opcode == entry->src_opcode)
+ return entry->dst_opcode;
+
+ if (opcode < entry->src_opcode)
+ max = mid - 1;
+ else
+ min = mid + 1;
+ }
+
+ /* No conversion found */
+ return opcode;
+}
+
+static u8 spi_nor_3to4_opcode(u8 opcode)
+{
+ /* MUST be sorted by 3byte opcode */
+#define ENTRY_3TO4(_opcode) { _opcode, _opcode##_4B }
+ static const struct spi_nor_address_entry spi_nor_3to4_table[] = {
+ ENTRY_3TO4(SPINOR_OP_PP), /* 0x02 */
+ ENTRY_3TO4(SPINOR_OP_READ), /* 0x03 */
+ ENTRY_3TO4(SPINOR_OP_READ_FAST), /* 0x0b */
+ ENTRY_3TO4(SPINOR_OP_BE_4K), /* 0x20 */
+ ENTRY_3TO4(SPINOR_OP_PP_1_1_4), /* 0x32 */
+ ENTRY_3TO4(SPINOR_OP_PP_1_4_4), /* 0x38 */
+ ENTRY_3TO4(SPINOR_OP_READ_1_1_2), /* 0x3b */
+ ENTRY_3TO4(SPINOR_OP_BE_32K), /* 0x52 */
+ ENTRY_3TO4(SPINOR_OP_READ_1_1_4), /* 0x6b */
+ ENTRY_3TO4(SPINOR_OP_READ_1_2_2), /* 0xbb */
+ ENTRY_3TO4(SPINOR_OP_SE), /* 0xd8 */
+ ENTRY_3TO4(SPINOR_OP_READ_1_4_4), /* 0xeb */
+ };
+#undef ENTRY_3TO4
+
+ return spi_nor_convert_opcode(opcode, spi_nor_3to4_table,
+ ARRAY_SIZE(spi_nor_3to4_table));
+}
+
+static void spi_nor_set_4byte_opcodes(struct spi_nor *nor,
+ const struct flash_info *info)
+{
+ /* Do some manufacturer fixups first */
+ switch (JEDEC_MFR(info)) {
+ case SNOR_MFR_SPANSION:
+ /* No small sector erase for 4-byte command set */
+ nor->erase_opcode = SPINOR_OP_SE;
+ nor->mtd.erasesize = info->sector_size;
+ break;
+
+ default:
+ break;
+ }
+
+ nor->read_opcode = spi_nor_3to4_opcode(nor->read_opcode);
+ nor->program_opcode = spi_nor_3to4_opcode(nor->program_opcode);
+ nor->erase_opcode = spi_nor_3to4_opcode(nor->erase_opcode);
+}
+
/* Enable/disable 4-byte addressing mode. */
static inline int set_4byte(struct spi_nor *nor, const struct flash_info *info,
- int enable)
+ u32 enable)
{
int status;
bool need_wren = false;
@@ -201,16 +275,26 @@
/* Some Micron need WREN command; all will accept it */
need_wren = true;
case SNOR_MFR_MACRONIX:
- case SNOR_MFR_WINBOND:
if (need_wren)
write_enable(nor);
cmd = enable ? SPINOR_OP_EN4B : SPINOR_OP_EX4B;
status = nor->write_reg(nor, cmd, NULL, 0);
+
if (need_wren)
write_disable(nor);
return status;
+ case SNOR_MFR_WINBOND:
+ if (enable)
+ return nor->write_reg(nor, SPINOR_OP_EN4B, NULL, 0);
+ else {
+ /* w25q256fvfg must send reset to disable 4 byte mode */
+ nor->write_reg(nor, SPINOR_ENABLE_RESET, NULL, 0);
+ nor->write_reg(nor, SPINOR_OP_RESET, NULL, 0);
+ udelay(30);
+ }
+ return 0;
default:
/* Spansion style */
nor->cmd_buf[0] = enable << 7;
@@ -220,24 +304,28 @@
static inline int spi_nor_sr_ready(struct spi_nor *nor)
{
int sr = read_sr(nor);
+
if (sr < 0)
return sr;
else
- return !(sr & SR_WIP);
+ return !((unsigned int)sr & SR_WIP);
}
-static inline int spi_nor_fsr_ready(struct spi_nor *nor)
+static inline unsigned int spi_nor_fsr_ready(struct spi_nor *nor)
{
int fsr = read_fsr(nor);
+ unsigned int ufsr = (unsigned int)fsr;
+
if (fsr < 0)
return fsr;
else
- return fsr & FSR_READY;
+ return ufsr & FSR_READY;
}
static int spi_nor_ready(struct spi_nor *nor)
{
int sr, fsr;
+
sr = spi_nor_sr_ready(nor);
if (sr < 0)
return sr;
@@ -282,7 +370,31 @@
return spi_nor_wait_till_ready_with_timeout(nor,
DEFAULT_READY_WAIT_JIFFIES);
}
+static int issi_spi_nor_wait_till_ready(struct spi_nor *nor)
+{
+ unsigned long deadline;
+ int timeout = 0;
+ int ret;
+ deadline = jiffies + DEFAULT_READY_WAIT_JIFFIES;
+
+ while (!timeout) {
+ if (time_after_eq(jiffies, deadline))
+ timeout = 1;
+
+ ret = spi_nor_sr_ready(nor);
+ if (ret < 0)
+ return ret;
+ if (ret)
+ return 0;
+
+ cond_resched();
+ }
+
+ dev_err(nor->dev, "flash operation timed out\n");
+
+ return -ETIMEDOUT;
+}
/*
* Erase the whole flash memory
*
@@ -367,6 +479,12 @@
if (ret)
return ret;
+#ifdef CONFIG_GOKE_SPI_BLOCK_PROTECT
+ if ((nor->level) && (addr < nor->end_addr)) {
+ dev_err(nor->dev, "Error: The erase area was locked\n");
+ return -EINVAL;
+ }
+#endif
/* whole-chip erase? */
if (len == mtd->size) {
unsigned long timeout;
@@ -745,6 +863,280 @@
return ret;
}
+#define SNOR_RD_MODES \
+ (SNOR_MODE_SLOW | \
+ SNOR_MODE_1_1_1 | \
+ SNOR_MODE_1_1_2 | \
+ SNOR_MODE_1_2_2 | \
+ SNOR_MODE_1_1_4 | \
+ SNOR_MODE_1_4_4)
+
+#define SNOR_WR_MODES \
+ (SNOR_MODE_1_1_1 | \
+ SNOR_MODE_1_1_4)
+
+static int spansion_quad_enable(struct spi_nor *nor);
+static int macronix_quad_enable(struct spi_nor *nor);
+static int gd_quad_enable(struct spi_nor *nor);
+static int xtx_quad_enable(struct spi_nor *nor);
+static int issi_quad_enable(struct spi_nor *nor);
+static int puya_quad_enable(struct spi_nor *nor);
+static int puya_quad_enable(struct spi_nor *nor);
+
+#define SNOR_EON_RD_MODES \
+ (SNOR_MODE_SLOW | \
+ SNOR_MODE_1_1_1 | \
+ SNOR_MODE_1_1_2 | \
+ SNOR_MODE_1_2_2)
+
+#define SNOR_EON_WR_MODES \
+ (SNOR_MODE_1_1_1)
+
+static const struct spi_nor_basic_flash_parameter eon_params = {
+ .rd_modes = SNOR_EON_RD_MODES,
+ .reads[SNOR_MIDX_SLOW] = SNOR_OP_READ(0, 0, SPINOR_OP_READ),
+ .reads[SNOR_MIDX_1_1_1] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_FAST),
+ .reads[SNOR_MIDX_1_1_2] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_2),
+ .reads[SNOR_MIDX_1_2_2] = SNOR_OP_READ(8, 0, SPINOR_OP_READ_1_2_2),
+ .reads[SNOR_MIDX_1_1_4] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_4),
+ .reads[SNOR_MIDX_1_4_4] = SNOR_OP_READ(8, 16, SPINOR_OP_READ_1_4_4),
+
+ .wr_modes = SNOR_EON_WR_MODES,
+ .page_programs[SNOR_MIDX_1_1_1] = SPINOR_OP_PP,
+
+ .erase_types[0] = SNOR_OP_ERASE_64K(SPINOR_OP_SE),
+
+};
+
+static const struct spi_nor_basic_flash_parameter esmt_params = {
+ .rd_modes = SNOR_RD_MODES,
+ .reads[SNOR_MIDX_SLOW] = SNOR_OP_READ(0, 0, SPINOR_OP_READ),
+ .reads[SNOR_MIDX_1_1_1] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_FAST),
+ .reads[SNOR_MIDX_1_1_2] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_2),
+ .reads[SNOR_MIDX_1_2_2] = SNOR_OP_READ(8, 0, SPINOR_OP_READ_1_2_2),
+ .reads[SNOR_MIDX_1_1_4] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_4),
+ .reads[SNOR_MIDX_1_4_4] = SNOR_OP_READ(8, 16, SPINOR_OP_READ_1_4_4),
+
+ .wr_modes = SNOR_WR_MODES,
+ .page_programs[SNOR_MIDX_1_1_1] = SPINOR_OP_PP,
+ .page_programs[SNOR_MIDX_1_1_4] = SPINOR_OP_PP_1_1_4,
+
+ .erase_types[0] = SNOR_OP_ERASE_64K(SPINOR_OP_SE),
+
+ .enable_quad_io = macronix_quad_enable,
+
+};
+
+#define SNOR_PARAGON_WR_MODES \
+ (SNOR_MODE_1_1_1)
+
+static const struct spi_nor_basic_flash_parameter paragon_params = {
+ .rd_modes = SNOR_RD_MODES,
+ .reads[SNOR_MIDX_SLOW] = SNOR_OP_READ(0, 0, SPINOR_OP_READ),
+ .reads[SNOR_MIDX_1_1_1] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_FAST),
+ .reads[SNOR_MIDX_1_1_2] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_2),
+ .reads[SNOR_MIDX_1_2_2] = SNOR_OP_READ(8, 0, SPINOR_OP_READ_1_2_2),
+ .reads[SNOR_MIDX_1_1_4] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_4),
+ .reads[SNOR_MIDX_1_4_4] = SNOR_OP_READ(8, 16, SPINOR_OP_READ_1_4_4),
+
+ .wr_modes = SNOR_PARAGON_WR_MODES,
+ .page_programs[SNOR_MIDX_1_1_1] = SPINOR_OP_PP,
+
+ .erase_types[0] = SNOR_OP_ERASE_64K(SPINOR_OP_SE),
+
+ .enable_quad_io = spansion_quad_enable,
+
+};
+
+static const struct spi_nor_basic_flash_parameter gd_params = {
+ .rd_modes = SNOR_RD_MODES,
+ .reads[SNOR_MIDX_SLOW] = SNOR_OP_READ(0, 0, SPINOR_OP_READ),
+ .reads[SNOR_MIDX_1_1_1] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_FAST),
+ .reads[SNOR_MIDX_1_1_2] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_2),
+ .reads[SNOR_MIDX_1_2_2] = SNOR_OP_READ(8, 0, SPINOR_OP_READ_1_2_2),
+ .reads[SNOR_MIDX_1_1_4] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_4),
+ .reads[SNOR_MIDX_1_4_4] = SNOR_OP_READ(8, 16, SPINOR_OP_READ_1_4_4),
+
+ .wr_modes = SNOR_WR_MODES,
+ .page_programs[SNOR_MIDX_1_1_1] = SPINOR_OP_PP,
+ .page_programs[SNOR_MIDX_1_1_4] = SPINOR_OP_PP_1_1_4,
+
+ .erase_types[0] = SNOR_OP_ERASE_64K(SPINOR_OP_SE),
+
+ .enable_quad_io = gd_quad_enable,
+
+};
+
+static const struct spi_nor_basic_flash_parameter winbond_params = {
+ .rd_modes = SNOR_RD_MODES,
+ .reads[SNOR_MIDX_SLOW] = SNOR_OP_READ(0, 0, SPINOR_OP_READ),
+ .reads[SNOR_MIDX_1_1_1] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_FAST),
+ .reads[SNOR_MIDX_1_1_2] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_2),
+ .reads[SNOR_MIDX_1_2_2] = SNOR_OP_READ(8, 0, SPINOR_OP_READ_1_2_2),
+ .reads[SNOR_MIDX_1_1_4] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_4),
+ .reads[SNOR_MIDX_1_4_4] = SNOR_OP_READ(8, 16, SPINOR_OP_READ_1_4_4),
+
+ .wr_modes = SNOR_WR_MODES,
+ .page_programs[SNOR_MIDX_1_1_1] = SPINOR_OP_PP,
+ .page_programs[SNOR_MIDX_1_1_4] = SPINOR_OP_PP_1_1_4,
+
+ .erase_types[0] = SNOR_OP_ERASE_64K(SPINOR_OP_SE),
+
+ .enable_quad_io = spansion_quad_enable,
+
+};
+
+static const struct spi_nor_basic_flash_parameter spansion_params = {
+ .rd_modes = SNOR_RD_MODES,
+ .reads[SNOR_MIDX_SLOW] = SNOR_OP_READ(0, 0, SPINOR_OP_READ),
+ .reads[SNOR_MIDX_1_1_1] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_FAST),
+ .reads[SNOR_MIDX_1_1_2] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_2),
+ .reads[SNOR_MIDX_1_2_2] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_2_2),
+ .reads[SNOR_MIDX_1_1_4] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_4),
+ .reads[SNOR_MIDX_1_4_4] = SNOR_OP_READ(8, 16, SPINOR_OP_READ_1_4_4),
+
+ .wr_modes = SNOR_WR_MODES,
+ .page_programs[SNOR_MIDX_1_1_1] = SPINOR_OP_PP,
+ .page_programs[SNOR_MIDX_1_1_4] = SPINOR_OP_PP_1_1_4,
+
+ .erase_types[0] = SNOR_OP_ERASE_64K(SPINOR_OP_SE),
+
+ .enable_quad_io = spansion_quad_enable,
+
+};
+
+static const struct spi_nor_basic_flash_parameter issi_params = {
+ .rd_modes = SNOR_RD_MODES,
+ .reads[SNOR_MIDX_SLOW] = SNOR_OP_READ(0, 0, SPINOR_OP_READ),
+ .reads[SNOR_MIDX_1_1_1] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_FAST),
+ .reads[SNOR_MIDX_1_1_2] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_2),
+ .reads[SNOR_MIDX_1_2_2] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_2_2),
+ .reads[SNOR_MIDX_1_1_4] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_4),
+ .reads[SNOR_MIDX_1_4_4] = SNOR_OP_READ(8, 16, SPINOR_OP_READ_1_4_4),
+
+ .wr_modes = SNOR_WR_MODES,
+ .page_programs[SNOR_MIDX_1_1_1] = SPINOR_OP_PP,
+ .page_programs[SNOR_MIDX_1_1_4] = SPINOR_OP_PP_1_1_4,
+
+ .erase_types[0] = SNOR_OP_ERASE_64K(SPINOR_OP_SE),
+
+ .enable_quad_io = issi_quad_enable,
+
+};
+
+#define SNOR_MXIC_WR_MODES \
+ (SNOR_MODE_1_1_1 | \
+ SNOR_MODE_1_4_4)
+
+static const struct spi_nor_basic_flash_parameter mxic_params = {
+ .rd_modes = SNOR_RD_MODES,
+ .reads[SNOR_MIDX_SLOW] = SNOR_OP_READ(0, 0, SPINOR_OP_READ),
+ .reads[SNOR_MIDX_1_1_1] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_FAST),
+ .reads[SNOR_MIDX_1_1_2] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_2),
+ .reads[SNOR_MIDX_1_2_2] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_2_2),
+ .reads[SNOR_MIDX_1_1_4] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_4),
+ .reads[SNOR_MIDX_1_4_4] = SNOR_OP_READ(8, 16, SPINOR_OP_READ_1_4_4),
+
+ .wr_modes = SNOR_MXIC_WR_MODES,
+ .page_programs[SNOR_MIDX_1_1_1] = SPINOR_OP_PP,
+ .page_programs[SNOR_MIDX_1_4_4] = SPINOR_OP_PP_1_4_4,
+
+ .erase_types[0] = SNOR_OP_ERASE_64K(SPINOR_OP_SE),
+
+ .enable_quad_io = macronix_quad_enable,
+
+};
+
+static const struct spi_nor_basic_flash_parameter xmc_params = {
+ .rd_modes = SNOR_RD_MODES,
+ .reads[SNOR_MIDX_SLOW] = SNOR_OP_READ(0, 0, SPINOR_OP_READ),
+ .reads[SNOR_MIDX_1_1_1] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_FAST),
+ .reads[SNOR_MIDX_1_1_2] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_2),
+ .reads[SNOR_MIDX_1_2_2] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_2_2),
+ .reads[SNOR_MIDX_1_1_4] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_4),
+ .reads[SNOR_MIDX_1_4_4] = SNOR_OP_READ(0, 24, SPINOR_OP_READ_1_4_4),
+
+ .wr_modes = SNOR_WR_MODES,
+ .page_programs[SNOR_MIDX_1_1_1] = SPINOR_OP_PP,
+ .page_programs[SNOR_MIDX_1_1_4] = SPINOR_OP_PP_1_1_4,
+
+ .erase_types[0] = SNOR_OP_ERASE_64K(SPINOR_OP_SE),
+
+};
+
+static const struct spi_nor_basic_flash_parameter micron_params = {
+ .rd_modes = SNOR_RD_MODES,
+ .reads[SNOR_MIDX_SLOW] = SNOR_OP_READ(0, 0, SPINOR_OP_READ),
+ .reads[SNOR_MIDX_1_1_1] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_FAST),
+ .reads[SNOR_MIDX_1_1_2] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_2),
+ .reads[SNOR_MIDX_1_2_2] = SNOR_OP_READ(8, 8, SPINOR_OP_READ_1_2_2),
+ .reads[SNOR_MIDX_1_1_4] = SNOR_OP_READ(1, 7, SPINOR_OP_READ_1_1_4),
+ .reads[SNOR_MIDX_1_4_4] = SNOR_OP_READ(0, 40, SPINOR_OP_READ_1_4_4),
+
+ .wr_modes = SNOR_WR_MODES,
+ .page_programs[SNOR_MIDX_1_1_1] = SPINOR_OP_PP,
+ .page_programs[SNOR_MIDX_1_1_4] = SPINOR_OP_PP_1_1_4,
+
+ .erase_types[0] = SNOR_OP_ERASE_64K(SPINOR_OP_SE),
+
+};
+
+static const struct spi_nor_basic_flash_parameter micron_4k_params = {
+ .rd_modes = SNOR_RD_MODES,
+ .reads[SNOR_MIDX_SLOW] = SNOR_OP_READ(0, 0, SPINOR_OP_READ),
+ .reads[SNOR_MIDX_1_1_1] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_FAST),
+ .reads[SNOR_MIDX_1_1_2] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_2),
+ .reads[SNOR_MIDX_1_2_2] = SNOR_OP_READ(1, 7, SPINOR_OP_READ_1_2_2),
+ .reads[SNOR_MIDX_1_1_4] = SNOR_OP_READ(1, 7, SPINOR_OP_READ_1_1_4),
+ .reads[SNOR_MIDX_1_4_4] = SNOR_OP_READ(1, 9, SPINOR_OP_READ_1_4_4),
+
+ .wr_modes = SNOR_WR_MODES,
+ .page_programs[SNOR_MIDX_1_1_1] = SPINOR_OP_PP,
+ .page_programs[SNOR_MIDX_1_1_4] = SPINOR_OP_PP_1_1_4,
+
+ .erase_types[0] = SNOR_OP_ERASE_64K(SPINOR_OP_SE),
+ .erase_types[1] = SNOR_OP_ERASE_4K(SPINOR_OP_BE_4K),
+};
+
+static const struct spi_nor_basic_flash_parameter xtx_params = {
+ .rd_modes = SNOR_RD_MODES,
+ .reads[SNOR_MIDX_SLOW] = SNOR_OP_READ(0, 0, SPINOR_OP_READ),
+ .reads[SNOR_MIDX_1_1_1] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_FAST),
+ .reads[SNOR_MIDX_1_1_2] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_2),
+ .reads[SNOR_MIDX_1_2_2] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_2_2),
+ .reads[SNOR_MIDX_1_1_4] = SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_4),
+ .reads[SNOR_MIDX_1_4_4] = SNOR_OP_READ(0, 24, SPINOR_OP_READ_1_4_4),
+
+ .wr_modes = SNOR_WR_MODES,
+ .page_programs[SNOR_MIDX_1_1_1] = SPINOR_OP_PP,
+ .page_programs[SNOR_MIDX_1_1_4] = SPINOR_OP_PP_1_1_4,
+
+ .erase_types[0] = SNOR_OP_ERASE_64K(SPINOR_OP_SE),
+
+ .enable_quad_io = xtx_quad_enable,
+
+};
+
+static const struct spi_nor_basic_flash_parameter puya_params = {
+ .rd_modes= SNOR_RD_MODES,
+ .reads[SNOR_MIDX_SLOW]= SNOR_OP_READ(0, 0, SPINOR_OP_READ),
+ .reads[SNOR_MIDX_1_1_1]= SNOR_OP_READ(0, 8, SPINOR_OP_READ_FAST),
+ .reads[SNOR_MIDX_1_1_2]= SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_2),
+ .reads[SNOR_MIDX_1_2_2]= SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_2_2),
+ .reads[SNOR_MIDX_1_1_4]= SNOR_OP_READ(0, 8, SPINOR_OP_READ_1_1_4),
+ .reads[SNOR_MIDX_1_4_4]= SNOR_OP_READ(0, 24, SPINOR_OP_READ_1_4_4),
+
+ .wr_modes= SNOR_WR_MODES,
+ .page_programs[SNOR_MIDX_1_1_1]= SPINOR_OP_PP,
+ .page_programs[SNOR_MIDX_1_1_4]= SPINOR_OP_PP_1_1_4,
+
+ .erase_types[0]= SNOR_OP_ERASE_64K(SPINOR_OP_SE),
+
+ .enable_quad_io = puya_quad_enable,
+};
+
+#define PARAMS(_name) .params = &_name##_params
+
/* Used when the "_ext_id" is two bytes at most */
#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \
.id = { \
@@ -758,7 +1150,7 @@
.sector_size = (_sector_size), \
.n_sectors = (_n_sectors), \
.page_size = 256, \
- .flags = (_flags),
+ .flags = (_flags)
#define INFO6(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \
.id = { \
@@ -782,6 +1174,10 @@
.addr_width = (_addr_width), \
.flags = (_flags),
+/* Different from spi-max-frequency in DTS, the clk here stands for the clock
+ * rate on SPI interface, it is half of the FMC CRG configuration */
+#define CLK_MHZ_2X(clk) .clkrate = (clk * 2000000),
+
/* NOTE: double check command sets and memory organization when you add
* more nor chips. This current list focusses on newer chips, which
* have been converging on command sets which including JEDEC ID.
@@ -793,6 +1189,63 @@
* For historical (and compatibility) reasons (before we got above config) some
* old entries may be missing 4K flag.
*/
+#define SPI_NOR_IDS_VER "1.2"
+
+/******* SPI Nor ID Table ************************************************************************
+ * Version Manufacturer Chip Name Chipsize Block Vol Operation
+ * Macronix/MXIC MX25V1635F 2M 64K 3V3
+ * 1.0 Macronix/MXIC MX25L1606E 2M 64K 3V3
+ * Macronix/MXIC MX25L6436F 8M 64K 3V3
+ * Macronix/MXIC MX25R6435F 8M 64K 1V8/3V3 Add 14chips
+ * Macronix/MXIC MX25U6435F 8M 64K 1V8
+ * Macronix/MXIC MX25U12835F 16M 64K 1V8
+ * Macronix/MXIC MX25F128XXX 16M 64K 3V3
+ * Macronix/MXIC MX25U25635F/45G 32M 64K 1V8 25645G-DTR
+ * Macronix/MXIC MX25L(256/257) 32M 64K 3V3 25645G-DTR
+ * Macronix/MXIC MX25U51245G 64M 64K 1V8 51245G-DTR
+ * Macronix/MXIC MX25L51245G 64M 64K 3V3
+ * Macronix/MXIC MX66U1G45GM 128M 64K 1V8
+ * Spansion S25FL129P1 16M 64K 3V3
+ * Spansion S25FL256S 32M 64K 3V3
+ * Micron N25Q064A 8M 64K 3V3
+ * Micron N25QL064A 8M 64K 3V3
+ * Micron N25Q128A11/MT25QU128AB 16M 64K 1V8
+ * Micron N25QL128A 16M 64K 3V3
+ * Micron MT25QU256A 32M 64K 1V8
+ * Micron MT25QL256A 32M 64K 3V3
+ * Winbond W25Q16(B/C)V/S25FL016K 2M 64K 3V3
+ * Winbond W25Q32(B/F)V 4M 64K 3V3
+ * Winbond W25Q32FW 4M 64K 1V8
+ * Winbond W25Q64FW 8M 64K 1V8
+ * Winbond W25Q64FV(SPI)/W25Q64JV_IQ 8M 64K 3V3
+ * Winbond W25Q128FW 16M 64K 1V8
+ * Winbond W25Q128(B/F)V 16M 64K 3V3
+ * Winbond W25Q128JV_IM 16M 64K 3V3 DTR
+ * Winbond W25Q256JWEIQ 32M 64K 1V8
+ * Winbond W25Q256JWFIM 32M 64K 1V8
+ * ESMT/CFEON EN25Q32B 4M 64K 3V3
+ * ESMT/CFEON EN25Q64 8M 64K 3V3
+ * ESMT/CFEON EN25Q128 16M 64K 3V3
+ * ESMT/CFEON F25L64QA 8M 64K 3V3
+ * GD GD25Q16C 2M 64K 3V3
+ * GD GD25Q64 8M 64K 3V3
+ * GD GD25LQ128 16M 64K 1V8
+ * GD GD25Q128 16M 64K 3V3
+ * GD GD25Q256 32M 64K 3V3
+ * GD GD25LQ64C 8M 64K 1V8
+ * GD GD25Q32 4M 64K 3V3
+ * Paragon PN25F16S 2M 64K 3V3
+ * Paragon PN25F32S 4M 64K 3V3
+ * 1.1 ESMT/CFEON EN25QH64A 8M 64K 3V3
+ * 1.2 XMC XM25QH64AHIG 8M 64K 3V3
+ * XMC XM25QH128A 16M 64K 3V3
+ * XMC XM25QH128B 16M 64K 3V3
+ * Puya P25Q128H-SUH-IT 16M 64K 3V3
+ * FM FM25Q64-SOB-T-G 8M 64K 3V3
+ * FM FM25Q128-SOB-T-G 16M 64K 3V3
+ * HUAHONG H25S64 8M 64K 3V3
+ * HUAHONG H25S128 16M 64K 3V3
+ ********************************************************************************************/
static const struct flash_info spi_nor_ids[] = {
/* Atmel -- some are (confusingly) marketed as "DataFlash" */
{ "at25fs010", INFO(0x1f6601, 0, 32 * 1024, 4, SECT_4K) },
@@ -812,44 +1265,55 @@
/* EON -- en25xxx */
{ "en25f32", INFO(0x1c3116, 0, 64 * 1024, 64, SECT_4K) },
{ "en25p32", INFO(0x1c2016, 0, 64 * 1024, 64, 0) },
- { "en25q32b", INFO(0x1c3016, 0, 64 * 1024, 64, 0) },
+ { "en25q32b", INFO(0x1c3016, 0, 64 * 1024, 64,
+ SPI_NOR_QUAD_READ), PARAMS(eon), CLK_MHZ_2X(104) },
{ "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) },
- { "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, SECT_4K) },
+ { "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128,
+ SECT_4K | SPI_NOR_QUAD_READ), PARAMS(eon), CLK_MHZ_2X(104) },
+ { "en25qh32b-104hip2b", INFO(0x1c7016, 0, 64 * 1024, 64,
+ SPI_NOR_QUAD_READ), PARAMS(eon), CLK_MHZ_2X(133) },
+ { "en25qh64a", INFO(0x1c7017, 0, 64 * 1024, 128,
+ SPI_NOR_QUAD_READ), PARAMS(eon), CLK_MHZ_2X(104) },
+ { "en25q128", INFO(0x1c3018, 0, 64 * 1024, 256,
+ SPI_NOR_QUAD_READ), PARAMS(eon), CLK_MHZ_2X(104) },
{ "en25qh128", INFO(0x1c7018, 0, 64 * 1024, 256, 0) },
+ { "en25qh128a", INFO(0x1c7018, 0, 64 * 1024, 256,
+ SPI_NOR_QUAD_READ), PARAMS(eon), CLK_MHZ_2X(104) },
{ "en25qh256", INFO(0x1c7019, 0, 64 * 1024, 512, 0) },
{ "en25s64", INFO(0x1c3817, 0, 64 * 1024, 128, SECT_4K) },
/* ESMT */
{ "f25l32pa", INFO(0x8c2016, 0, 64 * 1024, 64, SECT_4K) },
+ { "f25l64qa", INFO(0x8c4117, 0, 64 * 1024, 128,
+ SPI_NOR_QUAD_READ), PARAMS(esmt), CLK_MHZ_2X(84) },
/* Everspin */
- { "mr25h256", CAT25_INFO( 32 * 1024, 1, 256, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
- { "mr25h10", CAT25_INFO(128 * 1024, 1, 256, 3, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
+ { "mr25h256", CAT25_INFO(32 * 1024, 1, 256, 2, SPI_NOR_NO_ERASE
+ | SPI_NOR_NO_FR) },
+ { "mr25h10", CAT25_INFO(128 * 1024, 1, 256, 3, SPI_NOR_NO_ERASE
+ | SPI_NOR_NO_FR) },
/* Fujitsu */
{ "mb85rs1mt", INFO(0x047f27, 0, 128 * 1024, 1, SPI_NOR_NO_ERASE) },
- /* GigaDevice */
- {
- "gd25q32", INFO(0xc84016, 0, 64 * 1024, 64,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
- SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
- },
- {
- "gd25q64", INFO(0xc84017, 0, 64 * 1024, 128,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
- SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
- },
- {
- "gd25lq64c", INFO(0xc86017, 0, 64 * 1024, 128,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
- SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
- },
- {
- "gd25q128", INFO(0xc84018, 0, 64 * 1024, 256,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
- SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
- },
+ /* GigaDevice 3.3V */
+ { "gd25q16c", INFO(0xc84015, 0, 64 * 1024, 32,
+ SECT_4K | SPI_NOR_QUAD_READ), PARAMS(gd), CLK_MHZ_2X(120) },
+ { "gd25q32", INFO(0xc84016, 0, 64 * 1024, 64,
+ SECT_4K | SPI_NOR_QUAD_READ), PARAMS(gd), CLK_MHZ_2X(120) },
+ { "gd25q64", INFO(0xc84017, 0, 64 * 1024, 128,
+ SECT_4K | SPI_NOR_QUAD_READ), PARAMS(gd), CLK_MHZ_2X(120) },
+ { "gd25q128/gd25q127", INFO(0xc84018, 0, 64 * 1024, 256,
+ SECT_4K | SPI_NOR_QUAD_READ), PARAMS(gd), CLK_MHZ_2X(80) },
+ { "gd25q256", INFO(0xc84019, 0, 64 * 1024, 512,
+ SECT_4K | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES), PARAMS(gd), CLK_MHZ_2X(80) },
+ /* GigaDevice 1.8V */
+ { "gd25lq16c", INFO(0xc86015, 0, 64 * 1024, 32,
+ SECT_4K | SPI_NOR_QUAD_READ), PARAMS(gd), CLK_MHZ_2X(104) },
+ { "gd25lq64", INFO(0xc86017, 0, 64 * 1024, 128,
+ SECT_4K | SPI_NOR_QUAD_READ), PARAMS(gd), CLK_MHZ_2X(133) },
+ { "gd25lq128", INFO(0xc86018, 0, 64 * 1024, 256,
+ SECT_4K | SPI_NOR_QUAD_READ), PARAMS(gd), CLK_MHZ_2X(133) },
/* Intel/Numonyx -- xxxs33b */
{ "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0) },
@@ -859,68 +1323,132 @@
/* ISSI */
{ "is25cd512", INFO(0x7f9d20, 0, 32 * 1024, 2, SECT_4K) },
- /* Macronix */
+ { "IS25WP512M-RMLA3", INFO(0x9d701a, 0, 64 * 1024, 1024,
+ SPI_NOR_QUAD_READ), PARAMS(issi), CLK_MHZ_2X(80) },
+
+ /* Macronix/MXIC 3.3V */
{ "mx25l512e", INFO(0xc22010, 0, 64 * 1024, 1, SECT_4K) },
{ "mx25l2005a", INFO(0xc22012, 0, 64 * 1024, 4, SECT_4K) },
{ "mx25l4005a", INFO(0xc22013, 0, 64 * 1024, 8, SECT_4K) },
{ "mx25l8005", INFO(0xc22014, 0, 64 * 1024, 16, 0) },
- { "mx25l1606e", INFO(0xc22015, 0, 64 * 1024, 32, SECT_4K) },
- { "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, SECT_4K) },
+ { "mx25l1606e", INFO(0xc22015, 0, 64 * 1024, 32, SECT_4K
+ | SPI_NOR_DUAL_READ), CLK_MHZ_2X(80) },
+ { "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, 0) },
{ "mx25l3255e", INFO(0xc29e16, 0, 64 * 1024, 64, SECT_4K) },
- { "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, SECT_4K) },
- { "mx25u6435f", INFO(0xc22537, 0, 64 * 1024, 128, SECT_4K) },
- { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) },
+ { "mx25l6436f", INFO(0xc22017, 0, 64 * 1024, 128,
+ SPI_NOR_QUAD_READ), PARAMS(mxic), CLK_MHZ_2X(133) },
+ { "mx25l12835f", INFO(0xc22018, 0, 64 * 1024, 256,
+ SPI_NOR_QUAD_READ), PARAMS(mxic), CLK_MHZ_2X(84) },
{ "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) },
- { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) },
+ { "mx25l25635f", INFO(0xc22019, 0, 64 * 1024, 512,
+ SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES), PARAMS(mxic), CLK_MHZ_2X(84) },
+ { "mx25l25673g", INFO(0xc22019, 0, 64 * 1024, 512, SPI_NOR_QUAD_READ
+ | SPI_NOR_4B_OPCODES) },
{ "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
- { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_QUAD_READ) },
- { "mx66l1g55g", INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ) },
-
- /* Micron */
- { "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64, SPI_NOR_QUAD_READ) },
- { "n25q032a", INFO(0x20bb16, 0, 64 * 1024, 64, SPI_NOR_QUAD_READ) },
- { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_QUAD_READ) },
- { "n25q064a", INFO(0x20bb17, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_QUAD_READ) },
- { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_QUAD_READ) },
- { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_QUAD_READ) },
- { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_QUAD_READ) },
- { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
- { "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
- { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
- { "n25q00a", INFO(0x20bb21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
+ { "mx66l51235l/mx25l51245g", INFO(0xc2201a, 0, 64 * 1024, 1024,
+ SPI_NOR_QUAD_READ), PARAMS(mxic), CLK_MHZ_2X(133)},
+ { "mx66l1g55g", INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ)},
+ { "mx25v1635f", INFO(0xc22315, 0, 64 * 1024, 32 ,
+ SPI_NOR_QUAD_READ), PARAMS(mxic), CLK_MHZ_2X(80) },
+ /* Macronix/MXIC Wide Voltage Range 1.65~3.6V */
+ { "mx25r6435f", INFO(0xc22817, 0, 64 * 1024, 128,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ), CLK_MHZ_2X(80) },
+ /* Macronix/MXIC 1.8V */
+ { "mx25u1633f", INFO(0xc22535, 0, 64 * 1024, 32,
+ SPI_NOR_QUAD_READ), PARAMS(mxic), CLK_MHZ_2X(80) },
+ { "mx25u6435f", INFO(0xc22537, 0, 64 * 1024, 128,
+ SECT_4K | SPI_NOR_QUAD_READ), PARAMS(mxic), CLK_MHZ_2X(84) },
+ { "mx25u12835f/mx25u12832f", INFO(0xc22538, 0, 64 * 1024, 256,
+ SPI_NOR_QUAD_READ), PARAMS(mxic), CLK_MHZ_2X(84) },
+ { "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512,
+ SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES), PARAMS(mxic), CLK_MHZ_2X(84) },
+ { "mx25u51245g", INFO(0xc2253a, 0, 64 * 1024, 1024,
+ SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES), PARAMS(mxic), CLK_MHZ_2X(166) },
+ { "mx66u1g45gm", INFO(0xc2253b, 0, 64 * 1024, 2048,
+ SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES), PARAMS(mxic), CLK_MHZ_2X(133) },
+
+ /* Micron 3.3V */
+ { "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64, SPI_NOR_QUAD_READ),
+ PARAMS(micron), CLK_MHZ_2X(84) },
+ { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, SPI_NOR_QUAD_READ),
+ PARAMS(micron_4k), CLK_MHZ_2X(108) },
+ { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, SPI_NOR_QUAD_READ),
+ PARAMS(micron), CLK_MHZ_2X(108) },
+ { "mt25ql256a", INFO(0x20ba19, 0x1044, 64 * 1024, 512, SPI_NOR_QUAD_READ),
+ PARAMS(micron), CLK_MHZ_2X(108) },
+ { "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024, USE_FSR),
+ PARAMS(micron_4k) },
+ { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, USE_FSR | SPI_NOR_QUAD_READ),
+ PARAMS(micron_4k), CLK_MHZ_2X(80) },
+ /* Micron 1.8V */
+ { "n25q032a", INFO(0x20bb16, 0, 64 * 1024, 64, SPI_NOR_QUAD_READ),
+ PARAMS(micron), CLK_MHZ_2X(108) },
+ { "n25q064a", INFO(0x20bb17, 0, 64 * 1024, 128, SPI_NOR_QUAD_READ),
+ PARAMS(micron), CLK_MHZ_2X(108) },
+ { "mt25qu128a/n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, SPI_NOR_QUAD_READ),
+ PARAMS(micron), CLK_MHZ_2X(108) },
+ { "mt25qu256a", INFO(0x20bb19, 0, 64 * 1024, 512,
+ SPI_NOR_4B_OPCODES | SPI_NOR_QUAD_READ), PARAMS(micron), CLK_MHZ_2X(108) },
+ { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, USE_FSR | SPI_NOR_QUAD_READ),
+ PARAMS(micron_4k), CLK_MHZ_2X(80) },
+
+ /* XMC */
+ { "xm25qh64a", INFO(0x207017, 0, 64 * 1024, 128, SPI_NOR_QUAD_READ),
+ PARAMS(xmc), CLK_MHZ_2X(104) },
+ { "xm25qh64b", INFO(0x206017, 0, 64 * 1024, 128, SPI_NOR_QUAD_READ),
+ PARAMS(xmc), CLK_MHZ_2X(104) },
+ { "xm25qh128a", INFO(0x207018, 0, 64 * 1024, 256, SPI_NOR_QUAD_READ),
+ PARAMS(xmc), CLK_MHZ_2X(104) },
+ { "xm25qh128b", INFO(0x206018, 0, 64 * 1024, 256, SPI_NOR_QUAD_READ),
+ PARAMS(xmc), CLK_MHZ_2X(104) },
/* PMC */
- { "pm25lv512", INFO(0, 0, 32 * 1024, 2, SECT_4K_PMC) },
- { "pm25lv010", INFO(0, 0, 32 * 1024, 4, SECT_4K_PMC) },
- { "pm25lq032", INFO(0x7f9d46, 0, 64 * 1024, 64, SECT_4K) },
+ { "pm25lv512", INFO(0, 0, 32 * 1024, 2, SECT_4K_PMC) },
+ { "pm25lv010", INFO(0, 0, 32 * 1024, 4, SECT_4K_PMC) },
+ { "pm25lq032", INFO(0x7f9d46, 0, 64 * 1024, 64, SECT_4K) },
/* Spansion -- single (large) sector size only, at least
* for the chips listed here (without boot sectors).
*/
- { "s25sl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "s25sl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+ { "s25sl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+ { "s25sl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
{ "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, 0) },
- { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "s25fl512s", INFO(0x010220, 0x4d00, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) },
+ { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512,
+ SPI_NOR_4B_OPCODES | SPI_NOR_QUAD_READ), PARAMS(spansion), CLK_MHZ_2X(104) },
+ { "s25fl512s", INFO(0x010220, 0x4d00, 256 * 1024, 256,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+ { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) },
+ { "s25fl127s/129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256,
+ SECT_4K | SPI_NOR_QUAD_READ), PARAMS(spansion), CLK_MHZ_2X(108) },
{ "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) },
{ "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) },
- { "s25fl128s", INFO6(0x012018, 0x4d0180, 64 * 1024, 256, SECT_4K | SPI_NOR_QUAD_READ) },
- { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "s25sl004a", INFO(0x010212, 0, 64 * 1024, 8, 0) },
- { "s25sl008a", INFO(0x010213, 0, 64 * 1024, 16, 0) },
- { "s25sl016a", INFO(0x010214, 0, 64 * 1024, 32, 0) },
- { "s25sl032a", INFO(0x010215, 0, 64 * 1024, 64, 0) },
- { "s25sl064a", INFO(0x010216, 0, 64 * 1024, 128, 0) },
- { "s25fl004k", INFO(0xef4013, 0, 64 * 1024, 8, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "s25fl008k", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "s25fl016k", INFO(0xef4015, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "s25fl064k", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) },
- { "s25fl116k", INFO(0x014015, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "s25fl132k", INFO(0x014016, 0, 64 * 1024, 64, SECT_4K) },
- { "s25fl164k", INFO(0x014017, 0, 64 * 1024, 128, SECT_4K) },
- { "s25fl204k", INFO(0x014013, 0, 64 * 1024, 8, SECT_4K | SPI_NOR_DUAL_READ) },
+ { "s25fl128s", INFO6(0x012018, 0x4d0180, 64 * 1024, 256, SECT_4K
+ | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+ { "s25fl128lagmfi010z", INFO(0x016018, 0, 64 * 1024, 256,
+ SPI_NOR_QUAD_READ)},
+ { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+ { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256,
+ SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+ { "s25sl004a", INFO(0x010212, 0, 64 * 1024, 8, 0) },
+ { "s25sl008a", INFO(0x010213, 0, 64 * 1024, 16, 0) },
+ { "s25sl016a", INFO(0x010214, 0, 64 * 1024, 32, 0) },
+ { "s25sl032a", INFO(0x010215, 0, 64 * 1024, 64, 0) },
+ { "s25sl064a", INFO(0x010216, 0, 64 * 1024, 128, 0) },
+ { "s25fl004k", INFO(0xef4013, 0, 64 * 1024, 8, SECT_4K
+ | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+ { "s25fl008k", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K
+ | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+ { "w25Q16jv-iq/s25fl016k", INFO(0xef4015, 0, 64 * 1024, 32,
+ SECT_4K | SPI_NOR_QUAD_READ), PARAMS(winbond), CLK_MHZ_2X(84) },
+ /* { "s25fl064k", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K
+ | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, */
+ { "s25fl132k", INFO(0x014016, 0, 64 * 1024, 64, SECT_4K) },
+ { "s25fl164k", INFO(0x014017, 0, 64 * 1024, 128, SECT_4K) },
+ { "s25fl204k", INFO(0x014013, 0, 64 * 1024, 8, SECT_4K
+ | SPI_NOR_DUAL_READ) },
/* SST -- large erase sizes are "overlays", "sectors" are 4K */
{ "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) },
@@ -972,43 +1500,101 @@
{ "m25px64", INFO(0x207117, 0, 64 * 1024, 128, 0) },
{ "m25px80", INFO(0x207114, 0, 64 * 1024, 16, 0) },
- /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */
+ /* Winbond 3.3V-- w25x "blocks" are 64K, "sectors" are 4KiB */
{ "w25x05", INFO(0xef3010, 0, 64 * 1024, 1, SECT_4K) },
{ "w25x10", INFO(0xef3011, 0, 64 * 1024, 2, SECT_4K) },
{ "w25x20", INFO(0xef3012, 0, 64 * 1024, 4, SECT_4K) },
{ "w25x40", INFO(0xef3013, 0, 64 * 1024, 8, SECT_4K) },
{ "w25x80", INFO(0xef3014, 0, 64 * 1024, 16, SECT_4K) },
- { "w25x16", INFO(0xef3015, 0, 64 * 1024, 32, SECT_4K) },
+ { "w25x16", INFO(0xef3015, 0, 64 * 1024, 32, SECT_4K
+ | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
{ "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) },
- { "w25q32", INFO(0xef4016, 0, 64 * 1024, 64, SECT_4K) },
- {
- "w25q32dw", INFO(0xef6016, 0, 64 * 1024, 64,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
- SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
- },
+ { "w25q32", INFO(0xef4016, 0, 64 * 1024, 64,
+ SECT_4K | SPI_NOR_QUAD_READ), PARAMS(winbond), CLK_MHZ_2X(80) },
{ "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) },
- { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) },
- {
- "w25q64dw", INFO(0xef6017, 0, 64 * 1024, 128,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
- SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
- },
- {
- "w25q128fw", INFO(0xef6018, 0, 64 * 1024, 256,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
- SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
- },
+ { "w25q64fv(spi)/w25q64jv_iq", INFO(0xef4017, 0, 64 * 1024, 128,
+ SECT_4K | SPI_NOR_QUAD_READ), PARAMS(winbond), CLK_MHZ_2X(80) },
{ "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K) },
{ "w25q80bl", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) },
- { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) },
- { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, SECT_4K) },
+ { "w25q128(b/f)v", INFO(0xef4018, 0, 64 * 1024, 256,
+ SECT_4K | SPI_NOR_QUAD_READ), PARAMS(winbond), CLK_MHZ_2X(104) },
+ { "w25q128jv_im", INFO(0xef7018, 0, 64 * 1024, 256,
+ SECT_4K | SPI_NOR_QUAD_READ), PARAMS(winbond), CLK_MHZ_2X(80) },
+#ifdef CONFIG_AUTOMOTIVE_GRADE
+ { "w25q256(f/j)v", INFO(0xef4019, 0, 64 * 1024, 512,
+ SECT_4K | SPI_NOR_QUAD_READ), PARAMS(winbond), CLK_MHZ_2X(80) },
+#else
+ { "w25q256(f/j)v", INFO(0xef4019, 0, 64 * 1024, 512,
+ SECT_4K | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES), PARAMS(winbond), CLK_MHZ_2X(80) },
+#endif
+ /* Winbond 1.8V */
+ { "w25q32fw", INFO(0xef6016, 0, 64 * 1024, 64,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB), PARAMS(winbond), CLK_MHZ_2X(80) },
+ { "w25q64dw", INFO(0xef6017, 0, 64 * 1024, 128,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB), PARAMS(winbond), CLK_MHZ_2X(80) },
+ { "w25q128fw", INFO(0xef6018, 0, 64 * 1024, 256,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB), PARAMS(winbond), CLK_MHZ_2X(80) },
+ { "w25q256jw-im", INFO(0xef8019, 0, 64 * 1024, 512,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_4B_OPCODES),
+ PARAMS(winbond), CLK_MHZ_2X(80) },
+ { "w25q256jw-iq", INFO(0xef6019, 0, 64 * 1024, 512,
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_4B_OPCODES),
+ PARAMS(winbond), CLK_MHZ_2X(133) },
/* Catalyst / On Semiconductor -- non-JEDEC */
- { "cat25c11", CAT25_INFO( 16, 8, 16, 1, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
- { "cat25c03", CAT25_INFO( 32, 8, 16, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
- { "cat25c09", CAT25_INFO( 128, 8, 32, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
- { "cat25c17", CAT25_INFO( 256, 8, 32, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
- { "cat25128", CAT25_INFO(2048, 8, 64, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
+ { "cat25c11", CAT25_INFO(16, 8, 16, 1, SPI_NOR_NO_ERASE
+ | SPI_NOR_NO_FR) },
+ { "cat25c03", CAT25_INFO(32, 8, 16, 2, SPI_NOR_NO_ERASE
+ | SPI_NOR_NO_FR) },
+ { "cat25c09", CAT25_INFO(28, 8, 32, 2, SPI_NOR_NO_ERASE
+ | SPI_NOR_NO_FR) },
+ { "cat25c17", CAT25_INFO(256, 8, 32, 2, SPI_NOR_NO_ERASE
+ | SPI_NOR_NO_FR) },
+ { "cat25128", CAT25_INFO(2048, 8, 64, 2, SPI_NOR_NO_ERASE
+ | SPI_NOR_NO_FR) },
+ /* Paragon 3.3V */
+ { "pn25f16s", INFO(0xe04015, 0, 64 * 1024, 32,
+ SPI_NOR_QUAD_READ), PARAMS(paragon), CLK_MHZ_2X(80) },
+ { "pn25f32s", INFO(0xe04016, 0, 64 * 1024, 64,
+ SPI_NOR_QUAD_READ), PARAMS(paragon), CLK_MHZ_2X(80) },
+
+ /* XTX */
+ { "xt25f16bssigu", INFO(0x0b4015, 0, 64 * 1024, 32,
+ SPI_NOR_QUAD_READ), PARAMS(xtx), CLK_MHZ_2X(120) },
+
+ { "xt25f32bssigu-s", INFO(0x0b4016, 0, 64 * 1024, 64,
+ SPI_NOR_QUAD_READ), PARAMS(xtx), CLK_MHZ_2X(120) },
+
+ { "xt25f128b", INFO(0x0b4018, 0, 64 * 1024, 256,
+ SPI_NOR_QUAD_READ), PARAMS(xtx), CLK_MHZ_2X(70) },
+
+ { "xt25f64b", INFO(0x0b4017, 0, 64 * 1024, 128,
+ SPI_NOR_QUAD_READ), PARAMS(xtx), CLK_MHZ_2X(70) },
+
+ /*puya 3.3V */
+ {"p25q128h", INFO(0x856018, 0, 64 * 1024, 256,
+ SPI_NOR_QUAD_READ), PARAMS(puya), CLK_MHZ_2X(104) },
+
+ /* FM 3.3v */
+ { "FM25Q64-SOB-T-G",INFO(0xa14017, 0, 64 * 1024, 128,
+ SPI_NOR_QUAD_READ), PARAMS(spansion), CLK_MHZ_2X(80) },
+ { "FM25Q128-SOB-T-G",INFO(0xa14018, 0, 64 * 1024, 256,
+ SPI_NOR_QUAD_READ), PARAMS(spansion), CLK_MHZ_2X(80) },
+
+ /* HUAHONG 3.3v */
+ { "H25S64",INFO(0x684017, 0, 64 * 1024, 128,
+ SPI_NOR_QUAD_READ), PARAMS(spansion), CLK_MHZ_2X(80) },
+
+ { "H25S128",INFO(0x684018, 0, 64 * 1024, 256,
+ SPI_NOR_QUAD_READ), PARAMS(spansion), CLK_MHZ_2X(80) },
+
+ { "ZB25VQ64A",INFO(0x5e4017, 0, 64 * 1024, 128,
+ SPI_NOR_QUAD_READ), PARAMS(spansion), CLK_MHZ_2X(104) },
{ },
};
@@ -1024,6 +1610,11 @@
return ERR_PTR(tmp);
}
+ if ((id[0] == 0xff) || (id[0] == 0x00)) {
+ dev_err(nor->dev, "unrecognized Manufacturer ID\n");
+ return ERR_PTR(-ENODEV);
+ }
+
for (tmp = 0; tmp < ARRAY_SIZE(spi_nor_ids) - 1; tmp++) {
info = &spi_nor_ids[tmp];
if (info->id_len) {
@@ -1036,6 +1627,36 @@
return ERR_PTR(-ENODEV);
}
+static int puya_quad_enable(struct spi_nor *nor)
+{
+ int ret;
+ u8 val;
+
+ ret = read_cr(nor);
+ if ((unsigned int)ret & CR_QUAD_EN_SPAN)
+ return 0;
+
+ val = (((unsigned int)ret & 0xff) | CR_QUAD_EN_SPAN);
+ write_enable(nor);
+
+ ret = write_sr2(nor, val);
+ if (ret < 0) {
+ dev_err(nor->dev,
+ "error while writing status register-2\n");
+ return -EINVAL;
+ }
+
+ if (spi_nor_wait_till_ready(nor))
+ return 1;
+
+ /* read back and check it */
+ ret = read_cr(nor);
+ if ((unsigned int)ret & CR_QUAD_EN_SPAN)
+ return 0;
+ else
+ return 1;
+}
+
static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, u_char *buf)
{
@@ -1167,14 +1788,22 @@
ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_WRITE);
if (ret)
return ret;
+#ifdef CONFIG_GOKE_SPI_BLOCK_PROTECT
+ if (nor->level && (to < nor->end_addr)) {
+ dev_err(nor->dev, "Error: The DMA write area was locked\n");
+ return -EINVAL;
+ }
+#endif
for (i = 0; i < len; ) {
ssize_t written;
page_offset = (to + i) & (nor->page_size - 1);
+#ifndef CONFIG_SPI_GOKE_SFC
WARN_ONCE(page_offset,
"Writing at offset %zu into a NOR page. Writing partial pages may decrease reliability and increase wear of NOR flash.",
page_offset);
+#endif
/* the size of data remaining on the first page */
page_remain = min_t(size_t,
nor->page_size - page_offset, len - i);
@@ -1211,15 +1840,22 @@
val = read_sr(nor);
if (val < 0)
return val;
+
+ if ((unsigned int)val & SR_QUAD_EN_MX)
+ return 0;
+
+ /* Update the Quad Enable bit. */
+ dev_dbg(nor->dev, "setting Macronix Quad Enable (non-volatile) bit\n");
+
write_enable(nor);
- write_sr(nor, val | SR_QUAD_EN_MX);
+ write_sr(nor, (u8)val | SR_QUAD_EN_MX);
if (spi_nor_wait_till_ready(nor))
return 1;
ret = read_sr(nor);
- if (!(ret > 0 && (ret & SR_QUAD_EN_MX))) {
+ if (!(ret > 0 && ((unsigned int)ret & SR_QUAD_EN_MX))) {
dev_err(nor->dev, "Macronix Quad bit not set\n");
return -EINVAL;
}
@@ -1227,6 +1863,41 @@
return 0;
}
+static int xtx_quad_enable(struct spi_nor *nor)
+{
+ u8 ret, val_h,val_l;
+ /* read SR high 8bit*/
+ val_h = read_cr(nor);
+ if (val_h < 0)
+ return val_h;
+
+ if (val_h & SR_QUAD_EN_XTX)
+ return 0;
+
+ /* Update the Quad Enable bit. */
+ dev_dbg(nor->dev, "setting xtx Quad Enable (non-volatile) bit\n");
+
+ write_enable(nor);
+
+ /* read SR low 8bit*/
+ val_l = read_sr(nor);
+
+ /* write SR */
+ nor->cmd_buf[0] = val_l;
+ nor->cmd_buf[1] = val_h;
+ nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 2);
+
+ if (spi_nor_wait_till_ready(nor))
+ return 1;
+
+ ret = read_cr(nor);
+ if (!(ret > 0 && (ret & SR_QUAD_EN_XTX))) {
+ dev_err(nor->dev, "xtx Quad bit not set\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
/*
* Write status Register and configuration register with 2 bytes
* The first byte will be written to the status register, while the
@@ -1243,29 +1914,168 @@
static int spansion_quad_enable(struct spi_nor *nor)
{
- int ret;
- int quad_en = CR_QUAD_EN_SPAN << 8;
+ unsigned int ret;
+ u16 val;
+
+ ret = read_cr(nor);
+ if (ret & CR_QUAD_EN_SPAN)
+ return 0;
+
+ /* Update the Quad Enable bit. */
+ dev_dbg(nor->dev, "setting Quad Enable (non-volatile) bit\n");
+
+ val = ((ret & 0xff) | CR_QUAD_EN_SPAN) << 8;
+
+ ret = read_sr(nor);
+ val |= (ret & 0xff);
+
+ write_enable(nor);
+
+ ret = write_sr_cr(nor, val);
+ if (ret < 0) {
+ dev_err(nor->dev,
+ "error while writing configuration register\n");
+ return -EINVAL;
+ }
+
+ if (spi_nor_wait_till_ready(nor))
+ return 1;
+
+ /* read back and check it */
+ ret = read_cr(nor);
+ if (!(ret > 0 && (ret & CR_QUAD_EN_SPAN))) {
+ dev_err(nor->dev, "Spansion Quad bit not set\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int issi_quad_enable(struct spi_nor *nor)
+{
+ unsigned int ret;
+ u16 val;
+
+ ret = read_sr(nor);
+ if (ret & QUAD_EN_ISSI)
+ return 0;
+
+ /* Update the Quad Enable bit. */
+ dev_dbg(nor->dev, "setting Quad Enable (non-volatile) bit\n");
+
+ val = ((ret & 0xff) | QUAD_EN_ISSI);
write_enable(nor);
- ret = write_sr_cr(nor, quad_en);
+ ret = write_sr(nor, val);
if (ret < 0) {
dev_err(nor->dev,
"error while writing configuration register\n");
return -EINVAL;
}
+ if (issi_spi_nor_wait_till_ready(nor))
+ return 1;
+
+ /* read back and check it */
+ ret = read_sr(nor);
+ if (!(ret > 0 && (ret & QUAD_EN_ISSI))) {
+ dev_err(nor->dev, "ISSI Quad bit not set\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int micron_quad_enable(struct spi_nor *nor)
+{
+ int ret;
+ u8 val;
+
+ ret = nor->read_reg(nor, SPINOR_OP_RD_EVCR, &val, 1);
+ if (ret < 0) {
+ dev_err(nor->dev, "error %d reading EVCR\n", ret);
+ return ret;
+ }
+
+ write_enable(nor);
+
+ /* set EVCR, enable quad I/O */
+ nor->cmd_buf[0] = val & ~EVCR_QUAD_EN_MICRON;
+ ret = nor->write_reg(nor, SPINOR_OP_WD_EVCR, nor->cmd_buf, 1);
+ if (ret < 0) {
+ dev_err(nor->dev, "error while writing EVCR register\n");
+ return ret;
+ }
+
ret = spi_nor_wait_till_ready(nor);
- if (ret) {
+ if (ret)
+ return ret;
+
+ /* read EVCR and check it */
+ ret = nor->read_reg(nor, SPINOR_OP_RD_EVCR, &val, 1);
+ if (ret < 0) {
+ dev_err(nor->dev, "error %d reading EVCR\n", ret);
+ return ret;
+ }
+ if (val & EVCR_QUAD_EN_MICRON) {
+ dev_err(nor->dev, "Micron EVCR Quad bit not clear\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int gd_quad_enable(struct spi_nor *nor)
+{
+ int ret;
+ u16 val;
+
+ /* First, Quad Enable for 16-Pin GD flash, use WRSR[01h] cmd */
+ ret = read_cr(nor);
+ val = (((unsigned int)ret & 0xff) | CR_QUAD_EN_SPAN) << 8;
+
+ ret = read_sr(nor);
+ val |= ((unsigned int)ret & 0xff);
+
+ write_enable(nor);
+
+ ret = write_sr_cr(nor, val);
+ if (ret < 0) {
dev_err(nor->dev,
- "timeout while writing configuration register\n");
+ "error while writing config and status register\n");
+ return -EINVAL;
+ }
+
+ if (spi_nor_wait_till_ready(nor))
+ return 1;
+
+ /* read back and check it */
+ ret = read_cr(nor);
+ if ((unsigned int)ret & CR_QUAD_EN_SPAN)
+ return 0;
+
+ /* Second, Quad Enable for 8-Pin GD flash, use WRCR[31h] cmd */
+ ret = read_sr(nor);
+ if (!((unsigned int)ret & SR_WEL))
+ write_enable(nor);
+
+ ret = read_cr(nor);
+ nor->cmd_buf[0] = ((unsigned int)ret & 0xff) | CR_QUAD_EN_SPAN;
+
+ ret = nor->write_reg(nor, SPINOR_OP_WRCR, nor->cmd_buf, 1);
+ if (ret < 0) {
+ dev_err(nor->dev, "error while writing config register\n");
return ret;
}
+ if (spi_nor_wait_till_ready(nor))
+ return 1;
+
/* read back and check it */
ret = read_cr(nor);
- if (!(ret > 0 && (ret & CR_QUAD_EN_SPAN))) {
- dev_err(nor->dev, "Spansion Quad bit not set\n");
+ if (!(ret > 0 && ((unsigned int)ret & CR_QUAD_EN_SPAN))) {
+ dev_err(nor->dev, "GigaDevice Quad bit not set\n");
return -EINVAL;
}
@@ -1277,6 +2087,7 @@
int status;
switch (JEDEC_MFR(info)) {
+ case SNOR_MFR_ESMT:
case SNOR_MFR_MACRONIX:
status = macronix_quad_enable(nor);
if (status) {
@@ -1285,7 +2096,40 @@
}
return status;
case SNOR_MFR_MICRON:
- return 0;
+ status = micron_quad_enable(nor);
+ if (status) {
+ dev_err(nor->dev, "Micron quad-read not enabled\n");
+ return -EINVAL;
+ }
+ return status;
+ case SNOR_MFR_GD:
+ status = gd_quad_enable(nor);
+ if (status) {
+ dev_err(nor->dev, "GD quad-read not enabled\n");
+ return -EINVAL;
+ }
+ return status;
+ case SNOR_MFR_XTX:
+ status = xtx_quad_enable(nor);
+ if (status) {
+ dev_err(nor->dev, "xtx quad-read not enabled\n");
+ return -EINVAL;
+ }
+ return status;
+ case SNOR_MFR_PUYA:
+ status = puya_quad_enable(nor);
+ if (status) {
+ dev_err(nor->dev, "puya quad-read not enabled\n");
+ return -EINVAL;
+ }
+ return status;
+ case SNOR_MFR_ISSI:
+ status = issi_quad_enable(nor);
+ if (status) {
+ dev_err(nor->dev, "puya quad-read not enabled\n");
+ return -EINVAL;
+ }
+ return status;
default:
status = spansion_quad_enable(nor);
if (status) {
@@ -1307,8 +2151,375 @@
return 0;
}
-int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode)
+#ifdef CONFIG_GOKE_SPI_BLOCK_PROTECT
+static void spi_lock_update_address(struct spi_nor *nor, const struct flash_info *info)
+{
+ unsigned int lock_level_max, sectorsize, chipsize;
+
+ if (!nor->level) {
+ nor->end_addr = 0;
+ dev_warn(nor->dev, "all blocks is unlocked.\n");
+ return;
+ }
+
+ sectorsize = info->sector_size;
+ chipsize = sectorsize * info->n_sectors;
+ lock_level_max = nor->lock_level_max;
+
+ switch (JEDEC_MFR(info)) {
+ case SNOR_MFR_MACRONIX:
+ if (chipsize == _2M) {
+ if ((nor->level != lock_level_max)
+ && (nor->level != 1))
+ nor->end_addr = chipsize - (sectorsize <<
+ (lock_level_max - nor->level - 1));
+ else
+ nor->end_addr = chipsize;
+ return;
+ }
+
+ if (chipsize != _8M)
+ break;
+ case SNOR_MFR_ESMT:
+ /* this case is for ESMT and MXIC 8M devices */
+ if (nor->level != lock_level_max)
+ nor->end_addr = chipsize - (sectorsize
+ << (lock_level_max - nor->level));
+ else
+ nor->end_addr = chipsize;
+ return;
+ case SNOR_MFR_EON:
+ if (nor->level != lock_level_max)
+ nor->end_addr = chipsize - (sectorsize
+ << (nor->level - 1));
+ else
+ nor->end_addr = chipsize;
+ return;
+ default:
+ break;
+ }
+
+ /* general case */
+ nor->end_addr = chipsize >> (lock_level_max - nor->level);
+}
+
+static unsigned char bsp_bp_to_level(struct spi_nor *nor,
+ const struct flash_info *info, unsigned int bp_num)
+{
+ int ret;
+ unsigned char val;
+ unsigned char level;
+ unsigned int chipsize;
+
+ ret = spi_nor_wait_till_ready(nor);
+ BUG_ON(ret);
+
+ ret = nor->read_reg(nor, SPINOR_OP_RDSR, &val, 1);
+ if (ret < 0) {
+ dev_err(nor->dev, "error %d reading SR\n", ret);
+ return ret;
+ }
+
+ if (bp_num == BP_NUM_3)
+ level = (val & SPI_NOR_SR_BP_MASK_3) >> SPI_NOR_SR_BP0_SHIFT;
+ else
+ level = (val & SPI_NOR_SR_BP_MASK_4) >> SPI_NOR_SR_BP0_SHIFT;
+
+ dev_dbg(nor->dev, "the current level[%d]\n", level);
+
+ if (bp_num == BP_NUM_4) {
+ nor->lock_level_max = LOCK_LEVEL_MAX(bp_num) - 5;
+ chipsize = info->sector_size * info->n_sectors;
+ if ((JEDEC_MFR(info) == SNOR_MFR_MACRONIX)
+ && (chipsize == _16M))
+ nor->lock_level_max--;
+ } else
+ nor->lock_level_max = LOCK_LEVEL_MAX(bp_num);
+ dev_dbg(nor->dev, "Get the max bp level: [%d]\n",
+ nor->lock_level_max);
+
+ return level;
+}
+
+static void bsp_get_spi_lock_info(struct spi_nor *nor, const struct flash_info *info)
+{
+ unsigned int chipsize;
+ struct device *dev = nor->dev;
+
+ chipsize = info->sector_size * info->n_sectors;
+
+ /* read the BP bit in RDSR to check whether nor is lock or not */
+ switch (JEDEC_MFR(info)) {
+ case SNOR_MFR_GD:
+ case SNOR_MFR_ESMT:
+ case SNOR_MFR_EON:
+ case SNOR_MFR_SPANSION:
+ /* BP bit convert to lock level */
+ nor->level = bsp_bp_to_level(nor, info, BP_NUM_3);
+ break;
+ case SNOR_MFR_WINBOND:
+ /* BP bit convert to lock level */
+ if (chipsize <= _16M)
+ nor->level = bsp_bp_to_level(nor, info, BP_NUM_3);
+ else
+ nor->level = bsp_bp_to_level(nor, info, BP_NUM_4);
+ break;
+ case SNOR_MFR_MACRONIX:
+ /* BP bit convert to lock level */
+ if (chipsize <= _8M)
+ nor->level = bsp_bp_to_level(nor, info, BP_NUM_3);
+ else
+ nor->level = bsp_bp_to_level(nor, info, BP_NUM_4);
+ break;
+ default:
+ goto usage;
+ }
+
+ spi_lock_update_address(nor, info);
+ if (nor->end_addr)
+ dev_info(dev, "Address range [0 => %#x] is locked.\n",
+ nor->end_addr);
+ return;
+usage:
+ dev_err(dev, "The ID: %#x isn't in the BP table,"
+ " Current device can't not protect\n",
+ JEDEC_MFR(info));
+}
+#endif/* CONFIG_GOKE_SPI_BLOCK_PROTECT */
+
+static int spi_nor_midx2proto(int midx, enum spi_nor_protocol *proto)
+{
+ switch (midx) {
+ case SNOR_MIDX_SLOW:
+ case SNOR_MIDX_1_1_1:
+ *proto = SNOR_PROTO_1_1_1;
+ break;
+
+ case SNOR_MIDX_1_1_2:
+ *proto = SNOR_PROTO_1_1_2;
+ break;
+
+ case SNOR_MIDX_1_2_2:
+ *proto = SNOR_PROTO_1_2_2;
+ break;
+ case SNOR_MIDX_1_1_4:
+ *proto = SNOR_PROTO_1_1_4;
+ break;
+
+ case SNOR_MIDX_1_4_4:
+ *proto = SNOR_PROTO_1_4_4;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int spi_nor_sr3_to_reset(struct spi_nor *nor)
{
+ int ret;
+ unsigned char val;
+
+ ret = nor->read_reg(nor, SPINOR_OP_RDSR3, &val, 1);
+ if (ret < 0) {
+ dev_err(nor->dev, "error %d reading Status Reg 3.\n", ret);
+ return ret;
+ }
+
+ if (SPI_NOR_GET_RST(val)) {
+ dev_dbg(nor->dev, "Device has worked on RESET#.\n");
+ return 0;
+ }
+
+ dev_dbg(nor->dev, "Start to enable RESET# function.\n");
+ val = SPI_NOR_SET_RST(val);
+
+ nor->write_reg(nor, SPINOR_OP_WRSR3, &val, 1);
+ if (ret < 0) {
+ dev_err(nor->dev, "error while writing Status Reg 3.\n");
+ return ret;
+ }
+
+ dev_dbg(nor->dev, "Enable RESET# function success.\n");
+
+ return 0;
+}
+
+static int spi_nor_reset_pin_enable(struct spi_nor *nor,
+ const struct flash_info *info)
+{
+ switch (JEDEC_MFR(info)) {
+ case SNOR_MFR_WINBOND:
+ case SNOR_MFR_GD:
+ return spi_nor_sr3_to_reset(nor);
+ default:
+ return 0;
+ }
+}
+
+static int spi_nor_setup(struct spi_nor *nor, const struct flash_info *info,
+ const struct spi_nor_basic_flash_parameter *params,
+ const struct spi_nor_modes *modes)
+{
+ bool enable_quad_io;
+ u32 rd_modes, wr_modes;
+ const struct spi_nor_erase_type *erase_type;
+ const struct spi_nor_read_op *read;
+ int rd_midx, wr_midx, err = 0;
+#ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS
+ int i = 0;
+#endif
+ rd_modes = modes->rd_modes;
+ wr_modes = modes->wr_modes;
+
+ /* Setup read operation. */
+ rd_midx = fls(params->rd_modes & rd_modes) - 1;
+ if (spi_nor_midx2proto(rd_midx, &nor->read_proto)) {
+ dev_err(nor->dev, "invalid (fast) read\n");
+ return -EINVAL;
+ }
+ read = &params->reads[rd_midx];
+ nor->read_opcode = read->opcode;
+ nor->read_dummy = read->num_mode_clocks + read->num_wait_states;
+
+ /* Set page program op code and protocol. */
+ wr_midx = fls(params->wr_modes & wr_modes) - 1;
+ if (spi_nor_midx2proto(wr_midx, &nor->write_proto)) {
+ dev_err(nor->dev, "invalid page program\n");
+ return -EINVAL;
+ }
+ nor->program_opcode = params->page_programs[wr_midx];
+
+ /* Set sector erase op code and size. */
+ erase_type = &params->erase_types[0];
+#ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS
+ for (i = 1; i < SNOR_MAX_ERASE_TYPES; ++i)
+ if (params->erase_types[i].size == 0x0c)
+ erase_type = &params->erase_types[i];
+#endif
+ nor->erase_opcode = erase_type->opcode;
+ nor->mtd.erasesize = (1 << erase_type->size);
+
+ enable_quad_io = (SNOR_PROTO_DATA_FROM_PROTO(nor->read_proto) == 4 ||
+ SNOR_PROTO_DATA_FROM_PROTO(nor->write_proto) == 4);
+
+ /* Enable Quad I/O if needed. */
+ if (enable_quad_io && params->enable_quad_io) {
+ err = params->enable_quad_io(nor);
+ if (err) {
+ dev_err(nor->dev,
+ "failed to enable the Quad I/O mode\n");
+ return err;
+ }
+ }
+
+ /*
+ * Fix erase protocol if needed, read and write protocols should
+ * already be valid.
+ */
+ nor->erase_proto = SNOR_PROTO_1_1_1;
+
+ dev_dbg(nor->dev,
+ "(Fast) Read: opcode=%02Xh, protocol=%03x, mode=%u, wait=%u\n",
+ nor->read_opcode, nor->read_proto,
+ read->num_mode_clocks, read->num_wait_states);
+ dev_dbg(nor->dev,
+ "Page Program: opcode=%02Xh, protocol=%03x\n",
+ nor->program_opcode, nor->write_proto);
+ dev_dbg(nor->dev,
+ "Sector Erase: opcode=%02Xh, protocol=%03x, sector size=%zu\n",
+ nor->erase_opcode, nor->erase_proto, (size_t)nor->mtd.erasesize);
+
+ return 0;
+}
+
+static int spi_nor_config(struct spi_nor *nor, const struct flash_info *info,
+ const struct spi_nor_basic_flash_parameter *params,
+ struct spi_nor_modes *modes)
+{
+ int ret;
+ unsigned char cval,val;
+
+ if (JEDEC_MFR(info) == SNOR_MFR_MACRONIX){
+ val = read_sr(nor);
+ if (val < 0)
+ return val;
+
+ /* read Configuration Register for macronix's spi nor flash */
+ ret = nor->read_reg(nor, SPINOR_OP_RDSR3, &cval, 1);
+ if(ret < 0){
+ dev_err(nor->dev, "error %d reading config Reg.\n", ret);
+ return ret;
+ }
+
+ /* check the bit[6:7] whether is set in uboot when use DTR mode;if it was set and clear it. */
+ /* pay attention to sequence of issuing WRSR instruction */
+ if (cval & CR_DUMMY_CYCLE){
+ write_enable(nor);
+ nor->cmd_buf[0]=val;
+ nor->cmd_buf[1]=(cval & (~CR_DUMMY_CYCLE));
+ ret = nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 2);
+ }
+ }
+
+ if (params) {
+ ret = spi_nor_setup(nor, info, params, modes);
+ if (ret)
+ return ret;
+ } else if (modes->rd_modes & SNOR_MODE_1_1_4 &&
+ info->flags & SPI_NOR_QUAD_READ) {
+ /*
+ * This branch is spcially for some devices which can
+ * not be stated by params, but only SPI_NOR_QUAD_READ,
+ * it just supports the protocol 1_1_4.
+ */
+ if (spi_nor_wait_till_ready(nor))
+ return 1;
+
+ ret = set_quad_mode(nor, info);
+ if (ret) {
+ dev_err(nor->dev, "quad mode not supported\n");
+ return ret;
+ }
+ nor->read_proto = SNOR_PROTO_1_1_4;
+ nor->read_opcode = SPINOR_OP_READ_1_1_4;
+ nor->read_dummy = 8;
+ } else if (modes->rd_modes & SNOR_MODE_1_1_2 &&
+ info->flags & SPI_NOR_DUAL_READ) {
+ /*
+ * This branch is spcially for some devices which can
+ * not be stated by params, but only SPI_NOR_DUAL_READ,
+ * it just supports the protocol 1_1_2.
+ */
+ nor->read_proto = SNOR_PROTO_1_1_2;
+ nor->read_opcode = SPINOR_OP_READ_1_1_2;
+ nor->read_dummy = 8;
+ } else {
+ if (modes->rd_modes & SNOR_MODE_1_1_1) {
+ nor->read_opcode = SPINOR_OP_READ_FAST;
+ nor->read_dummy = 8;
+ } else {
+ nor->read_opcode = SPINOR_OP_READ;
+ nor->read_dummy = 0;
+ }
+ }
+
+ if (!(modes->rd_modes & (SNOR_MODE_1_1_4 | SNOR_MODE_1_4_4))) {
+ ret = spi_nor_reset_pin_enable(nor, info);
+ if (ret < 0) {
+ dev_err(nor->dev, "Enable RESET# fail.\n");
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+int spi_nor_scan(struct spi_nor *nor, const char *name,
+ struct spi_nor_modes *modes)
+{
+ const struct spi_nor_basic_flash_parameter *params = NULL;
const struct flash_info *info = NULL;
struct device *dev = nor->dev;
struct mtd_info *mtd = &nor->mtd;
@@ -1320,11 +2531,19 @@
if (ret)
return ret;
+ /* Reset SPI protocol for all commands */
+ nor->erase_proto = SNOR_PROTO_1_1_1;
+ nor->read_proto = SNOR_PROTO_1_1_1;
+ nor->write_proto = SNOR_PROTO_1_1_1;
+
if (name)
info = spi_nor_match_id(name);
/* Try to auto-detect if chip name wasn't specified or not found */
- if (!info)
+ if (!info) {
+ dev_info(dev, "SPI Nor ID Table Version %s\n", SPI_NOR_IDS_VER);
info = spi_nor_read_id(nor);
+ }
+
if (IS_ERR_OR_NULL(info))
return -ENOENT;
@@ -1351,9 +2570,15 @@
info = jinfo;
}
}
+ if (info->params)
+ params = info->params;
mutex_init(&nor->lock);
+#ifdef CONFIG_GOKE_SPI_BLOCK_PROTECT
+ /* NOR block protection support */
+ bsp_get_spi_lock_info(nor, info);
+#else
/*
* Atmel, SST, Intel/Numonyx, and others serial NOR tend to power up
* with the software protection bits set
@@ -1367,6 +2592,7 @@
write_sr(nor, 0);
spi_nor_wait_till_ready(nor);
}
+#endif
if (!mtd->name)
mtd->name = dev_name(dev);
@@ -1380,7 +2606,8 @@
/* NOR protection support for STmicro/Micron chips and similar */
if (JEDEC_MFR(info) == SNOR_MFR_MICRON ||
- info->flags & SPI_NOR_HAS_LOCK) {
+ JEDEC_MFR(info) == SNOR_MFR_WINBOND ||
+ info->flags & SPI_NOR_HAS_LOCK) {
nor->flash_lock = stm_lock;
nor->flash_unlock = stm_unlock;
nor->flash_is_locked = stm_is_locked;
@@ -1428,92 +2655,61 @@
if (np) {
/* If we were instantiated by DT, use it */
if (of_property_read_bool(np, "m25p,fast-read"))
- nor->flash_read = SPI_NOR_FAST;
+ modes->rd_modes |= SNOR_MODE_1_1_1;
else
- nor->flash_read = SPI_NOR_NORMAL;
+ modes->rd_modes &= ~SNOR_MODE_1_1_1;
} else {
/* If we weren't instantiated by DT, default to fast-read */
- nor->flash_read = SPI_NOR_FAST;
+ modes->rd_modes |= SNOR_MODE_1_1_1;
}
/* Some devices cannot do fast-read, no matter what DT tells us */
if (info->flags & SPI_NOR_NO_FR)
- nor->flash_read = SPI_NOR_NORMAL;
-
- /* Quad/Dual-read mode takes precedence over fast/normal */
- if (mode == SPI_NOR_QUAD && info->flags & SPI_NOR_QUAD_READ) {
- ret = set_quad_mode(nor, info);
- if (ret) {
- dev_err(dev, "quad mode not supported\n");
- return ret;
- }
- nor->flash_read = SPI_NOR_QUAD;
- } else if (mode == SPI_NOR_DUAL && info->flags & SPI_NOR_DUAL_READ) {
- nor->flash_read = SPI_NOR_DUAL;
- }
-
- /* Default commands */
- switch (nor->flash_read) {
- case SPI_NOR_QUAD:
- nor->read_opcode = SPINOR_OP_READ_1_1_4;
- break;
- case SPI_NOR_DUAL:
- nor->read_opcode = SPINOR_OP_READ_1_1_2;
- break;
- case SPI_NOR_FAST:
- nor->read_opcode = SPINOR_OP_READ_FAST;
- break;
- case SPI_NOR_NORMAL:
- nor->read_opcode = SPINOR_OP_READ;
- break;
- default:
- dev_err(dev, "No Read opcode defined\n");
- return -EINVAL;
- }
+ modes->rd_modes &= ~SNOR_MODE_1_1_1;
nor->program_opcode = SPINOR_OP_PP;
+ /*
+ * Configure the SPI memory:
+ * - select op codes for (Fast) Read, Page Program and Sector Erase.
+ * - set the number of dummy cycles (mode cycles + wait states).
+ * - set the SPI protocols for register and memory accesses.
+ * - set the Quad Enable bit if needed (required by SPI x-y-4 protos).
+ */
+ ret = spi_nor_config(nor, info, params, modes);
+ if (ret)
+ return ret;
+
if (info->addr_width)
nor->addr_width = info->addr_width;
else if (mtd->size > 0x1000000) {
/* enable 4-byte addressing if the device exceeds 16MiB */
nor->addr_width = 4;
- if (JEDEC_MFR(info) == SNOR_MFR_SPANSION) {
- /* Dedicated 4-byte command set */
- switch (nor->flash_read) {
- case SPI_NOR_QUAD:
- nor->read_opcode = SPINOR_OP_READ4_1_1_4;
- break;
- case SPI_NOR_DUAL:
- nor->read_opcode = SPINOR_OP_READ4_1_1_2;
- break;
- case SPI_NOR_FAST:
- nor->read_opcode = SPINOR_OP_READ4_FAST;
- break;
- case SPI_NOR_NORMAL:
- nor->read_opcode = SPINOR_OP_READ4;
- break;
- }
- nor->program_opcode = SPINOR_OP_PP_4B;
- /* No small sector erase for 4-byte command set */
- nor->erase_opcode = SPINOR_OP_SE_4B;
- mtd->erasesize = info->sector_size;
- } else
+ if (JEDEC_MFR(info) == SNOR_MFR_SPANSION ||
+ info->flags & SPI_NOR_4B_OPCODES)
+ spi_nor_set_4byte_opcodes(nor, info);
+ else
set_4byte(nor, info, 1);
} else {
nor->addr_width = 3;
}
+ /* choose the suitable clockrate */
+ if ((info->flags & (SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)) /* device supports dual or quad */
+ && (modes->rd_modes & (~SNOR_MODE_SLOW)) /* controller supports fast mode */
+ && info->clkrate)
+ nor->clkrate = info->clkrate;
+ else
+ nor->clkrate = 24000000;
+
if (nor->addr_width > SPI_NOR_MAX_ADDR_WIDTH) {
dev_err(dev, "address width is too large: %u\n",
nor->addr_width);
return -EINVAL;
}
- nor->read_dummy = spi_nor_read_dummy_cycles(nor);
-
- dev_info(dev, "%s (%lld Kbytes)\n", info->name,
- (long long)mtd->size >> 10);
+ dev_info(dev, "%s (Chipsize %lld Mbytes, Blocksize %uKiB)\n",
+ info->name, (long long)mtd->size >> 20, mtd->erasesize / 1024);
dev_dbg(dev,
"mtd .name = %s, .size = 0x%llx (%lldMiB), "
@@ -1547,6 +2743,64 @@
return NULL;
}
+/******************************************************************************/
+void spi_nor_driver_shutdown(struct spi_nor *nor)
+{
+ /* disable 4-byte addressing if the device exceeds 16MiB */
+ if (nor->addr_width == 4) {
+ const struct flash_info *info = NULL;
+
+ info = spi_nor_read_id(nor);
+ set_4byte(nor, info, 0);
+ }
+ return;
+}
+
+#ifdef CONFIG_PM
+/******************************************************************************/
+int spi_nor_suspend(struct spi_nor *nor, pm_message_t state)
+{
+ return spi_nor_wait_till_ready(nor);
+}
+
+/******************************************************************************/
+int spi_nor_resume(struct spi_nor *nor)
+{
+ int ret;
+ const struct flash_info *info = NULL;
+ const struct spi_nor_basic_flash_parameter *params = NULL;
+ struct spi_nor_modes modes = {
+ .rd_modes = SNOR_MODE_SLOW,
+ .wr_modes = SNOR_MODE_1_1_1,
+ };
+
+ modes.rd_modes |= SNOR_MODE_1_1_1
+ | SNOR_MODE_1_1_2
+ | SNOR_MODE_1_2_2;
+#ifndef CONFIG_CLOSE_SPI_8PIN_4IO
+ modes.rd_modes |= SNOR_MODE_1_1_4 | SNOR_MODE_1_4_4;
+ modes.wr_modes |= SNOR_MODE_1_1_4 | SNOR_MODE_1_4_4;
+#endif
+
+ if (!info)
+ info = spi_nor_read_id(nor);
+
+ /* Quad mode takes precedence over fast/normal */
+ if (info->params)
+ params = info->params;
+
+ ret = spi_nor_config(nor, info, params, &modes);
+ if (ret)
+ return ret;
+
+ /* enable 4-byte addressing if the device exceeds 16MiB */
+ if (nor->addr_width == 4 && JEDEC_MFR(info) != SNOR_MFR_SPANSION)
+ set_4byte(nor, info, 1);
+
+ return 0;
+}
+#endif /* End of CONFIG_PM */
+
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Huang Shijie <shijie8@gmail.com>");
MODULE_AUTHOR("Mike Lavender");
diff -urN linux-4.9.37/drivers/net/ethernet/goke/femac/femac.c linux-4.9.y/drivers/net/ethernet/goke/femac/femac.c
--- linux-4.9.37/drivers/net/ethernet/goke/femac/femac.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/net/ethernet/goke/femac/femac.c 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,1560 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#include <linux/circ_buf.h>
+#include <linux/clk.h>
+#include <linux/etherdevice.h>
+#include <linux/if_ether.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of_mdio.h>
+#include <linux/of_net.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+#include <linux/tcp.h>
+#include <net/protocol.h>
+
+#include "phy_fix.h"
+#include "femac.h"
+#include "util.h"
+
+static void femac_irq_enable(const struct femac_priv *priv, u32 irqs)
+{
+ u32 val;
+
+ val = readl(priv->glb_base + GLB_IRQ_ENA);
+ writel(val | irqs, priv->glb_base + GLB_IRQ_ENA);
+}
+
+static void femac_irq_disable(const struct femac_priv *priv, u32 irqs)
+{
+ u32 val;
+
+ val = readl(priv->glb_base + GLB_IRQ_ENA);
+ writel(val & (~irqs), priv->glb_base + GLB_IRQ_ENA);
+}
+
+#ifdef CONFIG_FEPHY_OPT
+static u32 highflag = 0;
+static u32 lowflag = 0;
+static void femac_trim_phy(struct phy_device *phy_dev, u32 val)
+{
+ u32 val1;
+ /* 32 pieces of data */
+ int table[32] = {0x11, 0x10, 0x10, 0xf, 0xe, 0xd, 0xd, 0xc,
+ 0xb, 0xa, 0xa, 0x9, 0x8, 0x7, 0x7, 0x6,
+ 0x5, 0x5, 0x4, 0x3, 0x2, 0x2, 0x1, 0x0,
+ 0x3f, 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a
+ };
+
+ phy_write(phy_dev, MII_EXPMA, FEPHY_TRIM_CACHE);
+ phy_write(phy_dev, MII_EXPMD, val);
+ val &= 0x1f;
+ val1 = table[val];
+ phy_write(phy_dev, MII_EXPMA, FEPHY_TRIM_VALUE);
+ val = phy_read(phy_dev, MII_EXPMD);
+ val = (val1 << 2) | (val & 0x3); /* shift left 2 bits */
+ phy_write(phy_dev, MII_EXPMA, FEPHY_TRIM_VALUE);
+ phy_write(phy_dev, MII_EXPMD, val);
+}
+
+static void femac_trim(struct net_device *dev)
+{
+ struct phy_device *phy_dev = NULL;
+ int temp;
+ u32 val;
+
+ phy_dev = dev->phydev;
+ if (phy_dev == NULL) {
+ pr_err("get phy device failed \n");
+ return;
+ }
+
+ phy_write(phy_dev, MII_EXPMA, FEPHY_TRIM_CACHE);
+ val = phy_read(phy_dev, MII_EXPMD);
+ temp = regval_to_temp(val);
+ if ((temp > HIGH_TEMP) && (highflag == 0)) {
+ highflag = 1;
+ if ((val & 0x1f) > 1)
+ val = (val & 0xe0) | ((val & 0x1f) - 1);
+ else
+ return;
+ femac_trim_phy(phy_dev, val);
+ }
+ if ((temp < NORMAL_TEMP1) && (highflag == 1)) {
+ highflag = 0;
+ if ((val & 0x1f) < 0x1f)
+ val = (val & 0xe0) | ((val & 0x1f) + 1);
+ else
+ return;
+ femac_trim_phy(phy_dev, val);
+ }
+ if ((temp > NORMAL_TEMP2) && (lowflag == 0)) {
+ lowflag = 1;
+ if ((val & 0x1f) > 1)
+ val = (val & 0xe0) | ((val & 0x1f) - 1);
+ else
+ return;
+ femac_trim_phy(phy_dev, val);
+ }
+ if ((temp < LOW_TEMP) && (lowflag == 1)) {
+ lowflag = 0;
+ if ((val & 0x1f) < 0x1f)
+ val = (val & 0xe0) | ((val & 0x1f) + 1);
+ else
+ return;
+ femac_trim_phy(phy_dev, val);
+ }
+}
+
+static void femac_watchdog(struct work_struct *work)
+{
+ struct delayed_work *dwork = to_delayed_work(work);
+ struct femac_priv *priv = container_of(dwork, struct femac_priv, watchdog_queue);
+ void __iomem *sys_reg_addr;
+ struct net_device *dev = NULL;
+ u32 val;
+
+ dev = priv->ndev;
+ if (dev == NULL) {
+ pr_err("get net device failed \n");
+ return;
+ }
+
+ sys_reg_addr = (void __iomem *)ioremap_nocache(SYS_REG_ADDR, 0x100);
+ if (!sys_reg_addr) {
+ pr_err("iomap failed \n");
+ return;
+ }
+ val = readl(sys_reg_addr + MISC_CTRL45);
+ if ((val >> 30) != 0x3) { /* bit[30 31] */
+ val |= TSENSOR_EN;
+ writel(val, sys_reg_addr + MISC_CTRL45);
+ mdelay(10); /* wait 10ms */
+ }
+ val = readl(sys_reg_addr + MISC_CTRL47) & TSENSOR_RESULT0;
+ /* high 16bit */
+ val += (readl(sys_reg_addr + MISC_CTRL47) & TSENSOR_RESULT1) >> 16;
+ val += readl(sys_reg_addr + MISC_CTRL48) & TSENSOR_RESULT2;
+ /* high 16bit */
+ val += (readl(sys_reg_addr + MISC_CTRL48) & TSENSOR_RESULT3) >> 16;
+ val = val / 4; /* average value of the 4 values */
+ if (val < LOW_TEM_VALUE || val > HIGH_TEM_VALUE) {
+ goto out;
+ }
+ femac_trim(dev);
+out:
+ iounmap(sys_reg_addr);
+ schedule_delayed_work(&priv->watchdog_queue, FEPHY_OPT_TIMER);
+}
+#endif
+
+static void femac_tx_sg_dma_unmap(const struct femac_priv *priv,
+ const struct sk_buff *skb, unsigned int pos)
+{
+ struct tx_desc *desc_cur;
+ dma_addr_t addr;
+ u32 len;
+ int i;
+
+ desc_cur = priv->tx_ring.desc + pos;
+
+ addr = desc_cur->linear_addr;
+ len = desc_cur->linear_len;
+ dma_unmap_single(priv->dev, addr, len, DMA_TO_DEVICE);
+
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+ addr = desc_cur->frags[i].addr;
+ len = desc_cur->frags[i].size;
+ dma_unmap_page(priv->dev, addr, len, DMA_TO_DEVICE);
+ }
+}
+
+static void femac_tx_dma_unmap(const struct femac_priv *priv,
+ const struct sk_buff *skb, unsigned int pos)
+{
+ if (!(skb_is_gso(skb) || skb_shinfo(skb)->nr_frags)) {
+ dma_addr_t dma_addr;
+
+ dma_addr = priv->txq.dma_phys[pos];
+ dma_unmap_single(priv->dev, dma_addr, skb->len, DMA_TO_DEVICE);
+ } else {
+ femac_tx_sg_dma_unmap(priv, skb, pos);
+ }
+}
+
+static void femac_xmit_reclaim(struct net_device *dev)
+{
+ struct sk_buff *skb = NULL;
+ struct femac_priv *priv = netdev_priv(dev);
+ struct femac_queue *txq = &priv->txq;
+ unsigned int bytes_compl = 0;
+ unsigned int pkts_compl = 0;
+ u32 val;
+
+ netif_tx_lock(dev);
+
+ val = readl(priv->port_base + ADDRQ_STAT) & TX_CNT_INUSE_MASK;
+ while (val < priv->tx_fifo_used_cnt) {
+ skb = txq->skb[txq->tail];
+ if (unlikely(skb == NULL)) {
+ netdev_err(dev, "xmitq_cnt_inuse=%d, tx_fifo_used=%d\n",
+ val, priv->tx_fifo_used_cnt);
+ break;
+ }
+ femac_tx_dma_unmap(priv, skb, txq->tail);
+ pkts_compl++;
+ bytes_compl += skb->len;
+ dev_kfree_skb_any(skb);
+
+ priv->tx_fifo_used_cnt--;
+
+ val = readl(priv->port_base + ADDRQ_STAT) & TX_CNT_INUSE_MASK;
+ txq->skb[txq->tail] = NULL;
+ txq->tail = (txq->tail + 1) % txq->num;
+ }
+
+ netdev_completed_queue(dev, pkts_compl, bytes_compl);
+
+ if (unlikely(netif_queue_stopped(dev)) && pkts_compl)
+ netif_wake_queue(dev);
+
+ netif_tx_unlock(dev);
+}
+
+static void femac_get_tso_err_info(const struct femac_priv *priv)
+{
+ unsigned int reg_addr, reg_tx_info, reg_tx_err;
+ unsigned int sg_index;
+ struct tx_desc *sg_desc = NULL;
+ int *sg_word = NULL;
+ int i;
+
+ reg_addr = readl(priv->port_base + TSO_DBG_ADDR);
+ reg_tx_info = readl(priv->port_base + TSO_DBG_TX_INFO);
+ reg_tx_err = readl(priv->port_base + TSO_DBG_TX_ERR);
+
+ WARN(1, "tx err=0x%x, tx_info=0x%x, addr=0x%x\n",
+ reg_tx_err, reg_tx_info, reg_addr);
+
+ sg_index = (reg_addr - priv->tx_ring.dma_phys) / sizeof(struct tx_desc);
+ sg_desc = priv->tx_ring.desc + sg_index;
+ sg_word = (int *)sg_desc;
+ for (i = 0; i < sizeof(struct tx_desc) / sizeof(int); i++)
+ pr_err("%s,%d: sg_desc word[%d]=0x%x\n",
+ __func__, __LINE__, i, sg_word[i]);
+
+ /* restart MAC to transmit next packet */
+ femac_irq_disable(priv, INT_TX_ERR);
+ /*
+ * If we need allow netcard transmit packet again.
+ * we should readl TSO_DBG_STATE and enable irq.
+ */
+}
+
+static netdev_tx_t femac_net_xmit(struct sk_buff *skb,
+ struct net_device *dev);
+
+static netdev_tx_t femac_sw_gso(struct sk_buff *skb,
+ struct net_device *dev)
+{
+ struct sk_buff *segs = NULL;
+ struct sk_buff *curr_skb = NULL;
+ netdev_features_t features = dev->features;
+
+ features &= ~(NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
+ NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_UFO);
+ segs = skb_gso_segment(skb, features);
+ if (IS_ERR_OR_NULL(segs)) {
+ goto drop;
+ }
+
+ do {
+ curr_skb = segs;
+ segs = segs->next;
+ curr_skb->next = NULL;
+ if (femac_net_xmit(curr_skb, dev)) {
+ dev_kfree_skb(curr_skb);
+ while (segs != NULL) {
+ curr_skb = segs;
+ segs = segs->next;
+ curr_skb->next = NULL;
+ dev_kfree_skb_any(curr_skb);
+ }
+ goto drop;
+ }
+ } while (segs != NULL);
+
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+
+drop:
+ dev_kfree_skb_any(skb);
+ dev->stats.tx_dropped++;
+ return NETDEV_TX_OK;
+}
+
+static int femac_fill_sg_desc(const struct femac_priv *priv,
+ const struct sk_buff *skb, unsigned int pos)
+{
+ struct tx_desc *desc_cur;
+ dma_addr_t addr;
+ int ret;
+ int i;
+
+ desc_cur = priv->tx_ring.desc + pos;
+
+ desc_cur->ipv6_id = ntohl(skb_shinfo(skb)->ip6_frag_id);
+
+ desc_cur->total_len = skb->len;
+ addr = dma_map_single(priv->dev, skb->data, skb_headlen(skb),
+ DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(priv->dev, addr))) {
+ return -EINVAL;
+ }
+ desc_cur->linear_addr = addr;
+ desc_cur->linear_len = skb_headlen(skb);
+
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+ skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+ int len = frag->size;
+
+ addr = skb_frag_dma_map(priv->dev, frag, 0, len, DMA_TO_DEVICE);
+ ret = dma_mapping_error(priv->dev, addr);
+ if (unlikely(ret)) {
+ return -EINVAL;
+ }
+ desc_cur->frags[i].addr = addr;
+ desc_cur->frags[i].size = len;
+ }
+
+ return 0;
+}
+
+static void femac_adjust_link(struct net_device *dev)
+{
+ struct femac_priv *priv = netdev_priv(dev);
+ struct phy_device *phy = dev->phydev;
+ u32 status = 0;
+
+ if (phy->link)
+ status |= MAC_PORTSET_LINKED;
+ if (phy->duplex == DUPLEX_FULL)
+ status |= MAC_PORTSET_DUPLEX_FULL;
+ if (phy->speed == SPEED_100)
+ status |= MAC_PORTSET_SPEED_100M;
+
+ if ((status != priv->link_status) &&
+ ((status | priv->link_status) & MAC_PORTSET_LINKED)) {
+ writel(status, priv->port_base + MAC_PORTSET);
+ priv->link_status = status;
+ phy_print_status(phy);
+
+ priv->tx_pause_en = phy->pause;
+ femac_set_flow_ctrl(priv);
+ }
+}
+
+static void femac_rx_refill(struct femac_priv *priv)
+{
+ struct femac_queue *rxq = &priv->rxq;
+ struct sk_buff *skb = NULL;
+ u32 pos;
+ u32 len;
+ dma_addr_t addr;
+ u32 alloc_rxbuf_align;
+ int reserve_room;
+
+ pos = rxq->head;
+ while (readl(priv->port_base + ADDRQ_STAT) & BIT_RX_READY) {
+ if (!CIRC_SPACE(pos, rxq->tail, rxq->num)) {
+ break;
+ }
+ if (unlikely(rxq->skb[pos])) {
+ netdev_err(priv->ndev, "err skb[%d]=%p\n",
+ pos, rxq->skb[pos]);
+ break;
+ }
+ len = MAX_FRAME_SIZE + RXBUF_ADDR_ALIGN_SIZE;
+ skb = netdev_alloc_skb_ip_align(priv->ndev, len);
+ if (unlikely(skb == NULL)) {
+ break;
+ }
+
+ alloc_rxbuf_align = ((uintptr_t)skb->data - NET_IP_ALIGN) &
+ (RXBUF_ADDR_ALIGN_SIZE - 1);
+ if (alloc_rxbuf_align) {
+ reserve_room = RXBUF_ADDR_ALIGN_SIZE -
+ alloc_rxbuf_align;
+ len -= reserve_room;
+ skb_reserve(skb, reserve_room);
+ }
+
+ addr = dma_map_single(priv->dev, skb->data, len,
+ DMA_FROM_DEVICE);
+ if (dma_mapping_error(priv->dev, addr)) {
+ dev_kfree_skb_any(skb);
+ break;
+ }
+ rxq->dma_phys[pos] = addr;
+ rxq->skb[pos] = skb;
+ writel(addr, priv->port_base + IQ_ADDR);
+ pos = (pos + 1) % rxq->num;
+ }
+ rxq->head = pos;
+}
+
+#ifdef FEMAC_RX_REFILL_IN_IRQ
+static void femac_recv_queue(struct net_device *dev, struct sk_buff *skb,
+ u32 rx_pkt_info)
+{
+ struct femac_priv *priv = netdev_priv(dev);
+ int hdr_csum_done, hdr_csum_err;
+ int payload_csum_done, payload_csum_err;
+
+ skb->ip_summed = CHECKSUM_NONE;
+ if (dev->features & NETIF_F_RXCSUM) {
+ hdr_csum_done =
+ (rx_pkt_info >> BITS_HEADER_DONE_OFFSET) &
+ BITS_HEADER_DONE_MASK;
+ payload_csum_done =
+ (rx_pkt_info >> BITS_PAYLOAD_DONE_OFFSET) &
+ BITS_PAYLOAD_DONE_MASK;
+ hdr_csum_err =
+ (rx_pkt_info >> BITS_HEADER_ERR_OFFSET) &
+ BITS_HEADER_ERR_MASK;
+ payload_csum_err =
+ (rx_pkt_info >> BITS_PAYLOAD_ERR_OFFSET) &
+ BITS_PAYLOAD_ERR_MASK;
+
+ if (hdr_csum_done && payload_csum_done) {
+ if (unlikely(hdr_csum_err)) {
+ dev->stats.rx_errors++;
+ dev->stats.rx_crc_errors++;
+ dev_kfree_skb_any(skb);
+ return;
+ } else if (!payload_csum_err) {
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ }
+ }
+ }
+ skb_queue_tail(&priv->rx_head, skb);
+}
+
+static void femac_pre_receive(struct net_device *dev)
+{
+ struct femac_priv *priv = netdev_priv(dev);
+ struct femac_queue *rxq = &priv->rxq;
+ struct sk_buff *skb = NULL;
+ u32 rx_pkt_info, pos, len;
+ unsigned long rxflags;
+
+ spin_lock_irqsave(&priv->rxlock, rxflags);
+ pos = rxq->tail;
+ while (readl(priv->glb_base + GLB_IRQ_RAW) & IRQ_INT_RX_RDY) {
+ rx_pkt_info = readl(priv->port_base + IQFRM_DES);
+ len = rx_pkt_info & RX_FRAME_LEN_MASK;
+ len -= ETH_FCS_LEN;
+
+ /* tell hardware we will deal with this packet */
+ writel(IRQ_INT_RX_RDY, priv->glb_base + GLB_IRQ_RAW);
+
+ skb = rxq->skb[pos];
+ if (unlikely(skb == NULL)) {
+ netdev_err(dev, "rx skb NULL. pos=%d\n", pos);
+ break;
+ }
+ rxq->skb[pos] = NULL;
+
+ dma_unmap_single(priv->dev, rxq->dma_phys[pos], MAX_FRAME_SIZE,
+ DMA_FROM_DEVICE);
+ skb_put(skb, len);
+ if (unlikely(skb->len > MAX_FRAME_SIZE)) {
+ netdev_err(dev, "rcv len err, len = %d\n", skb->len);
+ dev->stats.rx_errors++;
+ dev->stats.rx_length_errors++;
+ dev_kfree_skb_any(skb);
+ goto next;
+ }
+
+ femac_recv_queue(dev, skb, rx_pkt_info);
+next:
+ pos = (pos + 1) % rxq->num;
+ }
+ rxq->tail = pos;
+
+ femac_rx_refill(priv);
+ spin_unlock_irqrestore(&priv->rxlock, rxflags);
+}
+
+static u32 femac_rx(struct net_device *dev, int limit)
+{
+ struct femac_priv *priv = netdev_priv(dev);
+ struct sk_buff *skb = skb_dequeue(&priv->rx_head);
+ u32 rx_pkts_num = 0;
+
+ while (skb != NULL) {
+ skb->protocol = eth_type_trans(skb, dev);
+ napi_gro_receive(&priv->napi, skb);
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += skb->len;
+ rx_pkts_num++;
+
+ if (rx_pkts_num >= limit) {
+ break;
+ }
+ skb = skb_dequeue(&priv->rx_head);
+ }
+
+ return rx_pkts_num;
+}
+#else
+static int femac_recv_queue(struct net_device *dev, struct sk_buff *skb,
+ u32 rx_pkt_info)
+{
+ struct femac_priv *priv = netdev_priv(dev);
+ int hdr_csum_done, hdr_csum_err;
+ int payload_csum_done, payload_csum_err;
+
+ skb->ip_summed = CHECKSUM_NONE;
+ if (dev->features & NETIF_F_RXCSUM) {
+ hdr_csum_done =
+ (rx_pkt_info >> BITS_HEADER_DONE_OFFSET) &
+ BITS_HEADER_DONE_MASK;
+ payload_csum_done =
+ (rx_pkt_info >> BITS_PAYLOAD_DONE_OFFSET) &
+ BITS_PAYLOAD_DONE_MASK;
+ hdr_csum_err =
+ (rx_pkt_info >> BITS_HEADER_ERR_OFFSET) &
+ BITS_HEADER_ERR_MASK;
+ payload_csum_err =
+ (rx_pkt_info >> BITS_PAYLOAD_ERR_OFFSET) &
+ BITS_PAYLOAD_ERR_MASK;
+
+ if (hdr_csum_done && payload_csum_done) {
+ if (unlikely(hdr_csum_err)) {
+ dev->stats.rx_errors++;
+ dev->stats.rx_crc_errors++;
+ dev_kfree_skb_any(skb);
+ return -1;
+ } else if (!payload_csum_err) {
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ }
+ }
+ }
+ return 0;
+}
+
+static u32 femac_rx(struct net_device *dev, int limit)
+{
+ struct femac_priv *priv = netdev_priv(dev);
+ struct femac_queue *rxq = &priv->rxq;
+ struct sk_buff *skb;
+ u32 rx_pkt_info, pos, len;
+ u32 rx_pkts_num = 0;
+
+ pos = rxq->tail;
+ while (readl(priv->glb_base + GLB_IRQ_RAW) & IRQ_INT_RX_RDY) {
+ rx_pkt_info = readl(priv->port_base + IQFRM_DES);
+ len = rx_pkt_info & RX_FRAME_LEN_MASK;
+ len -= ETH_FCS_LEN;
+
+ /* tell hardware we will deal with this packet */
+ writel(IRQ_INT_RX_RDY, priv->glb_base + GLB_IRQ_RAW);
+
+ rx_pkts_num++;
+
+ skb = rxq->skb[pos];
+ if (unlikely(!skb)) {
+ netdev_err(dev, "rx skb NULL. pos=%d\n", pos);
+ break;
+ }
+ rxq->skb[pos] = NULL;
+
+ dma_unmap_single(priv->dev, rxq->dma_phys[pos], MAX_FRAME_SIZE,
+ DMA_FROM_DEVICE);
+ skb_put(skb, len);
+ if (unlikely(skb->len > MAX_FRAME_SIZE)) {
+ netdev_err(dev, "rcv len err, len = %d\n", skb->len);
+ dev->stats.rx_errors++;
+ dev->stats.rx_length_errors++;
+ dev_kfree_skb_any(skb);
+ goto next;
+ }
+
+ if (femac_recv_queue(dev, skb, rx_pkt_info) < 0)
+ goto next;
+
+ skb->protocol = eth_type_trans(skb, dev);
+ napi_gro_receive(&priv->napi, skb);
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += len;
+next:
+ pos = (pos + 1) % rxq->num;
+ if (rx_pkts_num >= limit) {
+ break;
+ }
+ }
+ rxq->tail = pos;
+
+ femac_rx_refill(priv);
+
+ return rx_pkts_num;
+}
+#endif
+
+static int femac_poll(struct napi_struct *napi, int budget)
+{
+ struct femac_priv *priv = container_of(napi,
+ struct femac_priv, napi);
+ struct net_device *dev = priv->ndev;
+ int work_done = 0;
+ int task = budget;
+ u32 ints, num;
+
+ do {
+#ifdef FEMAC_RX_REFILL_IN_IRQ
+ femac_pre_receive(dev);
+#endif
+ femac_xmit_reclaim(dev);
+ num = femac_rx(dev, task);
+ work_done += num;
+ task -= num;
+ if (work_done >= budget) {
+ break;
+ }
+
+ ints = readl(priv->glb_base + GLB_IRQ_RAW);
+ writel(ints & DEF_INT_MASK,
+ priv->glb_base + GLB_IRQ_RAW);
+ } while (ints & DEF_INT_MASK);
+
+ if (work_done < budget) {
+ napi_complete(napi);
+ femac_irq_enable(priv, DEF_INT_MASK &
+ (~IRQ_INT_TX_PER_PACKET));
+ }
+
+ return work_done;
+}
+
+static irqreturn_t femac_interrupt(int irq, void *dev_id)
+{
+ u32 ints;
+ struct net_device *dev = (struct net_device *)dev_id;
+ struct femac_priv *priv = netdev_priv(dev);
+
+ ints = readl(priv->glb_base + GLB_IRQ_RAW);
+ if (likely(ints & DEF_INT_MASK)) {
+#ifdef FEMAC_RX_REFILL_IN_IRQ
+ femac_pre_receive(dev);
+#endif
+ writel(ints & DEF_INT_MASK,
+ priv->glb_base + GLB_IRQ_RAW);
+ femac_irq_disable(priv, DEF_INT_MASK);
+ napi_schedule(&priv->napi);
+ }
+
+ if (has_tso_cap(priv->hw_cap) && unlikely(ints & INT_TX_ERR))
+ femac_get_tso_err_info(priv);
+
+ return IRQ_HANDLED;
+}
+
+static int femac_init_tx_descriptor_ring(struct femac_priv *priv)
+{
+ priv->tx_ring.desc = (struct tx_desc *)dma_zalloc_coherent(priv->dev,
+ TXQ_NUM * sizeof(struct tx_desc), &priv->tx_ring.dma_phys, GFP_KERNEL);
+ if (!priv->tx_ring.desc) {
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static void femac_destroy_tx_descriptor_ring(struct femac_priv *priv)
+{
+ if (priv->tx_ring.desc)
+ dma_free_coherent(priv->dev, TXQ_NUM * sizeof(struct tx_desc),
+ priv->tx_ring.desc, priv->tx_ring.dma_phys);
+ priv->tx_ring.desc = NULL;
+}
+
+static int femac_init_queue(struct device *dev,
+ struct femac_queue *queue, unsigned int num)
+{
+ queue->skb = devm_kcalloc(dev, num, sizeof(struct sk_buff *), GFP_KERNEL);
+ if (queue->skb == NULL) {
+ return -ENOMEM;
+ }
+
+ queue->dma_phys = devm_kcalloc(dev, num, sizeof(dma_addr_t), GFP_KERNEL);
+ if (queue->dma_phys == NULL) {
+ return -ENOMEM;
+ }
+
+ queue->num = num;
+ queue->head = 0;
+ queue->tail = 0;
+
+ return 0;
+}
+
+static int femac_init_tx_and_rx_queues(struct femac_priv *priv)
+{
+ int ret;
+
+ ret = femac_init_queue(priv->dev, &priv->txq, TXQ_NUM);
+ if (ret) {
+ return ret;
+ }
+
+ ret = femac_init_queue(priv->dev, &priv->rxq, RXQ_NUM);
+ if (ret) {
+ return ret;
+ }
+
+ priv->tx_fifo_used_cnt = 0;
+
+ return 0;
+}
+
+static void femac_free_skb_rings(struct femac_priv *priv)
+{
+ struct femac_queue *txq = &priv->txq;
+ struct femac_queue *rxq = &priv->rxq;
+ struct sk_buff *skb = NULL;
+ dma_addr_t dma_addr;
+ u32 pos;
+
+ pos = rxq->tail;
+ while (pos != rxq->head) {
+ skb = rxq->skb[pos];
+ if (unlikely(skb == NULL)) {
+ netdev_err(priv->ndev, "NULL rx skb. pos=%d, head=%d\n",
+ pos, rxq->head);
+ pos = (pos + 1) % rxq->num;
+ continue;
+ }
+
+ dma_addr = rxq->dma_phys[pos];
+ dma_unmap_single(priv->dev, dma_addr, MAX_FRAME_SIZE, DMA_FROM_DEVICE);
+
+ dev_kfree_skb_any(skb);
+ rxq->skb[pos] = NULL;
+ pos = (pos + 1) % rxq->num;
+ }
+ rxq->tail = pos;
+
+ pos = txq->tail;
+ while (pos != txq->head) {
+ skb = txq->skb[pos];
+ if (unlikely(skb == NULL)) {
+ netdev_err(priv->ndev, "NULL tx skb. pos=%d, head=%d\n",
+ pos, txq->head);
+ pos = (pos + 1) % txq->num;
+ continue;
+ }
+ femac_tx_dma_unmap(priv, skb, pos);
+ dev_kfree_skb_any(skb);
+ txq->skb[pos] = NULL;
+ pos = (pos + 1) % txq->num;
+ }
+ txq->tail = pos;
+ priv->tx_fifo_used_cnt = 0;
+}
+
+static int femac_set_hw_mac_addr(const struct femac_priv *priv,
+ const unsigned char *mac)
+{
+ u32 reg;
+
+ reg = mac[1] | (mac[0] << 8); /* mac0 is high 8 bits */
+ writel(reg, priv->glb_base + GLB_HOSTMAC_H16);
+ /* addr2 [24 31] addr3 [16 23] addr4 [8 15] addr5 [0 7] */
+ reg = mac[5] | (mac[4] << 8) | (mac[3] << 16) | (mac[2] << 24);
+ writel(reg, priv->glb_base + GLB_HOSTMAC_L32);
+
+ return 0;
+}
+
+static int femac_port_reset(const struct femac_priv *priv)
+{
+ u32 val;
+
+ val = readl(priv->glb_base + GLB_SOFT_RESET);
+ val |= SOFT_RESET_ALL;
+ writel(val, priv->glb_base + GLB_SOFT_RESET);
+
+ usleep_range(500, 800); /* wait 500-800us */
+
+ val &= ~SOFT_RESET_ALL;
+ writel(val, priv->glb_base + GLB_SOFT_RESET);
+
+ return 0;
+}
+
+static int femac_net_open(struct net_device *dev)
+{
+ struct femac_priv *priv = netdev_priv(dev);
+
+ femac_set_hw_mac_addr(priv, dev->dev_addr);
+ /*
+ * clear interrupts will drop the first packet MAC have received,
+ * so do it before refill the rx free skbs.
+ */
+ writel(IRQ_ENA_PORT0_MASK, priv->glb_base + GLB_IRQ_RAW);
+ femac_rx_refill(priv);
+
+ netif_carrier_off(dev);
+ netdev_reset_queue(dev);
+ netif_start_queue(dev);
+ napi_enable(&priv->napi);
+
+ priv->link_status = 0;
+ if (dev->phydev)
+ phy_start(dev->phydev);
+
+ femac_irq_enable(priv, IRQ_ENA_ALL | IRQ_ENA_PORT0 | DEF_INT_MASK);
+ if (has_tso_cap(priv->hw_cap))
+ femac_irq_enable(priv, INT_TX_ERR);
+
+ return 0;
+}
+
+static void femac_port_init(struct femac_priv *priv);
+
+static int femac_net_close(struct net_device *dev)
+{
+ struct femac_priv *priv = netdev_priv(dev);
+
+ femac_irq_disable(priv, IRQ_ENA_PORT0);
+
+ if (dev->phydev)
+ phy_stop(dev->phydev);
+
+ netif_stop_queue(dev);
+ napi_disable(&priv->napi);
+
+ /*
+ * reset MAC port first before free skb rings
+ * to prevent potential risk of use-after-free.
+ */
+ femac_port_reset(priv);
+ femac_port_init(priv);
+
+ priv->tx_pause_en = false;
+ femac_set_flow_ctrl(priv);
+ femac_free_skb_rings(priv);
+#ifdef FEMAC_RX_REFILL_IN_IRQ
+ skb_queue_purge(&priv->rx_head);
+#endif
+
+ return 0;
+}
+
+static bool femac_net_isready(struct net_device *dev)
+{
+ struct femac_priv *priv = netdev_priv(dev);
+ struct femac_queue *txq = &priv->txq;
+ u32 val;
+
+ val = readl(priv->port_base + ADDRQ_STAT);
+ val &= BIT_TX_READY;
+ if (!val) {
+ femac_irq_enable(priv, IRQ_INT_TX_PER_PACKET);
+ dev->stats.tx_dropped++;
+ dev->stats.tx_fifo_errors++;
+ netif_stop_queue(dev);
+ return false;
+ }
+
+ if (unlikely(!CIRC_SPACE(txq->head, txq->tail,
+ txq->num))) {
+ femac_irq_enable(priv, IRQ_INT_TX_PER_PACKET);
+ dev->stats.tx_dropped++;
+ dev->stats.tx_fifo_errors++;
+ netif_stop_queue(dev);
+ return false;
+ }
+
+ return true;
+}
+
+static netdev_tx_t femac_net_xmit(struct sk_buff *skb,
+ struct net_device *dev)
+{
+ struct femac_priv *priv = netdev_priv(dev);
+ struct femac_queue *txq = &priv->txq;
+ dma_addr_t addr;
+ int ret;
+ u32 pkt_info;
+
+ if (!femac_net_isready(dev))
+ return NETDEV_TX_BUSY;
+
+ ret = femac_check_hw_capability(skb);
+ if (unlikely(ret)) {
+ if (ret == -ENOTSUPP)
+ return femac_sw_gso(skb, dev);
+
+ dev_kfree_skb_any(skb);
+ dev->stats.tx_dropped++;
+ return NETDEV_TX_OK;
+ }
+
+ pkt_info = femac_get_pkt_info(skb);
+
+ if (!(skb_is_gso(skb) || skb_shinfo(skb)->nr_frags)) {
+ addr = dma_map_single(priv->dev, skb->data,
+ skb->len, DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(priv->dev, addr))) {
+ dev_kfree_skb_any(skb);
+ dev->stats.tx_dropped++;
+ return NETDEV_TX_OK;
+ }
+ } else {
+ ret = femac_fill_sg_desc(priv, skb, txq->head);
+ if (unlikely(ret)) {
+ dev_kfree_skb_any(skb);
+ dev->stats.tx_dropped++;
+ return NETDEV_TX_OK;
+ }
+
+ addr = priv->tx_ring.dma_phys +
+ txq->head * sizeof(struct tx_desc);
+
+ /* Ensure desc info writen to memory before config hardware */
+ wmb();
+ }
+ txq->dma_phys[txq->head] = addr;
+
+ skb_tx_timestamp(skb);
+
+ txq->skb[txq->head] = skb;
+ txq->head = (txq->head + 1) % txq->num;
+
+ writel(addr, priv->port_base + EQ_ADDR);
+ writel(pkt_info, priv->port_base + EQFRM_LEN);
+
+ priv->tx_fifo_used_cnt++;
+
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += skb->len;
+ netdev_sent_queue(dev, skb->len);
+
+ return NETDEV_TX_OK;
+}
+
+static int femac_set_mac_address(struct net_device *dev, void *p)
+{
+ struct femac_priv *priv = netdev_priv(dev);
+ struct sockaddr *skaddr = p;
+
+ if (!is_valid_ether_addr(skaddr->sa_data)) {
+ return -EADDRNOTAVAIL;
+ }
+
+ memcpy(dev->dev_addr, skaddr->sa_data, dev->addr_len);
+ dev->addr_assign_type &= ~NET_ADDR_RANDOM;
+
+ femac_set_hw_mac_addr(priv, dev->dev_addr);
+
+ return 0;
+}
+
+static void femac_enable_hw_addr_filter(const struct femac_priv *priv,
+ unsigned int reg_n, bool enable)
+{
+ u32 val;
+
+ val = readl(priv->glb_base + glb_mac_h16(reg_n));
+ if (enable) {
+ val |= BIT_MACFLT_ENA;
+ } else {
+ val &= ~BIT_MACFLT_ENA;
+ }
+ writel(val, priv->glb_base + glb_mac_h16(reg_n));
+}
+
+static void femac_set_hw_addr_filter(const struct femac_priv *priv,
+ const unsigned char *addr, unsigned int reg_n)
+{
+ unsigned int high, low;
+ u32 val;
+
+ high = glb_mac_h16(reg_n);
+ low = glb_mac_l32(reg_n);
+ /* addr2 [24 31] addr3 [16 23] addr4 [8 15] addr5 [0 7] */
+ val = (addr[2] << 24) | (addr[3] << 16) | (addr[4] << 8) | addr[5];
+ writel(val, priv->glb_base + low);
+
+ val = readl(priv->glb_base + high);
+ val &= ~MACFLT_HI16_MASK;
+ val |= ((addr[0] << 8) | addr[1]); /* addr0 is high 8 bits */
+ val |= (BIT_MACFLT_ENA | BIT_MACFLT_FW2CPU);
+ writel(val, priv->glb_base + high);
+}
+
+static void femac_set_promisc_mode(const struct femac_priv *priv,
+ bool promisc_mode)
+{
+ u32 val;
+
+ val = readl(priv->glb_base + GLB_FWCTRL);
+ if (promisc_mode) {
+ val |= FWCTRL_FWALL2CPU;
+ } else {
+ val &= ~FWCTRL_FWALL2CPU;
+ }
+ writel(val, priv->glb_base + GLB_FWCTRL);
+}
+
+/* Handle multiple multicast addresses (perfect filtering) */
+static void femac_set_mc_addr_filter(const struct femac_priv *priv)
+{
+ struct net_device *dev = priv->ndev;
+ u32 val;
+
+ val = readl(priv->glb_base + GLB_MACTCTRL);
+ if ((netdev_mc_count(dev) > MAX_MULTICAST_ADDRESSES) ||
+ (dev->flags & IFF_ALLMULTI)) {
+ val |= MACTCTRL_MULTI2CPU;
+ } else {
+ int reg = MAX_UNICAST_ADDRESSES;
+ int i;
+ struct netdev_hw_addr *ha = NULL;
+
+ for (i = reg; i < MAX_MAC_FILTER_NUM; i++)
+ femac_enable_hw_addr_filter(priv, i, false);
+
+ netdev_for_each_mc_addr(ha, dev)
+ {
+ femac_set_hw_addr_filter(priv, ha->addr, reg);
+ reg++;
+ }
+ val &= ~MACTCTRL_MULTI2CPU;
+ }
+ writel(val, priv->glb_base + GLB_MACTCTRL);
+}
+
+/* Handle multiple unicast addresses (perfect filtering) */
+static void femac_set_uc_addr_filter(const struct femac_priv *priv)
+{
+ struct net_device *dev = priv->ndev;
+ u32 val;
+
+ val = readl(priv->glb_base + GLB_MACTCTRL);
+ if (netdev_uc_count(dev) > MAX_UNICAST_ADDRESSES) {
+ val |= MACTCTRL_UNI2CPU;
+ } else {
+ int reg = 0;
+ int i;
+ struct netdev_hw_addr *ha = NULL;
+
+ for (i = reg; i < MAX_UNICAST_ADDRESSES; i++)
+ femac_enable_hw_addr_filter(priv, i, false);
+
+ netdev_for_each_uc_addr(ha, dev)
+ {
+ femac_set_hw_addr_filter(priv, ha->addr, reg);
+ reg++;
+ }
+ val &= ~MACTCTRL_UNI2CPU;
+ }
+ writel(val, priv->glb_base + GLB_MACTCTRL);
+}
+
+static void femac_net_set_rx_mode(struct net_device *dev)
+{
+ struct femac_priv *priv = netdev_priv(dev);
+
+ if (dev->flags & IFF_PROMISC) {
+ femac_set_promisc_mode(priv, true);
+ } else {
+ femac_set_promisc_mode(priv, false);
+ femac_set_mc_addr_filter(priv);
+ femac_set_uc_addr_filter(priv);
+ }
+}
+
+static int femac_net_ioctl(struct net_device *dev,
+ struct ifreq *ifreq, int cmd)
+{
+ if (!netif_running(dev)) {
+ return -EINVAL;
+ }
+
+ if (!dev->phydev) {
+ return -EINVAL;
+ }
+
+ return phy_mii_ioctl(dev->phydev, ifreq, cmd);
+}
+
+static const struct ethtool_ops femac_ethtools_ops = {
+ .get_link = ethtool_op_get_link,
+ .get_link_ksettings = phy_ethtool_get_link_ksettings,
+ .set_link_ksettings = phy_ethtool_set_link_ksettings,
+ .get_pauseparam = femac_get_pauseparam,
+ .set_pauseparam = femac_set_pauseparam,
+ .get_ts_info = ethtool_op_get_ts_info,
+};
+
+static const struct net_device_ops femac_netdev_ops = {
+ .ndo_open = femac_net_open,
+ .ndo_stop = femac_net_close,
+ .ndo_start_xmit = femac_net_xmit,
+ .ndo_do_ioctl = femac_net_ioctl,
+ .ndo_set_mac_address = femac_set_mac_address,
+ .ndo_set_rx_mode = femac_net_set_rx_mode,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_set_features = femac_set_features,
+};
+
+static void femac_verify_flow_ctrl_args(struct femac_priv *priv)
+{
+ if (priv->tx_pause_active_thresh < FC_ACTIVE_MIN ||
+ priv->tx_pause_active_thresh > FC_ACTIVE_MAX)
+ priv->tx_pause_active_thresh = FC_ACTIVE_DEFAULT;
+
+ if (priv->tx_pause_deactive_thresh < FC_DEACTIVE_MIN ||
+ priv->tx_pause_deactive_thresh > FC_DEACTIVE_MAX)
+ priv->tx_pause_deactive_thresh = FC_DEACTIVE_DEFAULT;
+
+ if (priv->tx_pause_active_thresh >= priv->tx_pause_deactive_thresh) {
+ priv->tx_pause_active_thresh = FC_ACTIVE_DEFAULT;
+ priv->tx_pause_deactive_thresh = FC_DEACTIVE_DEFAULT;
+ }
+}
+
+static void femac_core_reset(const struct femac_priv *priv)
+{
+ reset_control_assert(priv->mac_rst);
+ reset_control_deassert(priv->mac_rst);
+}
+
+static void femac_phy_reset(const struct femac_priv *priv)
+{
+ /*
+ * To make sure PHY hardware reset success,
+ * we must keep PHY in deassert state first and
+ * then complete the hardware reset operation
+ */
+ reset_control_deassert(priv->phy_rst);
+ femac_sleep_us(priv->phy_reset_delays[PRE_DELAY]);
+
+ reset_control_assert(priv->phy_rst);
+ /*
+ * delay some time to ensure reset ok,
+ * this depends on PHY hardware feature
+ */
+ femac_sleep_us(priv->phy_reset_delays[PULSE]);
+ reset_control_deassert(priv->phy_rst);
+ /* delay some time to ensure later MDIO access */
+ femac_sleep_us(priv->phy_reset_delays[POST_DELAY]);
+}
+
+static void femac_port_init(struct femac_priv *priv)
+{
+ u32 val;
+
+ /* MAC gets link status info and phy mode by software config */
+ val = MAC_PORTSEL_STAT_CPU;
+ if (priv->ndev->phydev->interface == PHY_INTERFACE_MODE_RMII)
+ val |= MAC_PORTSEL_RMII;
+ writel(val, priv->port_base + MAC_PORTSEL);
+
+ /* clear all interrupt status */
+ writel(IRQ_ENA_PORT0_MASK, priv->glb_base + GLB_IRQ_RAW);
+ femac_irq_disable(priv, IRQ_ENA_PORT0_MASK | IRQ_ENA_PORT0);
+
+ if (has_tso_cap(priv->hw_cap)) {
+ /* enable TSO debug for error handle */
+ val = readl(priv->port_base + TSO_DBG_EN);
+ val |= BITS_TSO_DBG_EN;
+ writel(val, priv->port_base + TSO_DBG_EN);
+ }
+
+ val = readl(priv->glb_base + GLB_FWCTRL);
+ val &= ~(FWCTRL_VLAN_ENABLE | FWCTRL_FWALL2CPU);
+ val |= FWCTRL_FW2CPU_ENA;
+ writel(val, priv->glb_base + GLB_FWCTRL);
+
+ val = readl(priv->glb_base + GLB_MACTCTRL);
+ val |= (MACTCTRL_BROAD2CPU | MACTCTRL_MACT_ENA);
+ writel(val, priv->glb_base + GLB_MACTCTRL);
+
+ val = readl(priv->port_base + MAC_SET);
+ val &= ~MAX_FRAME_SIZE_MASK;
+ val |= MAX_FRAME_SIZE;
+ writel(val, priv->port_base + MAC_SET);
+
+ val = RX_COALESCED_TIMER |
+ (RX_COALESCED_FRAMES << RX_COALESCED_FRAME_OFFSET);
+ writel(val, priv->port_base + RX_COALESCE_SET);
+
+ val = (HW_RX_FIFO_DEPTH << RX_DEPTH_OFFSET) | HW_TX_FIFO_DEPTH;
+ writel(val, priv->port_base + QLEN_SET);
+
+ femac_set_flow_ctrl(priv);
+}
+
+static int femac_drv_res(struct platform_device *pdev,
+ struct femac_priv *priv)
+{
+ struct resource *res = NULL;
+ struct device *dev = &pdev->dev;
+ struct device_node *node = dev->of_node;
+ int ret;
+
+ if (of_device_is_compatible(node, "goke,femac-v2"))
+ priv->hw_cap |= HW_CAP_TSO | HW_CAP_RXCSUM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ priv->port_base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(priv->port_base)) {
+ ret = PTR_ERR(priv->port_base);
+ return ret;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ priv->glb_base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(priv->glb_base)) {
+ ret = PTR_ERR(priv->glb_base);
+ return ret;
+ }
+
+ priv->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(priv->clk)) {
+ dev_err(dev, "failed to get clk\n");
+ ret = -ENODEV;
+ return ret;
+ }
+
+ ret = clk_prepare_enable(priv->clk);
+ if (ret) {
+ dev_err(dev, "failed to enable clk %d\n", ret);
+ return ret;
+ }
+ return 0;
+}
+
+static int femac_drv_mac(struct platform_device *pdev,
+ struct femac_priv *priv)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *node = dev->of_node;
+ const char *mac_addr = NULL;
+ struct net_device *ndev = priv->ndev;
+
+ priv->mac_rst = devm_reset_control_get(dev, "mac");
+ if (IS_ERR(priv->mac_rst))
+ return PTR_ERR(priv->mac_rst);
+
+ femac_core_reset(priv);
+
+ mac_addr = of_get_mac_address(node);
+ if (mac_addr != NULL)
+ ether_addr_copy(ndev->dev_addr, mac_addr);
+ if (!is_valid_ether_addr(ndev->dev_addr)) {
+ eth_hw_addr_random(ndev);
+ dev_warn(dev, "using random MAC address %pM\n",
+ ndev->dev_addr);
+ }
+ return 0;
+}
+
+static struct phy_device* femac_drv_phy(struct platform_device *pdev,
+ struct femac_priv *priv, int *ret)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *node = dev->of_node;
+ struct phy_device* phy = NULL;
+
+ priv->phy_rst = devm_reset_control_get(dev, "phy");
+ if (IS_ERR(priv->phy_rst)) {
+ priv->phy_rst = NULL;
+ } else {
+ *ret = of_property_read_u32_array(node, PHY_RESET_DELAYS_PROPERTY,
+ priv->phy_reset_delays, DELAYS_NUM);
+ if (*ret)
+ return phy;
+ femac_phy_reset(priv);
+ }
+
+ phy_register_fixups();
+
+ phy = of_phy_get_and_connect(priv->ndev, node, femac_adjust_link);
+ if (phy == NULL) {
+ /* check if a fixed-link is defined in device-tree */
+ if (of_phy_is_fixed_link(node)) {
+ *ret = of_phy_register_fixed_link(node);
+ if (*ret < 0) {
+ dev_err(dev, "cannot regitster fixed link phy %d \n", *ret);
+ return phy;
+ }
+ /*
+ * In case of a fixed link phy, the DT node associated
+ * to the phy is the Ethernet MAC DT node.
+ */
+ phy = of_phy_connect(priv->ndev, of_node_get(node), &femac_adjust_link, 0, of_get_phy_mode(node));
+ if (phy == NULL) {
+ dev_err(dev, "fixed_link didnot connect successfully.\n");
+ return phy;
+ }
+ } else {
+ dev_err(dev, "connect to PHY failed!\n");
+ *ret = -ENODEV;
+ return phy;
+ }
+ }
+
+ phy->advertising |= ADVERTISED_Pause;
+ phy->supported |= ADVERTISED_Pause;
+ phy->advertising &= ~(ADVERTISED_1000baseT_Full |
+ ADVERTISED_1000baseT_Half);
+
+ phy_attached_print(phy, "phy_id=0x%.8lx, phy_mode=%s\n",
+ (unsigned long)phy->phy_id, phy_modes(phy->interface));
+
+ return phy;
+}
+
+static void femac_drv_napi(struct platform_device *pdev,
+ struct femac_priv *priv)
+{
+ struct net_device *ndev = priv->ndev;
+
+ ndev->watchdog_timeo = 6 * HZ; /* 6HZ */
+ ndev->priv_flags |= IFF_UNICAST_FLT;
+ ndev->netdev_ops = &femac_netdev_ops;
+ ndev->ethtool_ops = &femac_ethtools_ops;
+ netif_napi_add(ndev, &priv->napi, femac_poll, FEMAC_POLL_WEIGHT);
+
+#ifdef CONFIG_FEPHY_OPT
+ INIT_DELAYED_WORK(&priv->watchdog_queue, femac_watchdog);
+ schedule_delayed_work(&priv->watchdog_queue, FEPHY_OPT_TIMER);
+#endif
+
+ if (has_tso_cap(priv->hw_cap))
+ ndev->hw_features |= NETIF_F_SG |
+ NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
+ NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_UFO;
+
+ if (has_rxcsum_cap(priv->hw_cap))
+ ndev->hw_features |= NETIF_F_RXCSUM;
+ ndev->features |= ndev->hw_features;
+ ndev->vlan_features |= ndev->features;
+
+ device_set_wakeup_capable(priv->dev, true);
+ device_set_wakeup_enable(priv->dev, true);
+
+ priv->tx_pause_en = true;
+ priv->tx_pause_active_thresh = TX_FLOW_CTRL_ACTIVE_THRESHOLD;
+ priv->tx_pause_deactive_thresh = TX_FLOW_CTRL_DEACTIVE_THRESHOLD;
+
+ femac_verify_flow_ctrl_args(priv);
+
+ femac_port_init(priv);
+
+ if (has_rxcsum_cap(priv->hw_cap))
+ femac_enable_rxcsum_drop(priv, true);
+}
+
+static int femac_drv_queues(struct platform_device *pdev,
+ struct femac_priv *priv)
+{
+ int ret;
+
+#ifdef FEMAC_RX_REFILL_IN_IRQ
+ skb_queue_head_init(&priv->rx_head);
+ spin_lock_init(&priv->rxlock);
+#endif
+ ret = femac_init_tx_and_rx_queues(priv);
+ if (ret)
+ return ret;
+
+ if (has_tso_cap(priv->hw_cap)) {
+ ret = femac_init_tx_descriptor_ring(priv);
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
+static int femac_drv_register(struct platform_device *pdev,
+ struct femac_priv *priv)
+{
+ struct device *dev = &pdev->dev;
+ struct net_device *ndev = priv->ndev;
+ int ret;
+
+ ndev->irq = platform_get_irq(pdev, 0);
+ if (ndev->irq <= 0) {
+ dev_err(dev, "No irq resource\n");
+ ret = -ENODEV;
+ return ret;
+ }
+
+ ret = devm_request_irq(dev, ndev->irq, femac_interrupt,
+ IRQF_SHARED, pdev->name, ndev);
+ if (ret) {
+ dev_err(dev, "devm_request_irq %d failed!\n", ndev->irq);
+ return ret;;
+ }
+
+ ret = register_netdev(ndev);
+ if (ret) {
+ dev_err(dev, "register_netdev failed!\n");
+ return ret;;
+ }
+ return 0;
+}
+
+static int femac_drv_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct net_device *ndev = NULL;
+ struct femac_priv *priv = NULL;
+ struct phy_device *phy = NULL;
+ int ret;
+
+ ndev = alloc_etherdev(sizeof(*priv));
+ if (ndev == NULL)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, ndev);
+ SET_NETDEV_DEV(ndev, &pdev->dev);
+
+ priv = netdev_priv(ndev);
+ priv->dev = dev;
+ priv->ndev = ndev;
+
+ ret = femac_drv_res(pdev, priv);
+ if (ret)
+ goto out_free_netdev;
+
+ ret = femac_drv_mac(pdev, priv);
+ if (ret)
+ goto out_disable_clk;
+
+ phy = femac_drv_phy(pdev, priv, &ret);
+ if (phy == NULL)
+ goto out_disable_clk;
+
+ femac_drv_napi(pdev, priv);
+
+ ret = femac_drv_queues(pdev, priv);
+ if (ret)
+ goto out_disconnect_phy;
+
+ ret = femac_drv_register(pdev, priv);
+ if (ret)
+ goto out_destroy_descriptor;
+
+ return ret;
+
+out_destroy_descriptor:
+ if (has_tso_cap(priv->hw_cap))
+ femac_destroy_tx_descriptor_ring(priv);
+out_disconnect_phy:
+ netif_napi_del(&priv->napi);
+ phy_disconnect(phy);
+out_disable_clk:
+ clk_disable_unprepare(priv->clk);
+out_free_netdev:
+ free_netdev(ndev);
+
+ return ret;
+}
+
+static int femac_drv_remove(struct platform_device *pdev)
+{
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct femac_priv *priv = netdev_priv(ndev);
+
+ netif_napi_del(&priv->napi);
+ unregister_netdev(ndev);
+ if (has_tso_cap(priv->hw_cap))
+ femac_destroy_tx_descriptor_ring(priv);
+
+ phy_disconnect(ndev->phydev);
+#ifdef CONFIG_FEPHY_OPT
+ cancel_delayed_work_sync(&priv->watchdog_queue);
+#endif
+ clk_disable_unprepare(priv->clk);
+ free_netdev(ndev);
+
+ phy_unregister_fixups();
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int femac_drv_suspend(struct platform_device *pdev,
+ pm_message_t state)
+{
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct femac_priv *priv = netdev_priv(ndev);
+
+ disable_irq(ndev->irq);
+ if (netif_running(ndev)) {
+ femac_net_close(ndev);
+ netif_device_detach(ndev);
+ }
+
+ clk_disable_unprepare(priv->clk);
+
+ return 0;
+}
+
+static int femac_drv_resume(struct platform_device *pdev)
+{
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct femac_priv *priv = netdev_priv(ndev);
+
+ clk_prepare_enable(priv->clk);
+ if (priv->phy_rst != NULL)
+ femac_phy_reset(priv);
+
+ if (netif_running(ndev)) {
+ femac_port_init(priv);
+ femac_net_open(ndev);
+ netif_device_attach(ndev);
+ }
+ enable_irq(ndev->irq);
+
+ return 0;
+}
+#endif
+
+static const struct of_device_id femac_match[] = {
+ {
+ .compatible = "goke,femac",
+ },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, femac_match);
+
+static struct platform_driver femac_driver = {
+ .driver = {
+ .name = "femac",
+ .of_match_table = femac_match,
+ },
+ .probe = femac_drv_probe,
+ .remove = femac_drv_remove,
+#ifdef CONFIG_PM
+ .suspend = femac_drv_suspend,
+ .resume = femac_drv_resume,
+#endif
+};
+
+module_platform_driver(femac_driver);
+
+MODULE_DESCRIPTION("Goke Fast Ethernet MAC driver");
+MODULE_AUTHOR("Goke");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:femac");
diff -urN linux-4.9.37/drivers/net/ethernet/goke/femac/femac.h linux-4.9.y/drivers/net/ethernet/goke/femac/femac.h
--- linux-4.9.37/drivers/net/ethernet/goke/femac/femac.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/net/ethernet/goke/femac/femac.h 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#ifndef __ETH_GOKE_FEMAC_H__
+#define __ETH_GOKE_FEMAC_H__
+
+/* MAC control register list */
+#define MAC_PORTSEL 0x0200
+#define MAC_PORTSEL_STAT_CPU BIT(0)
+#define MAC_PORTSEL_RMII BIT(1)
+#define MAC_PORTSET 0x0208
+#define MAC_PORTSET_DUPLEX_FULL BIT(0)
+#define MAC_PORTSET_LINKED BIT(1)
+#define MAC_PORTSET_SPEED_100M BIT(2)
+#define MAC_SET 0x0210
+#define MAX_FRAME_SIZE 1600
+#define MAX_FRAME_SIZE_MASK GENMASK(10, 0)
+#define BIT_PAUSE_EN BIT(18)
+#define RX_COALESCE_SET 0x0340
+#define RX_COALESCED_FRAME_OFFSET 24
+#define RX_COALESCED_FRAMES 8
+#define RX_COALESCED_TIMER 0x74
+#define QLEN_SET 0x0344
+#define RX_DEPTH_OFFSET 8
+#define MAX_HW_FIFO_DEPTH 64
+#define HW_TX_FIFO_DEPTH 12
+#define HW_RX_FIFO_DEPTH (MAX_HW_FIFO_DEPTH - HW_TX_FIFO_DEPTH)
+#define FC_LEVEL 0x0348
+#define BITS_FC_ACTIVE_THR_OFFSET 8
+#define FC_DEACTIVE_THR_MASK GENMASK(5, 0)
+#define FC_ACTIVE_THR_MASK GENMASK(13, 8)
+#define BIT_FC_EN BIT(14)
+#define IQFRM_DES 0x0354
+#define RX_FRAME_LEN_MASK GENMASK(11, 0)
+#define BITS_PAYLOAD_ERR_OFFSET 28
+#define BITS_PAYLOAD_ERR_MASK 0x1
+#define BITS_HEADER_ERR_OFFSET 29
+#define BITS_HEADER_ERR_MASK 0x1
+#define BITS_PAYLOAD_DONE_OFFSET 30
+#define BITS_PAYLOAD_DONE_MASK 0x1
+#define BITS_HEADER_DONE_OFFSET 31
+#define BITS_HEADER_DONE_MASK 0x1
+#define IQ_ADDR 0x0358
+#define EQ_ADDR 0x0360
+#define EQFRM_LEN 0x0364
+#define ADDRQ_STAT 0x036C
+#define TX_CNT_INUSE_MASK GENMASK(5, 0)
+#define BIT_TX_READY BIT(24)
+#define BIT_RX_READY BIT(25)
+#define RX_COE_CTRL 0x0380
+#define BIT_COE_IPV6_UDP_ZERO_DROP BIT(13)
+#define BIT_COE_PAYLOAD_DROP BIT(14)
+#define BIT_COE_IPHDR_DROP BIT(15)
+#define COE_ERR_DROP (BIT_COE_IPHDR_DROP | \
+ BIT_COE_PAYLOAD_DROP | \
+ BIT_COE_IPV6_UDP_ZERO_DROP)
+#define TSO_DBG_EN 0x03A4
+#define BITS_TSO_DBG_EN BIT(31)
+#define TSO_DBG_STATE 0x03A8
+#define TSO_DBG_ADDR 0x03AC
+#define TSO_DBG_TX_INFO 0x03B0
+#define TSO_DBG_TX_ERR 0x03B4
+/* global control register list */
+#define GLB_HOSTMAC_L32 0x0000
+#define GLB_HOSTMAC_H16 0x0004
+#define GLB_SOFT_RESET 0x0008
+#define SOFT_RESET_ALL BIT(0)
+#define GLB_FWCTRL 0x0010
+#define FWCTRL_VLAN_ENABLE BIT(0)
+#define FWCTRL_FW2CPU_ENA BIT(5)
+#define FWCTRL_FWALL2CPU BIT(7)
+#define GLB_MACTCTRL 0x0014
+#define MACTCTRL_UNI2CPU BIT(1)
+#define MACTCTRL_MULTI2CPU BIT(3)
+#define MACTCTRL_BROAD2CPU BIT(5)
+#define MACTCTRL_MACT_ENA BIT(7)
+#define GLB_IRQ_STAT 0x0030
+#define GLB_IRQ_ENA 0x0034
+#define IRQ_ENA_PORT0_MASK GENMASK(7, 0)
+#define IRQ_ENA_PORT0 BIT(18)
+#define IRQ_ENA_ALL BIT(19)
+#define GLB_IRQ_RAW 0x0038
+#define IRQ_INT_RX_RDY BIT(0)
+#define IRQ_INT_TX_PER_PACKET BIT(1)
+#define IRQ_INT_TX_FIFO_EMPTY BIT(6)
+#define IRQ_INT_MULTI_RXRDY BIT(7)
+#define INT_TX_ERR BIT(8)
+#define DEF_INT_MASK (IRQ_INT_MULTI_RXRDY | \
+ IRQ_INT_TX_PER_PACKET | \
+ IRQ_INT_TX_FIFO_EMPTY)
+#define GLB_MAC_L32_BASE 0x0100
+#define GLB_MAC_H16_BASE 0x0104
+#define MACFLT_HI16_MASK GENMASK(15, 0)
+#define BIT_MACFLT_ENA BIT(17)
+#define BIT_MACFLT_FW2CPU BIT(21)
+#define glb_mac_h16(reg) (GLB_MAC_H16_BASE + ((reg) * 0x8))
+#define glb_mac_l32(reg) (GLB_MAC_L32_BASE + ((reg) * 0x8))
+#define MAX_MAC_FILTER_NUM 8
+#define MAX_UNICAST_ADDRESSES 2
+#define MAX_MULTICAST_ADDRESSES (MAX_MAC_FILTER_NUM - MAX_UNICAST_ADDRESSES)
+/* software tx and rx queue number, should be power of 2 */
+#define TXQ_NUM 64
+#define RXQ_NUM 128
+#define FEMAC_POLL_WEIGHT 64
+#define HW_CAP_TSO BIT(0)
+#define HW_CAP_RXCSUM BIT(1)
+#define has_tso_cap(hw_cap) ((hw_cap) & HW_CAP_TSO)
+#define has_rxcsum_cap(hw_cap) ((hw_cap) & HW_CAP_RXCSUM)
+#define RXBUF_ADDR_ALIGN_SIZE 64UL
+/* UDP header len is 2 word */
+#define UDP_HDR_LEN 2
+/* IPv6 header len is 10 word */
+#define IPV6_HDR_LEN 10
+#define WORD_TO_BYTE 4
+
+#define BIT_OFFSET_NFRAGS_NUM 11
+#define BIT_OFFSET_PROT_HEADER_LEN 16
+#define BIT_OFFSET_IP_HEADER_LEN 20
+#define BIT_FLAG_SG BIT(26)
+#define BIT_FLAG_TXCSUM BIT(27)
+#define BIT_FLAG_UDP BIT(28)
+#define BIT_FLAG_IPV6 BIT(29)
+#define BIT_FLAG_VLAN BIT(30)
+#define BIT_FLAG_TSO BIT(31)
+
+#define PHY_RESET_DELAYS_PROPERTY "goke,phy-reset-delays-us"
+
+/*
+ * The threshold for activing tx flow ctrl.
+ * When the left amount of receive queue descriptors is below this threshold,
+ * hardware will send pause frame immediately.
+ * We advise this value is set between 1 and 10.
+ * Too bigger is not a good choice.
+ * This value must be smaller than tx flow ctrl deactive threshold.
+ */
+#define TX_FLOW_CTRL_ACTIVE_THRESHOLD 3
+/*
+ * The threshold for deactiving tx flow ctrl.
+ * When the left amount of receive queue descriptors is
+ * above or equal with this threshold,
+ * hardware will exit flow control state.
+ * We advise this value is set between 1 and 10.
+ * Too bigger is not a good choice.
+ * This value must be larger than tx flow ctrl active threshold.
+ */
+#define TX_FLOW_CTRL_DEACTIVE_THRESHOLD 5
+#define FC_ACTIVE_MIN 1
+#define FC_ACTIVE_DEFAULT 3
+#define FC_ACTIVE_MAX 31
+#define FC_DEACTIVE_MIN 1
+#define FC_DEACTIVE_DEFAULT 5
+#define FC_DEACTIVE_MAX 31
+
+#ifdef CONFIG_FEPHY_OPT
+/* FEPHY register list */
+
+#define SYS_REG_ADDR 0x12028000
+#define FEPHY_TRIM_CACHE 0x3022
+#define FEPHY_TRIM_VALUE 0x20a1
+#define LOW_TEM_VALUE 117
+#define HIGH_TEM_VALUE 915
+#define LINK_STATUS 0x4
+#define IS_LINK 0X4
+#define SPEED_STATUS 0x18
+#define SPEED_100M 0x8
+#define LINK_AN_SR 0x11
+#define MISC_CTRL45 0x00B4
+#define MISC_CTRL47 0x00BC
+#define MISC_CTRL48 0x00C0
+#define TSENSOR_RESULT0 0x3ff
+#define TSENSOR_RESULT1 0x3ff0000
+#define TSENSOR_RESULT2 0x3ff
+#define TSENSOR_RESULT3 0x3ff0000
+#define TSENSOR_EN 0xc3200000
+#define HIGH_TEMP 100
+#define NORMAL_TEMP1 90
+#define NORMAL_TEMP2 20
+#define LOW_TEMP 10
+#define TSENSOR_LIMIT 0xfffff
+#define regval_to_temp(val) ((val - 117) * 165 / 798 - 40)
+#define FEPHY_OPT_TIMER (30 * HZ)
+#endif
+
+enum phy_reset_delays {
+ PRE_DELAY,
+ PULSE,
+ POST_DELAY,
+ DELAYS_NUM,
+};
+
+struct femac_queue {
+ struct sk_buff **skb;
+ dma_addr_t *dma_phys;
+ unsigned int num;
+ unsigned int head;
+ unsigned int tail;
+};
+
+struct femac_tx_desc_ring {
+ struct tx_desc *desc;
+ dma_addr_t dma_phys;
+};
+
+#define FEMAC_RX_REFILL_IN_IRQ
+
+struct femac_priv {
+ void __iomem *port_base;
+ void __iomem *glb_base;
+ struct clk *clk;
+ struct reset_control *mac_rst;
+ struct reset_control *phy_rst;
+ u32 phy_reset_delays[DELAYS_NUM];
+ u32 link_status;
+
+#ifdef CONFIG_FEPHY_OPT
+ struct delayed_work watchdog_queue;
+#endif
+ struct device *dev;
+ struct net_device *ndev;
+
+ u32 hw_cap;
+ struct femac_queue txq;
+ struct femac_queue rxq;
+#ifdef FEMAC_RX_REFILL_IN_IRQ
+ struct sk_buff_head rx_head;
+ spinlock_t rxlock;
+#endif
+ struct femac_tx_desc_ring tx_ring;
+ u32 tx_fifo_used_cnt;
+ struct napi_struct napi;
+
+ /* 802.3x flow control */
+ bool tx_pause_en;
+ u32 tx_pause_active_thresh;
+ u32 tx_pause_deactive_thresh;
+};
+
+struct frags_info {
+ /* Word(2*i+2) */
+ u32 addr;
+ /* Word(2*i+3) */
+ u32 size : 16;
+ u32 reserved : 16;
+};
+
+struct tx_desc {
+ /* Word0 */
+ u32 total_len : 17;
+ u32 reserv : 15;
+ /* Word1 */
+ u32 ipv6_id;
+ /* Word2 */
+ u32 linear_addr;
+ /* Word3 */
+ u32 linear_len : 16;
+ u32 reserv3 : 16;
+ /* MAX_SKB_FRAGS is 30 */
+ struct frags_info frags[30];
+};
+
+#endif
diff -urN linux-4.9.37/drivers/net/ethernet/goke/femac/Makefile linux-4.9.y/drivers/net/ethernet/goke/femac/Makefile
--- linux-4.9.37/drivers/net/ethernet/goke/femac/Makefile 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/net/ethernet/goke/femac/Makefile 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,5 @@
+#
+# Makefile for the Fast Ethernet network device drivers.
+#
+
+obj-$(CONFIG_GOKE_FEMAC) += femac.o phy_fix.o util.o
diff -urN linux-4.9.37/drivers/net/ethernet/goke/femac/phy_fix.c linux-4.9.y/drivers/net/ethernet/goke/femac/phy_fix.c
--- linux-4.9.37/drivers/net/ethernet/goke/femac/phy_fix.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/net/ethernet/goke/femac/phy_fix.c 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#include <linux/phy.h>
+#include "phy_fix.h"
+
+static const u32 phy_v2_fix_param[] = {
+#include "phy_v2.h"
+};
+
+static const u32 phy_v1_fix_param[] = {
+#include "phy_v1.h"
+};
+
+static int phy_expanded_write_bulk(struct phy_device *phy_dev,
+ const u32 reg_and_val[], int count)
+{
+ int i, v;
+ u32 reg_addr;
+ u16 val;
+
+ v = phy_read(phy_dev, MII_BMCR);
+ v = (u32)v | BMCR_PDOWN;
+ phy_write(phy_dev, MII_BMCR, v);
+
+ for (i = 0; i < count; i += 2) { /* Process 2 data at a time. */
+ reg_addr = reg_and_val[i];
+ val = (u16)reg_and_val[i + 1];
+ phy_write(phy_dev, MII_EXPMA, reg_addr);
+ phy_write(phy_dev, MII_EXPMD, val);
+ }
+
+ v = phy_read(phy_dev, MII_BMCR);
+ v = (u32)v & (~BMCR_PDOWN);
+ phy_write(phy_dev, MII_BMCR, v);
+
+ return 0;
+}
+
+static int goke_fephy_v272_fix(struct phy_device *phy_dev)
+{
+ int count;
+
+ count = ARRAY_SIZE(phy_v2_fix_param);
+ if (count % 2) /* must be an even number, mod 2 */
+ pr_warn("internal FEPHY fix register count is not right.\n");
+ phy_expanded_write_bulk(phy_dev, phy_v2_fix_param, count);
+
+ return 0;
+}
+
+static int goke_fephy_v115_fix(struct phy_device *phy_dev)
+{
+ int count;
+
+ count = ARRAY_SIZE(phy_v1_fix_param);
+ if (count % 2) /* must be an even number, mod 2 */
+ pr_warn("internal FEPHY fix register count is not right.\n");
+ phy_expanded_write_bulk(phy_dev, phy_v1_fix_param, count);
+
+ return 0;
+}
+
+void phy_register_fixups(void)
+{
+ phy_register_fixup_for_uid(GOKE_PHY_ID_V272,
+ GOKE_PHY_MASK,
+ goke_fephy_v272_fix);
+
+ phy_register_fixup_for_uid(GOKE_PHY_ID_V115,
+ GOKE_PHY_MASK,
+ goke_fephy_v115_fix);
+}
+
+void phy_unregister_fixups(void)
+{
+ phy_unregister_fixup_for_uid(GOKE_PHY_ID_V272,
+ GOKE_PHY_MASK);
+
+ phy_unregister_fixup_for_uid(GOKE_PHY_ID_V115,
+ GOKE_PHY_MASK);
+}
diff -urN linux-4.9.37/drivers/net/ethernet/goke/femac/phy_fix.h linux-4.9.y/drivers/net/ethernet/goke/femac/phy_fix.h
--- linux-4.9.37/drivers/net/ethernet/goke/femac/phy_fix.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/net/ethernet/goke/femac/phy_fix.h 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#ifndef __ETH_PHY_FIX_H__
+#define __ETH_PHY_FIX_H__
+
+#define GOKE_PHY_ID_V272 0x20669901
+#define GOKE_PHY_ID_V115 0x20669903
+#define GOKE_PHY_MASK 0xffffffff
+
+#define MII_EXPMD 0x1d
+#define MII_EXPMA 0x1e
+
+void phy_register_fixups(void);
+void phy_unregister_fixups(void);
+
+#endif
diff -urN linux-4.9.37/drivers/net/ethernet/goke/femac/phy_v1.h linux-4.9.y/drivers/net/ethernet/goke/femac/phy_v1.h
--- linux-4.9.37/drivers/net/ethernet/goke/femac/phy_v1.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/net/ethernet/goke/femac/phy_v1.h 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#ifndef __ETH_PHY_S28V115_2C02_H__
+#define __ETH_PHY__S28V115_2C02_H__
+ 0x33f9, 0xbd, 0x33fa, 0x34, 0x33fb, 0x00,
+ 0x33fc, 0x39, 0x3400, 0x39, 0x3401, 0xCC,
+ 0x3402, 0x2C, 0x3403, 0x02, 0x3404, 0xFD,
+ 0x3405, 0xFF, 0x3406, 0xF0, 0x3407, 0xF6,
+ 0x3408, 0x36, 0x3409, 0x18, 0x340A, 0x26,
+ 0x340B, 0x05, 0x340C, 0xC6, 0x340D, 0x01,
+ 0x340E, 0xF7, 0x340F, 0x36, 0x3410, 0x18,
+ 0x3411, 0xCC, 0x3412, 0x35, 0x3413, 0x9F,
+ 0x3414, 0x1A, 0x3415, 0xB3, 0x3416, 0x00,
+ 0x3417, 0xD2, 0x3418, 0x27, 0x3419, 0x09,
+ 0x341A, 0xFD, 0x341B, 0x00, 0x341C, 0xD2,
+ 0x341D, 0x7F, 0x341E, 0x01, 0x341F, 0xBF,
+ 0x3420, 0x7F, 0x3421, 0x01, 0x3422, 0xB1,
+ 0x3423, 0x39, 0x3424, 0x3C, 0x3425, 0x3C,
+ 0x3426, 0x30, 0x3427, 0xF6, 0x3428, 0x30,
+ 0x3429, 0x55, 0x342A, 0xC0, 0x342B, 0x07,
+ 0x342C, 0x18, 0x342D, 0xFE, 0x342E, 0x30,
+ 0x342F, 0x4C, 0x3430, 0x18, 0x3431, 0x3A,
+ 0x3432, 0x18, 0x3433, 0xE6, 0x3434, 0x00,
+ 0x3435, 0x5C, 0x3436, 0xE7, 0x3437, 0x01,
+ 0x3438, 0xC1, 0x3439, 0x07, 0x343A, 0x23,
+ 0x343B, 0x04, 0x343C, 0xC6, 0x343D, 0x07,
+ 0x343E, 0xE7, 0x343F, 0x01, 0x3440, 0x58,
+ 0x3441, 0x58, 0x3442, 0x58, 0x3443, 0x58,
+ 0x3444, 0x58, 0x3445, 0xE7, 0x3446, 0x00,
+ 0x3447, 0xF6, 0x3448, 0x20, 0x3449, 0x04,
+ 0x344A, 0xC4, 0x344B, 0x1F, 0x344C, 0xEA,
+ 0x344D, 0x00, 0x344E, 0xF7, 0x344F, 0x20,
+ 0x3450, 0x04, 0x3451, 0x38, 0x3452, 0x38,
+ 0x3453, 0x39, 0x3454, 0x3C, 0x3455, 0x37,
+ 0x3456, 0x36, 0x3457, 0x30, 0x3458, 0x1A,
+ 0x3459, 0xEE, 0x345A, 0x00, 0x345B, 0x18,
+ 0x345C, 0xE6, 0x345D, 0x00, 0x345E, 0x26,
+ 0x345F, 0x1C, 0x3460, 0xF6, 0x3461, 0x00,
+ 0x3462, 0x5C, 0x3463, 0xC5, 0x3464, 0x04,
+ 0x3465, 0x27, 0x3466, 0x06, 0x3467, 0xCC,
+ 0x3468, 0x36, 0x3469, 0x12, 0x346A, 0xBD,
+ 0x346B, 0xF0, 0x346C, 0xA5, 0x346D, 0xF6,
+ 0x346E, 0x00, 0x346F, 0x47, 0x3470, 0xC4,
+ 0x3471, 0xF3, 0x3472, 0xF7, 0x3473, 0x00,
+ 0x3474, 0x47, 0x3475, 0xC6, 0x3476, 0x01,
+ 0x3477, 0x1A, 0x3478, 0xEE, 0x3479, 0x00,
+ 0x347A, 0x20, 0x347B, 0x10, 0x347C, 0x5A,
+ 0x347D, 0x26, 0x347E, 0x14, 0x347F, 0xF6,
+ 0x3480, 0x00, 0x3481, 0x46, 0x3482, 0x4F,
+ 0x3483, 0xC4, 0x3484, 0x0C, 0x3485, 0x83,
+ 0x3486, 0x00, 0x3487, 0x08, 0x3488, 0x26,
+ 0x3489, 0x05, 0x348A, 0xC6, 0x348B, 0x02,
+ 0x348C, 0x18, 0x348D, 0xE7, 0x348E, 0x00,
+ 0x348F, 0x5F, 0x3490, 0x38, 0x3491, 0x38,
+ 0x3492, 0x39, 0x3493, 0xF6, 0x3494, 0x00,
+ 0x3495, 0x5C, 0x3496, 0xC5, 0x3497, 0x04,
+ 0x3498, 0x27, 0x3499, 0x06, 0x349A, 0xCC,
+ 0x349B, 0x36, 0x349C, 0x08, 0x349D, 0xBD,
+ 0x349E, 0xF0, 0x349F, 0xA5, 0x34A0, 0xF6,
+ 0x34A1, 0x00, 0x34A2, 0x47, 0x34A3, 0xC4,
+ 0x34A4, 0xF3, 0x34A5, 0xCA, 0x34A6, 0x08,
+ 0x34A7, 0xF7, 0x34A8, 0x00, 0x34A9, 0x47,
+ 0x34AA, 0x18, 0x34AB, 0xFE, 0x34AC, 0x00,
+ 0x34AD, 0xB6, 0x34AE, 0x18, 0x34AF, 0xAD,
+ 0x34B0, 0x00, 0x34B1, 0xBD, 0x34B2, 0x34,
+ 0x34B3, 0x24, 0x34B4, 0xF6, 0x34B5, 0x1E,
+ 0x34B6, 0x05, 0x34B7, 0xC5, 0x34B8, 0x02,
+ 0x34B9, 0x27, 0x34BA, 0x0A, 0x34BB, 0xF6,
+ 0x34BC, 0x1E, 0x34BD, 0x07, 0x34BE, 0xC5,
+ 0x34BF, 0x02, 0x34C0, 0x27, 0x34C1, 0x03,
+ 0x34C2, 0xBD, 0x34C3, 0xC0, 0x34C4, 0x33,
+ 0x34C5, 0xF6, 0x34C6, 0x31, 0x34C7, 0x1F,
+ 0x34C8, 0x37, 0x34C9, 0xC6, 0x34CA, 0x52,
+ 0x34CB, 0xBD, 0x34CC, 0xDC, 0x34CD, 0x53,
+ 0x34CE, 0x31, 0x34CF, 0xF6, 0x34D0, 0x00,
+ 0x34D1, 0x41, 0x34D2, 0xC5, 0x34D3, 0x10,
+ 0x34D4, 0x26, 0x34D5, 0x04, 0x34D6, 0x13,
+ 0x34D7, 0x23, 0x34D8, 0x40, 0x34D9, 0x0D,
+ 0x34DA, 0xBD, 0x34DB, 0x93, 0x34DC, 0xCE,
+ 0x34DD, 0x1A, 0x34DE, 0xEE, 0x34DF, 0x00,
+ 0x34E0, 0x18, 0x34E1, 0x6F, 0x34E2, 0x00,
+ 0x34E3, 0xC6, 0x34E4, 0x04, 0x34E5, 0x20,
+ 0x34E6, 0xA9, 0x34E7, 0x1A, 0x34E8, 0xEE,
+ 0x34E9, 0x00, 0x34EA, 0x18, 0x34EB, 0x6F,
+ 0x34EC, 0x00, 0x34ED, 0xC6, 0x34EE, 0x01,
+ 0x34EF, 0x20, 0x34F0, 0x9F, 0x34F1, 0x3C,
+ 0x34F2, 0x37, 0x34F3, 0x36, 0x34F4, 0x30,
+ 0x34F5, 0x1A, 0x34F6, 0xEE, 0x34F7, 0x00,
+ 0x34F8, 0x18, 0x34F9, 0xE6, 0x34FA, 0x00,
+ 0x34FB, 0x26, 0x34FC, 0x49, 0x34FD, 0xF6,
+ 0x34FE, 0x00, 0x34FF, 0x5C, 0x3500, 0xC5,
+ 0x3501, 0x04, 0x3502, 0x27, 0x3503, 0x06,
+ 0x3504, 0xCC, 0x3505, 0x35, 0x3506, 0xFC,
+ 0x3507, 0xBD, 0x3508, 0xF0, 0x3509, 0xA5,
+ 0x350A, 0xC6, 0x350B, 0x52, 0x350C, 0xBD,
+ 0x350D, 0xDC, 0x350E, 0xF3, 0x350F, 0x5D,
+ 0x3510, 0x27, 0x3511, 0x03, 0x3512, 0xBD,
+ 0x3513, 0xC0, 0x3514, 0x22, 0x3515, 0xF6,
+ 0x3516, 0x00, 0x3517, 0x46, 0x3518, 0xC5,
+ 0x3519, 0x0C, 0x351A, 0x26, 0x351B, 0x0A,
+ 0x351C, 0x1A, 0x351D, 0xEE, 0x351E, 0x00,
+ 0x351F, 0x18, 0x3520, 0x6F, 0x3521, 0x00,
+ 0x3522, 0xC6, 0x3523, 0x07, 0x3524, 0x20,
+ 0x3525, 0x1D, 0x3526, 0xFC, 0x3527, 0x30,
+ 0x3528, 0x0C, 0x3529, 0xBD, 0x352A, 0x93,
+ 0x352B, 0x19, 0x352C, 0xBD, 0x352D, 0x9F,
+ 0x352E, 0x0B, 0x352F, 0xC6, 0x3530, 0x02,
+ 0x3531, 0x37, 0x3532, 0xC6, 0x3533, 0x51,
+ 0x3534, 0xBD, 0x3535, 0xDC, 0x3536, 0x53,
+ 0x3537, 0x31, 0x3538, 0x7F, 0x3539, 0x02,
+ 0x353A, 0x07, 0x353B, 0xC6, 0x353C, 0x02,
+ 0x353D, 0x1A, 0x353E, 0xEE, 0x353F, 0x00,
+ 0x3540, 0x18, 0x3541, 0xE7, 0x3542, 0x00,
+ 0x3543, 0x38, 0x3544, 0x38, 0x3545, 0x39,
+ 0x3546, 0xC6, 0x3547, 0x52, 0x3548, 0xBD,
+ 0x3549, 0xDC, 0x354A, 0xF3, 0x354B, 0x5D,
+ 0x354C, 0x27, 0x354D, 0x03, 0x354E, 0xBD,
+ 0x354F, 0xC0, 0x3550, 0x22, 0x3551, 0xF6,
+ 0x3552, 0x00, 0x3553, 0x46, 0x3554, 0xC5,
+ 0x3555, 0x0C, 0x3556, 0x26, 0x3557, 0x0A,
+ 0x3558, 0x1A, 0x3559, 0xEE, 0x355A, 0x00,
+ 0x355B, 0x18, 0x355C, 0x6F, 0x355D, 0x00,
+ 0x355E, 0xC6, 0x355F, 0x07, 0x3560, 0x20,
+ 0x3561, 0xE1, 0x3562, 0xC6, 0x3563, 0x51,
+ 0x3564, 0xBD, 0x3565, 0xDC, 0x3566, 0xF3,
+ 0x3567, 0x5D, 0x3568, 0x26, 0x3569, 0x04,
+ 0x356A, 0xC6, 0x356B, 0x02, 0x356C, 0x20,
+ 0x356D, 0xD5, 0x356E, 0xF6, 0x356F, 0x00,
+ 0x3570, 0x41, 0x3571, 0xC5, 0x3572, 0x10,
+ 0x3573, 0x26, 0x3574, 0x20, 0x3575, 0xF6,
+ 0x3576, 0x02, 0x3577, 0x07, 0x3578, 0xC1,
+ 0x3579, 0x02, 0x357A, 0x24, 0x357B, 0x19,
+ 0x357C, 0x18, 0x357D, 0xFE, 0x357E, 0x02,
+ 0x357F, 0x08, 0x3580, 0x18, 0x3581, 0xAD,
+ 0x3582, 0x00, 0x3583, 0xF6, 0x3584, 0x02,
+ 0x3585, 0x06, 0x3586, 0x27, 0x3587, 0x0D,
+ 0x3588, 0xC6, 0x3589, 0x02, 0x358A, 0x37,
+ 0x358B, 0xC6, 0x358C, 0x51, 0x358D, 0xBD,
+ 0x358E, 0xDC, 0x358F, 0x53, 0x3590, 0x31,
+ 0x3591, 0xC6, 0x3592, 0x02, 0x3593, 0x20,
+ 0x3594, 0xAE, 0x3595, 0x1A, 0x3596, 0xEE,
+ 0x3597, 0x00, 0x3598, 0x18, 0x3599, 0x6F,
+ 0x359A, 0x00, 0x359B, 0xC6, 0x359C, 0x03,
+ 0x359D, 0x20, 0x359E, 0xA4, 0x359F, 0xF6,
+ 0x35A0, 0x01, 0x35A1, 0xBF, 0x35A2, 0xC1,
+ 0x35A3, 0x08, 0x35A4, 0x24, 0x35A5, 0x55,
+ 0x35A6, 0xBD, 0x35A7, 0xF6, 0x35A8, 0xD3,
+ 0x35A9, 0x35, 0x35AA, 0xBA, 0x35AB, 0x35,
+ 0x35AC, 0xC2, 0x35AD, 0x35, 0x35AE, 0xCA,
+ 0x35AF, 0x35, 0x35B0, 0xD2, 0x35B1, 0x35,
+ 0x35B2, 0xDA, 0x35B3, 0x35, 0x35B4, 0xE2,
+ 0x35B5, 0x35, 0x35B6, 0xEA, 0x35B7, 0x35,
+ 0x35B8, 0xF2, 0x35B9, 0x39, 0x35BA, 0xCC,
+ 0x35BB, 0x01, 0x35BC, 0xB1, 0x35BD, 0xBD,
+ 0x35BE, 0x34, 0x35BF, 0x54, 0x35C0, 0x20,
+ 0x35C1, 0x36, 0x35C2, 0xCC, 0x35C3, 0x01,
+ 0x35C4, 0xB1, 0x35C5, 0xBD, 0x35C6, 0xC1,
+ 0x35C7, 0x52, 0x35C8, 0x20, 0x35C9, 0x2E,
+ 0x35CA, 0xCC, 0x35CB, 0x01, 0x35CC, 0xB1,
+ 0x35CD, 0xBD, 0x35CE, 0x34, 0x35CF, 0xF1,
+ 0x35D0, 0x20, 0x35D1, 0x26, 0x35D2, 0xCC,
+ 0x35D3, 0x01, 0x35D4, 0xB1, 0x35D5, 0xBD,
+ 0x35D6, 0xC3, 0x35D7, 0x9A, 0x35D8, 0x20,
+ 0x35D9, 0x1E, 0x35DA, 0xCC, 0x35DB, 0x01,
+ 0x35DC, 0xB1, 0x35DD, 0xBD, 0x35DE, 0xC4,
+ 0x35DF, 0x39, 0x35E0, 0x20, 0x35E1, 0x16,
+ 0x35E2, 0xCC, 0x35E3, 0x01, 0x35E4, 0xB1,
+ 0x35E5, 0xBD, 0x35E6, 0xC5, 0x35E7, 0x0B,
+ 0x35E8, 0x20, 0x35E9, 0x0E, 0x35EA, 0xCC,
+ 0x35EB, 0x01, 0x35EC, 0xB1, 0x35ED, 0xBD,
+ 0x35EE, 0xC6, 0x35EF, 0x3A, 0x35F0, 0x20,
+ 0x35F1, 0x06, 0x35F2, 0xCC, 0x35F3, 0x01,
+ 0x35F4, 0xB1, 0x35F5, 0xBD, 0x35F6, 0xC7,
+ 0x35F7, 0xC2, 0x35F8, 0xF7, 0x35F9, 0x01,
+ 0x35FA, 0xBF, 0x35FB, 0x39, 0x35FC, 0x43,
+ 0x35FD, 0x3A, 0x35FE, 0x41, 0x35FF, 0x44,
+ 0x3600, 0x54, 0x3601, 0x5F, 0x3602, 0x41,
+ 0x3603, 0x54, 0x3604, 0x4E, 0x3605, 0x0A,
+ 0x3606, 0x0D, 0x3607, 0x00, 0x3608, 0x43,
+ 0x3609, 0x3A, 0x360A, 0x45, 0x360B, 0x6E,
+ 0x360C, 0x5F, 0x360D, 0x53, 0x360E, 0x74,
+ 0x360F, 0x0A, 0x3610, 0x0D, 0x3611, 0x00,
+ 0x3612, 0x43, 0x3613, 0x3A, 0x3614, 0x49,
+ 0x3615, 0x0A, 0x3616, 0x0D, 0x3617, 0x00,
+ 0x3618, 0x00, 0x3400, 0x01, 0x33f8, 0x01
+#endif
\ В конце файла нет новой строки
diff -urN linux-4.9.37/drivers/net/ethernet/goke/femac/phy_v2.h linux-4.9.y/drivers/net/ethernet/goke/femac/phy_v2.h
--- linux-4.9.37/drivers/net/ethernet/goke/femac/phy_v2.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/net/ethernet/goke/femac/phy_v2.h 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#ifndef __ETH_PHY_V272_2723_H__
+#define __ETH_PHY_V272_2723_H__
+ 0x33f9, 0xbd, 0x33fa, 0x34, 0x33fb, 0x00,
+ 0x33fc, 0x39, 0x3400, 0x39, 0x3401, 0xCC,
+ 0x3402, 0x27, 0x3403, 0x23, 0x3404, 0xFD,
+ 0x3405, 0xFF, 0x3406, 0xF0, 0x3407, 0x20,
+ 0x3408, 0x00, 0x3409, 0x3C, 0x340A, 0x3C,
+ 0x340B, 0x30, 0x340C, 0xF6, 0x340D, 0x00,
+ 0x340E, 0x4A, 0x340F, 0xC4, 0x3410, 0x7F,
+ 0x3411, 0xE7, 0x3412, 0x01, 0x3413, 0xF6,
+ 0x3414, 0x01, 0x3415, 0xBE, 0x3416, 0xC1,
+ 0x3417, 0x02, 0x3418, 0x27, 0x3419, 0x0E,
+ 0x341A, 0xE6, 0x341B, 0x01, 0x341C, 0xC1,
+ 0x341D, 0x14, 0x341E, 0x27, 0x341F, 0x08,
+ 0x3420, 0xC1, 0x3421, 0x18, 0x3422, 0x25,
+ 0x3423, 0x09, 0x3424, 0xC1, 0x3425, 0x1B,
+ 0x3426, 0x22, 0x3427, 0x05, 0x3428, 0xC6,
+ 0x3429, 0x5C, 0x342A, 0xF7, 0x342B, 0x20,
+ 0x342C, 0xA1, 0x342D, 0xF6, 0x342E, 0x01,
+ 0x342F, 0xBF, 0x3430, 0xC1, 0x3431, 0x01,
+ 0x3432, 0x26, 0x3433, 0x29, 0x3434, 0xF6,
+ 0x3435, 0x30, 0x3436, 0x55, 0x3437, 0xC0,
+ 0x3438, 0x05, 0x3439, 0xE7, 0x343A, 0x01,
+ 0x343B, 0xC1, 0x343C, 0x13, 0x343D, 0x23,
+ 0x343E, 0x04, 0x343F, 0xC6, 0x3440, 0x13,
+ 0x3441, 0xE7, 0x3442, 0x01, 0x3443, 0x18,
+ 0x3444, 0xFE, 0x3445, 0x30, 0x3446, 0x4C,
+ 0x3447, 0x18, 0x3448, 0x3A, 0x3449, 0x18,
+ 0x344A, 0xE6, 0x344B, 0x00, 0x344C, 0x58,
+ 0x344D, 0x58, 0x344E, 0x58, 0x344F, 0x58,
+ 0x3450, 0x58, 0x3451, 0xE7, 0x3452, 0x00,
+ 0x3453, 0xF6, 0x3454, 0x20, 0x3455, 0x04,
+ 0x3456, 0xC4, 0x3457, 0x1F, 0x3458, 0xEA,
+ 0x3459, 0x00, 0x345A, 0xF7, 0x345B, 0x20,
+ 0x345C, 0x04, 0x345D, 0x38, 0x345E, 0x38,
+ 0x345F, 0x39, 0x3400, 0x01, 0x33f8, 0x01
+#endif
\ В конце файла нет новой строки
diff -urN linux-4.9.37/drivers/net/ethernet/goke/femac/util.c linux-4.9.y/drivers/net/ethernet/goke/femac/util.c
--- linux-4.9.37/drivers/net/ethernet/goke/femac/util.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/net/ethernet/goke/femac/util.c 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#include <linux/if_vlan.h>
+#include <linux/ip.h>
+#include <net/ipv6.h>
+
+#include "util.h"
+
+static void femac_do_udp_checksum(struct sk_buff *skb)
+{
+ int offset;
+ __wsum csum;
+ __sum16 udp_csum;
+
+ offset = skb_checksum_start_offset(skb);
+ WARN_ON(offset >= skb_headlen(skb));
+ csum = skb_checksum(skb, offset, skb->len - offset, 0);
+
+ offset += skb->csum_offset;
+ WARN_ON(offset + sizeof(__sum16) > skb_headlen(skb));
+
+ udp_csum = csum_fold(csum);
+ if (udp_csum == 0)
+ udp_csum = CSUM_MANGLED_0;
+
+ *(__sum16 *)(skb->data + offset) = udp_csum;
+
+ skb->ip_summed = CHECKSUM_NONE;
+}
+
+static __be16 femac_get_l3_proto(struct sk_buff *skb)
+{
+ __be16 l3_proto;
+
+ l3_proto = skb->protocol;
+ if (skb->protocol == htons(ETH_P_8021Q))
+ l3_proto = vlan_get_protocol(skb);
+
+ return l3_proto;
+}
+
+static inline bool femac_skb_is_ipv6(struct sk_buff *skb)
+{
+ return (femac_get_l3_proto(skb) == htons(ETH_P_IPV6));
+}
+
+static int femac_check_hw_capability_for_ipv6(struct sk_buff *skb)
+{
+ unsigned int l4_proto;
+
+ l4_proto = ipv6_hdr(skb)->nexthdr;
+ if ((l4_proto != IPPROTO_TCP) && (l4_proto != IPPROTO_UDP)) {
+ /*
+ * when IPv6 next header is not tcp or udp,
+ * it means that IPv6 next header is extension header.
+ * Hardware can't deal with this case,
+ * so do checksumming by software or do GSO by software.
+ */
+ if (skb_is_gso(skb)) {
+ return -ENOTSUPP;
+ }
+
+ if (skb->ip_summed == CHECKSUM_PARTIAL &&
+ skb_checksum_help(skb)) {
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+int femac_check_hw_capability(struct sk_buff *skb)
+{
+ /*
+ * if tcp_mtu_probe() use (2 * tp->mss_cache) as probe_size,
+ * the linear data length will be larger than 2048,
+ * the MAC can't handle it, so let the software do it.
+ */
+ if (skb_is_gso(skb) && (skb_headlen(skb) > 2048)) { /* max is 2048 */
+ return -ENOTSUPP;
+ }
+
+ if (femac_skb_is_ipv6(skb)) {
+ return femac_check_hw_capability_for_ipv6(skb);
+ }
+
+ return 0;
+}
+
+static unsigned int femac_get_pkt_info_gso(struct sk_buff *skb,
+ bool txcsum, unsigned int max_mss, unsigned int l4_proto)
+{
+ u32 pkt_info = 0;
+ bool do_txcsum = txcsum;
+
+ /*
+ * Although netcard support UFO feature, it can't deal with
+ * UDP header checksum.
+ * So the driver will do UDP header checksum and netcard will just
+ * fragment the packet.
+ */
+ if (do_txcsum && skb_is_gso(skb) && (l4_proto == IPPROTO_UDP)) {
+ femac_do_udp_checksum(skb);
+ do_txcsum = false;
+ }
+
+ if (do_txcsum)
+ pkt_info |= BIT_FLAG_TXCSUM;
+
+ if (skb_is_gso(skb)) {
+ pkt_info |= (BIT_FLAG_SG | BIT_FLAG_TSO);
+ } else if (skb_shinfo(skb)->nr_frags) {
+ pkt_info |= BIT_FLAG_SG;
+ }
+
+ pkt_info |= (skb_shinfo(skb)->nr_frags << BIT_OFFSET_NFRAGS_NUM);
+ pkt_info |= (skb_is_gso(skb) ? ((skb_shinfo(skb)->gso_size > max_mss) ? max_mss : skb_shinfo(skb)->gso_size) :
+ (skb->len + ETH_FCS_LEN));
+ return pkt_info;
+}
+
+u32 femac_get_pkt_info(struct sk_buff *skb)
+{
+ __be16 l3_proto;
+ unsigned int l4_proto = IPPROTO_MAX;
+ bool do_txcsum = false;
+ int max_data_len = skb->len - ETH_HLEN;
+ unsigned int max_mss = ETH_DATA_LEN;
+ u32 pkt_info = 0;
+
+ if (skb->ip_summed == CHECKSUM_PARTIAL)
+ do_txcsum = true;
+
+ l3_proto = skb->protocol;
+ if (skb->protocol == htons(ETH_P_8021Q)) {
+ l3_proto = vlan_get_protocol(skb);
+ max_data_len -= VLAN_HLEN;
+ pkt_info |= BIT_FLAG_VLAN;
+ }
+
+ if (l3_proto == htons(ETH_P_IP)) {
+ struct iphdr *iph = ip_hdr(skb);
+
+ if ((max_data_len >= GSO_MAX_SIZE) &&
+ (ntohs(iph->tot_len) <= (iph->ihl << 2))) /* trans 2 bytes */
+ iph->tot_len = htons(GSO_MAX_SIZE - 1);
+
+ max_mss -= iph->ihl * WORD_TO_BYTE;
+ pkt_info |= (iph->ihl << BIT_OFFSET_IP_HEADER_LEN);
+ l4_proto = iph->protocol;
+ } else if (l3_proto == htons(ETH_P_IPV6)) {
+ max_mss -= IPV6_HDR_LEN * WORD_TO_BYTE;
+ pkt_info |= BIT_FLAG_IPV6;
+ pkt_info |= (IPV6_HDR_LEN << BIT_OFFSET_IP_HEADER_LEN);
+ l4_proto = ipv6_hdr(skb)->nexthdr;
+ } else {
+ do_txcsum = false;
+ }
+
+ if (l4_proto == IPPROTO_TCP) {
+ max_mss -= tcp_hdr(skb)->doff * WORD_TO_BYTE;
+ pkt_info |= (tcp_hdr(skb)->doff << BIT_OFFSET_PROT_HEADER_LEN);
+ } else if (l4_proto == IPPROTO_UDP) {
+ if (l3_proto == htons(ETH_P_IPV6))
+ max_mss -= sizeof(struct frag_hdr);
+ pkt_info |= (BIT_FLAG_UDP |
+ (UDP_HDR_LEN << BIT_OFFSET_PROT_HEADER_LEN));
+ } else {
+ do_txcsum = false;
+ }
+
+ pkt_info |= femac_get_pkt_info_gso(skb, do_txcsum, max_mss, l4_proto);
+
+ return pkt_info;
+}
+
+void femac_sleep_us(u32 time_us)
+{
+ u32 time_ms;
+
+ if (!time_us) {
+ return;
+ }
+
+ time_ms = DIV_ROUND_UP(time_us, 1000); /* add 1000us, round up */
+ if (time_ms < 20) { /* less than 20 ms */
+ usleep_range(time_us, time_us + 500); /* add maximum 500us */
+ } else {
+ msleep(time_ms);
+ }
+}
+
+void femac_set_flow_ctrl(const struct femac_priv *priv)
+{
+ unsigned int pause_en;
+ unsigned int tx_flow_ctrl;
+
+ tx_flow_ctrl = readl(priv->port_base + FC_LEVEL);
+ tx_flow_ctrl &= ~FC_DEACTIVE_THR_MASK;
+ tx_flow_ctrl |= priv->tx_pause_deactive_thresh;
+ tx_flow_ctrl &= ~FC_ACTIVE_THR_MASK;
+ tx_flow_ctrl |= priv->tx_pause_active_thresh << BITS_FC_ACTIVE_THR_OFFSET;
+
+ pause_en = readl(priv->port_base + MAC_SET);
+
+ if (priv->tx_pause_en) {
+ tx_flow_ctrl |= BIT_FC_EN;
+ pause_en |= BIT_PAUSE_EN;
+ } else {
+ tx_flow_ctrl &= ~BIT_FC_EN;
+ pause_en &= ~BIT_PAUSE_EN;
+ }
+
+ writel(tx_flow_ctrl, priv->port_base + FC_LEVEL);
+
+ writel(pause_en, priv->port_base + MAC_SET);
+}
+
+void femac_get_pauseparam(struct net_device *dev,
+ struct ethtool_pauseparam *pause)
+{
+ struct femac_priv *priv = netdev_priv(dev);
+
+ pause->autoneg = dev->phydev->autoneg;
+ pause->rx_pause = 1;
+ if (priv->tx_pause_en)
+ pause->tx_pause = 1;
+}
+
+int femac_set_pauseparam(struct net_device *dev,
+ struct ethtool_pauseparam *pause)
+{
+ struct femac_priv *priv = netdev_priv(dev);
+ struct phy_device *phy = dev->phydev;
+ int ret = 0;
+
+ if (pause->rx_pause == 0) {
+ return -EINVAL;
+ }
+
+ if (pause->tx_pause != priv->tx_pause_en) {
+ priv->tx_pause_en = pause->tx_pause;
+ femac_set_flow_ctrl(priv);
+ }
+
+ if (phy->autoneg) {
+ if (netif_running(dev)) {
+ struct ethtool_cmd cmd;
+ /* auto-negotiation automatically restarted */
+ cmd.cmd = ETHTOOL_NWAY_RST;
+ cmd.supported = phy->supported;
+ cmd.advertising = phy->advertising;
+ cmd.autoneg = phy->autoneg;
+ cmd.speed = phy->speed;
+ cmd.duplex = phy->duplex;
+ cmd.phy_address = phy->mdio.addr;
+ ret = phy_ethtool_sset(phy, &cmd);
+ }
+ }
+
+ return ret;
+}
+
+void femac_enable_rxcsum_drop(const struct femac_priv *priv,
+ bool drop)
+{
+ unsigned int val;
+
+ val = readl(priv->port_base + RX_COE_CTRL);
+ val &= ~COE_ERR_DROP;
+ if (drop)
+ val |= (BIT_COE_IPHDR_DROP | BIT_COE_IPV6_UDP_ZERO_DROP);
+ writel(val, priv->port_base + RX_COE_CTRL);
+}
+
+int femac_set_features(struct net_device *dev, netdev_features_t features)
+{
+ struct femac_priv *priv = netdev_priv(dev);
+ netdev_features_t changed = dev->features ^ features;
+
+ if (changed & NETIF_F_RXCSUM) {
+ if (features & NETIF_F_RXCSUM) {
+ femac_enable_rxcsum_drop(priv, true);
+ } else {
+ femac_enable_rxcsum_drop(priv, false);
+ }
+ }
+
+ return 0;
+}
\ В конце файла нет новой строки
diff -urN linux-4.9.37/drivers/net/ethernet/goke/femac/util.h linux-4.9.y/drivers/net/ethernet/goke/femac/util.h
--- linux-4.9.37/drivers/net/ethernet/goke/femac/util.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/net/ethernet/goke/femac/util.h 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#ifndef __ETH_UTIL_H__
+#define __ETH_UTIL_H__
+
+#include "femac.h"
+
+int femac_check_hw_capability(struct sk_buff *skb);
+u32 femac_get_pkt_info(struct sk_buff *skb);
+void femac_sleep_us(u32 time_us);
+void femac_set_flow_ctrl(const struct femac_priv *priv);
+void femac_get_pauseparam(struct net_device *dev,
+ struct ethtool_pauseparam *pause);
+int femac_set_pauseparam(struct net_device *dev,
+ struct ethtool_pauseparam *pause);
+void femac_enable_rxcsum_drop(const struct femac_priv *priv,
+ bool drop);
+int femac_set_features(struct net_device *dev, netdev_features_t features);
+
+#endif
\ В конце файла нет новой строки
diff -urN linux-4.9.37/drivers/net/ethernet/goke/Kconfig linux-4.9.y/drivers/net/ethernet/goke/Kconfig
--- linux-4.9.37/drivers/net/ethernet/goke/Kconfig 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/net/ethernet/goke/Kconfig 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,32 @@
+#
+# Goke device configuration
+#
+
+config NET_VENDOR_GOKE
+ bool "Goke devices"
+ default y
+ depends on (OF || ACPI) && HAS_DMA
+ depends on ARM || ARM64 || COMPILE_TEST
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about Goke devices. If you say Y, you will be asked
+ for your specific card in the following questions.
+
+if NET_VENDOR_GOKE
+
+config GOKE_FEMAC
+ tristate "Goke Fast Ethernet MAC device support"
+ depends on HAS_IOMEM
+ select PHYLIB
+ select RESET_CONTROLLER
+ help
+ This selects the Goke Fast Ethernet MAC device(FEMAC).
+ The FEMAC receives and transmits data over Ethernet
+ ports at 10/100 Mbps in full-duplex or half-duplex mode.
+ The FEMAC exchanges data with the CPU, and supports
+ the energy efficient Ethernet (EEE).
+
+endif # NET_VENDOR_GOKE
diff -urN linux-4.9.37/drivers/net/ethernet/goke/Makefile linux-4.9.y/drivers/net/ethernet/goke/Makefile
--- linux-4.9.37/drivers/net/ethernet/goke/Makefile 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/net/ethernet/goke/Makefile 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,5 @@
+#
+# Makefile for the network device drivers.
+#
+
+obj-$(CONFIG_GOKE_FEMAC) += femac/
diff -urN linux-4.9.37/drivers/net/ethernet/Kconfig linux-4.9.y/drivers/net/ethernet/Kconfig
--- linux-4.9.37/drivers/net/ethernet/Kconfig 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/net/ethernet/Kconfig 2021-06-07 13:01:33.000000000 +0300
@@ -75,6 +75,7 @@
source "drivers/net/ethernet/freescale/Kconfig"
source "drivers/net/ethernet/fujitsu/Kconfig"
source "drivers/net/ethernet/hisilicon/Kconfig"
+source "drivers/net/ethernet/goke/Kconfig"
source "drivers/net/ethernet/hp/Kconfig"
source "drivers/net/ethernet/ibm/Kconfig"
source "drivers/net/ethernet/intel/Kconfig"
diff -urN linux-4.9.37/drivers/net/ethernet/Makefile linux-4.9.y/drivers/net/ethernet/Makefile
--- linux-4.9.37/drivers/net/ethernet/Makefile 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/net/ethernet/Makefile 2021-06-07 13:01:33.000000000 +0300
@@ -38,6 +38,7 @@
obj-$(CONFIG_NET_VENDOR_FREESCALE) += freescale/
obj-$(CONFIG_NET_VENDOR_FUJITSU) += fujitsu/
obj-$(CONFIG_NET_VENDOR_HISILICON) += hisilicon/
+obj-$(CONFIG_NET_VENDOR_GOKE) += goke/
obj-$(CONFIG_NET_VENDOR_HP) += hp/
obj-$(CONFIG_NET_VENDOR_IBM) += ibm/
obj-$(CONFIG_NET_VENDOR_INTEL) += intel/
diff -urN linux-4.9.37/drivers/net/phy/Kconfig linux-4.9.y/drivers/net/phy/Kconfig
--- linux-4.9.37/drivers/net/phy/Kconfig 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/net/phy/Kconfig 2021-06-07 13:01:33.000000000 +0300
@@ -89,6 +89,13 @@
config MDIO_CAVIUM
tristate
+config MDIO_GOKE_FEMAC
+ tristate "Goke femac MDIO buses"
+ depends on HAS_IOMEM && OF_MDIO
+ help
+ This module provides a driver for the MDIO busses found in the
+ Goke SoC that have an Fast Ethernet.
+
config MDIO_GPIO
tristate "GPIO lib-based bitbanged MDIO buses"
depends on MDIO_BITBANG && GPIOLIB
diff -urN linux-4.9.37/drivers/net/phy/Makefile linux-4.9.y/drivers/net/phy/Makefile
--- linux-4.9.37/drivers/net/phy/Makefile 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/net/phy/Makefile 2021-06-07 13:01:33.000000000 +0300
@@ -13,6 +13,7 @@
obj-$(CONFIG_MDIO_BUS_MUX_GPIO) += mdio-mux-gpio.o
obj-$(CONFIG_MDIO_BUS_MUX_MMIOREG) += mdio-mux-mmioreg.o
obj-$(CONFIG_MDIO_CAVIUM) += mdio-cavium.o
+obj-$(CONFIG_MDIO_GOKE_FEMAC) += mdio-goke-femac.o
obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o
obj-$(CONFIG_MDIO_HISI_FEMAC) += mdio-hisi-femac.o
obj-$(CONFIG_MDIO_MOXART) += mdio-moxart.o
diff -urN linux-4.9.37/drivers/net/phy/mdio-goke-femac.c linux-4.9.y/drivers/net/phy/mdio-goke-femac.c
--- linux-4.9.37/drivers/net/phy/mdio-goke-femac.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/net/phy/mdio-goke-femac.c 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,450 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#include <linux/clk.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_mdio.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+#define MDIO_RWCTRL 0x00
+#define MDIO_RO_DATA 0x04
+#define MDIO_WRITE BIT(13)
+#define MDIO_RW_FINISH BIT(15)
+#define BIT_PHY_ADDR_OFFSET 8
+#define BIT_WR_DATA_OFFSET 16
+
+#define BIT_MASK_FEPHY_ADDR GENMASK(4, 0)
+#define BIT_FEPHY_SEL BIT(5)
+
+#if defined(CONFIG_ARCH_CJ104V100)
+#define BIT_OFFSET_LD_SET 0
+#define BIT_OFFSET_LDO_SET 5
+#define BIT_OFFSET_R_TUNING 8
+#else
+#define BIT_OFFSET_LD_SET 25
+#define BIT_OFFSET_LDO_SET 22
+#define BIT_OFFSET_R_TUNING 16
+#endif
+#define MII_EXPMD 0x1d
+#define MII_EXPMA 0x1e
+
+#define REG_LD_AM 0x3050
+#define BIT_MASK_LD_SET GENMASK(4, 0)
+#define REG_LDO_AM 0x3051
+#define BIT_MASK_LDO_SET GENMASK(2, 0)
+#define REG_R_TUNING 0x3052
+#define BIT_MASK_R_TUNING GENMASK(5, 0)
+#define REG_WR_DONE 0x3053
+#define BIT_CFG_DONE BIT(0)
+#define BIT_CFG_ACK BIT(1)
+#define REG_DEF_ATE 0x3057
+#define BIT_AUTOTRIM_DONE BIT(0)
+
+#define PHY_RESET_DELAYS_PROPERTY "goke,phy-reset-delays-us"
+
+enum phy_reset_delays {
+ PRE_DELAY,
+ PULSE,
+ POST_DELAY,
+ DELAYS_NUM,
+};
+
+struct femac_mdio_data {
+ struct clk *clk;
+ struct clk *fephy_clk;
+ struct reset_control *phy_rst;
+ struct reset_control *fephy_rst;
+ u32 phy_reset_delays[DELAYS_NUM];
+ void __iomem *membase;
+ void __iomem *fephy_iobase;
+ void __iomem *fephy_trim_iobase;
+ struct mii_bus *bus;
+ u32 phy_addr;
+};
+
+static int femac_mdio_wait_ready(struct femac_mdio_data *data)
+{
+ u32 val;
+
+ return readl_poll_timeout_atomic(data->membase + MDIO_RWCTRL,
+ val, val & MDIO_RW_FINISH, 20, 10000);
+}
+
+static int femac_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
+{
+ struct femac_mdio_data *data = bus->priv;
+ int ret;
+
+ ret = femac_mdio_wait_ready(data);
+ if (ret)
+ return ret;
+
+ writel(((u32)mii_id << BIT_PHY_ADDR_OFFSET) | ((u32)regnum),
+ data->membase + MDIO_RWCTRL);
+
+ ret = femac_mdio_wait_ready(data);
+ if (ret)
+ return ret;
+
+ return readl(data->membase + MDIO_RO_DATA) & 0xFFFF;
+}
+
+static int femac_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
+ u16 value)
+{
+ struct femac_mdio_data *data = bus->priv;
+ int ret;
+
+ ret = femac_mdio_wait_ready(data);
+ if (ret)
+ return ret;
+
+ writel(MDIO_WRITE | (value << BIT_WR_DATA_OFFSET) |
+ ((u32)mii_id << BIT_PHY_ADDR_OFFSET) | ((u32)regnum),
+ data->membase + MDIO_RWCTRL);
+
+ return femac_mdio_wait_ready(data);
+}
+
+static void femac_sleep_us(u32 time_us)
+{
+ u32 time_ms;
+
+ if (!time_us)
+ return;
+
+ time_ms = DIV_ROUND_UP(time_us, 1000);
+ if (time_ms < 20)
+ usleep_range(time_us, time_us + 500);
+ else
+ msleep(time_ms);
+}
+
+static void femac_phy_reset(const struct femac_mdio_data *data)
+{
+ /* To make sure PHY hardware reset success,
+ * we must keep PHY in deassert state first and
+ * then complete the hardware reset operation
+ */
+ reset_control_deassert(data->phy_rst);
+ femac_sleep_us(data->phy_reset_delays[PRE_DELAY]);
+
+ reset_control_assert(data->phy_rst);
+ /* delay some time to ensure reset ok,
+ * this depends on PHY hardware feature
+ */
+ femac_sleep_us(data->phy_reset_delays[PULSE]);
+ reset_control_deassert(data->phy_rst);
+ /* delay some time to ensure later MDIO access */
+ femac_sleep_us(data->phy_reset_delays[POST_DELAY]);
+}
+
+static void femac_get_phy_addr(struct femac_mdio_data *data,
+ struct device_node *np)
+{
+ struct device_node *child = NULL;
+ int addr;
+
+ child = of_get_next_available_child(np, NULL);
+ if (!child) {
+ pr_err("%s: No valid PHY device node!\n", __func__);
+ return;
+ }
+
+ addr = of_mdio_parse_addr(&data->bus->dev, child);
+ if (addr < 0) {
+ pr_err("%s: get PHY address failed!\n", __func__);
+ return;
+ }
+
+ data->phy_addr = addr;
+}
+
+static inline bool femac_use_fephy(struct femac_mdio_data *data)
+{
+ /*return false;*/
+ return (data->fephy_iobase ?
+ !(readl(data->fephy_iobase) & BIT_FEPHY_SEL) : false);
+}
+
+static void femac_fephy_reset(struct femac_mdio_data *data)
+{
+ u32 val;
+
+ /* disable MDCK clock to make sure FEPHY reset success */
+ clk_disable_unprepare(data->clk);
+
+ val = readl(data->fephy_iobase);
+ val &= ~BIT_MASK_FEPHY_ADDR;
+ val |= data->phy_addr;
+ writel(val, data->fephy_iobase);
+
+ clk_prepare_enable(data->fephy_clk);
+ udelay(10);
+
+ reset_control_assert(data->fephy_rst);
+ udelay(10);
+ reset_control_deassert(data->fephy_rst);
+ /* delay at least 15ms for MDIO operation */
+ msleep(20);
+
+ clk_prepare_enable(data->clk);
+ /* delay 5ms after enable MDCK to make sure FEPHY trim safe */
+ mdelay(5);
+}
+
+static inline int fephy_expanded_read(struct mii_bus *bus, int phy_addr,
+ u32 reg_addr)
+{
+ int ret;
+
+ femac_mdio_write(bus, phy_addr, MII_EXPMA, reg_addr);
+ ret = femac_mdio_read(bus, phy_addr, MII_EXPMD);
+
+ return ret;
+}
+
+static inline int fephy_expanded_write(struct mii_bus *bus, int phy_addr,
+ u32 reg_addr, u16 val)
+{
+ int ret;
+
+ femac_mdio_write(bus, phy_addr, MII_EXPMA, reg_addr);
+ ret = femac_mdio_write(bus, phy_addr, MII_EXPMD, val);
+
+ return ret;
+}
+
+void femac_fephy_use_default_trim(struct femac_mdio_data *data)
+{
+ unsigned short val;
+ int timeout = 3;
+
+ pr_info("No OTP data, internal PHY use default ATE parameters!\n");
+
+ do {
+ msleep(250);
+ val = fephy_expanded_read(data->bus, data->phy_addr,
+ REG_DEF_ATE);
+ val &= BIT_AUTOTRIM_DONE;
+ } while (!val && --timeout);
+
+ if (!timeout)
+ pr_err("femac PHY wait autotrim done timeout!\n");
+
+ mdelay(5);
+}
+
+static void femac_fephy_trim(struct femac_mdio_data *data)
+{
+ struct mii_bus *bus = data->bus;
+ u32 phy_addr = data->phy_addr;
+ int timeout = 3000;
+ u32 val;
+ u8 ld_set;
+ u8 ldo_set;
+ u8 r_tuning;
+
+ val = readl(data->fephy_iobase);
+ ld_set = (val >> BIT_OFFSET_LD_SET) & BIT_MASK_LD_SET;
+ ldo_set = (val >> BIT_OFFSET_LDO_SET) & BIT_MASK_LDO_SET;
+ r_tuning = (val >> BIT_OFFSET_R_TUNING) & BIT_MASK_R_TUNING;
+
+ if (!ld_set && !ldo_set && !r_tuning) {
+ femac_fephy_use_default_trim(data);
+ return;
+ }
+
+ val = fephy_expanded_read(bus, phy_addr, REG_LD_AM);
+ val = (val & ~BIT_MASK_LD_SET) | (ld_set & BIT_MASK_LD_SET);
+ fephy_expanded_write(bus, phy_addr, REG_LD_AM, val);
+
+ val = fephy_expanded_read(bus, phy_addr, REG_LDO_AM);
+ val = (val & ~BIT_MASK_LDO_SET) | (ldo_set & BIT_MASK_LDO_SET);
+ fephy_expanded_write(bus, phy_addr, REG_LDO_AM, val);
+
+ val = fephy_expanded_read(bus, phy_addr, REG_R_TUNING);
+ val = (val & ~BIT_MASK_R_TUNING) | (r_tuning & BIT_MASK_R_TUNING);
+ fephy_expanded_write(bus, phy_addr, REG_R_TUNING, val);
+
+ val = fephy_expanded_read(bus, phy_addr, REG_WR_DONE);
+ if (val & BIT_CFG_ACK)
+ pr_err("femac PHY 0x3053 bit CFG_ACK value: 1\n");
+ val = val | BIT_CFG_DONE;
+ fephy_expanded_write(bus, phy_addr, REG_WR_DONE, val);
+
+ do {
+ usleep_range(100, 150);
+ val = fephy_expanded_read(bus, phy_addr, REG_WR_DONE);
+ val &= BIT_CFG_ACK;
+ } while (!val && --timeout);
+ if (!timeout)
+ pr_err("femac PHY 0x3053 wait bit CFG_ACK timeout!\n");
+
+ mdelay(5);
+
+ pr_info("FEPHY:addr=%d, la_am=0x%x, ldo_am=0x%x, r_tuning=0x%x\n",
+ phy_addr,
+ fephy_expanded_read(bus, phy_addr, REG_LD_AM),
+ fephy_expanded_read(bus, phy_addr, REG_LDO_AM),
+ fephy_expanded_read(bus, phy_addr, REG_R_TUNING));
+}
+
+static void femac_fephy_reset_and_trim(struct femac_mdio_data *data)
+{
+ femac_fephy_reset(data);
+ femac_fephy_trim(data);
+}
+
+static void femac_fephy_set_phy_addr(struct femac_mdio_data *data)
+{
+ u32 val;
+
+ if (!data->fephy_iobase)
+ return;
+
+ val = readl(data->fephy_iobase);
+ val &= ~BIT_MASK_FEPHY_ADDR;
+ val |= (data->phy_addr + 1);
+ writel(val, data->fephy_iobase);
+}
+
+static int femac_mdio_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct mii_bus *bus;
+ struct femac_mdio_data *data;
+ struct resource *res;
+ int ret;
+
+ bus = mdiobus_alloc_size(sizeof(*data));
+ if (!bus)
+ return -ENOMEM;
+
+ bus->name = "femac_mii_bus";
+ bus->read = &femac_mdio_read;
+ bus->write = &femac_mdio_write;
+ snprintf(bus->id, MII_BUS_ID_SIZE, "%s", pdev->name);
+ bus->parent = &pdev->dev;
+
+ data = bus->priv;
+ data->bus = bus;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ data->membase = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(data->membase)) {
+ ret = PTR_ERR(data->membase);
+ goto err_out_free_mdiobus;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (res) {
+ data->fephy_iobase = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(data->fephy_iobase)) {
+ ret = PTR_ERR(data->fephy_iobase);
+ goto err_out_free_mdiobus;
+ }
+ } else {
+ data->fephy_iobase = NULL;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+ if (res) {
+ data->fephy_trim_iobase = devm_ioremap_resource(&pdev->dev,
+ res);
+ if (IS_ERR(data->fephy_trim_iobase)) {
+ ret = PTR_ERR(data->fephy_trim_iobase);
+ goto err_out_free_mdiobus;
+ }
+ } else {
+ data->fephy_trim_iobase = NULL;
+ }
+
+ data->clk = devm_clk_get(&pdev->dev, "mdio");
+ if (IS_ERR(data->clk)) {
+ ret = PTR_ERR(data->clk);
+ goto err_out_free_mdiobus;
+ }
+
+ data->fephy_clk = devm_clk_get(&pdev->dev, "phy");
+ if (IS_ERR(data->fephy_clk))
+ data->fephy_clk = NULL;
+
+ ret = clk_prepare_enable(data->clk);
+ if (ret)
+ goto err_out_free_mdiobus;
+
+ data->phy_rst = devm_reset_control_get(&pdev->dev, "external-phy");
+ if (IS_ERR(data->phy_rst)) {
+ data->phy_rst = NULL;
+ } else {
+ ret = of_property_read_u32_array(np,
+ PHY_RESET_DELAYS_PROPERTY,
+ data->phy_reset_delays,
+ DELAYS_NUM);
+ if (ret)
+ goto err_out_disable_clk;
+ femac_phy_reset(data);
+ }
+
+ data->fephy_rst = devm_reset_control_get(&pdev->dev, "internal-phy");
+ if (IS_ERR(data->fephy_rst))
+ data->fephy_rst = NULL;
+
+ femac_get_phy_addr(data, np);
+ if (femac_use_fephy(data))
+ femac_fephy_reset_and_trim(data);
+ else
+ femac_fephy_set_phy_addr(data);
+
+ ret = of_mdiobus_register(bus, np);
+ if (ret)
+ goto err_out_disable_clk;
+
+ platform_set_drvdata(pdev, bus);
+
+ return 0;
+
+err_out_disable_clk:
+ clk_disable_unprepare(data->fephy_clk);
+ clk_disable_unprepare(data->clk);
+err_out_free_mdiobus:
+ mdiobus_free(bus);
+ return ret;
+}
+
+static int femac_mdio_remove(struct platform_device *pdev)
+{
+ struct mii_bus *bus = platform_get_drvdata(pdev);
+ struct femac_mdio_data *data = bus->priv;
+
+ mdiobus_unregister(bus);
+ clk_disable_unprepare(data->clk);
+ mdiobus_free(bus);
+
+ return 0;
+}
+
+static const struct of_device_id femac_mdio_dt_ids[] = {
+ { .compatible = "goke,femac-mdio" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, femac_mdio_dt_ids);
+
+static struct platform_driver femac_mdio_driver = {
+ .probe = femac_mdio_probe,
+ .remove = femac_mdio_remove,
+ .driver = {
+ .name = "femac-mdio",
+ .of_match_table = femac_mdio_dt_ids,
+ },
+};
+
+module_platform_driver(femac_mdio_driver);
+
+MODULE_DESCRIPTION("Goke Fast Ethernet MAC MDIO interface driver");
+MODULE_LICENSE("GPL v2");
diff -urN linux-4.9.37/drivers/net/phy/phy_device.c linux-4.9.y/drivers/net/phy/phy_device.c
--- linux-4.9.37/drivers/net/phy/phy_device.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/net/phy/phy_device.c 2021-06-07 13:01:33.000000000 +0300
@@ -234,6 +234,53 @@
}
EXPORT_SYMBOL(phy_register_fixup_for_id);
+/**
+ * phy_unregister_fixup - remove a phy_fixup from the list
+ * @bus_id: A string matches fixup->bus_id (or PHY_ANY_ID) in phy_fixup_list
+ * @phy_uid: A phy id matches fixup->phy_id (or PHY_ANY_UID) in phy_fixup_list
+ * @phy_uid_mask: Applied to phy_uid and fixup->phy_uid before comparison
+ */
+int phy_unregister_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask)
+{
+ struct list_head *pos, *n;
+ struct phy_fixup *fixup;
+ int ret;
+
+ ret = -ENODEV;
+
+ mutex_lock(&phy_fixup_lock);
+ list_for_each_safe(pos, n, &phy_fixup_list) {
+ fixup = list_entry(pos, struct phy_fixup, list);
+
+ if ((!strcmp(fixup->bus_id, bus_id)) &&
+ ((fixup->phy_uid & phy_uid_mask) ==
+ (phy_uid & phy_uid_mask))) {
+ list_del(&fixup->list);
+ kfree(fixup);
+ ret = 0;
+ break;
+ }
+ }
+ mutex_unlock(&phy_fixup_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(phy_unregister_fixup);
+
+/* Unregisters a fixup of any PHY with the UID in phy_uid */
+int phy_unregister_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask)
+{
+ return phy_unregister_fixup(PHY_ANY_ID, phy_uid, phy_uid_mask);
+}
+EXPORT_SYMBOL(phy_unregister_fixup_for_uid);
+
+/* Unregisters a fixup of the PHY with id string bus_id */
+int phy_unregister_fixup_for_id(const char *bus_id)
+{
+ return phy_unregister_fixup(bus_id, PHY_ANY_UID, 0xffffffff);
+}
+EXPORT_SYMBOL(phy_unregister_fixup_for_id);
+
/* Returns 1 if fixup matches phydev in bus_id and phy_uid.
* Fixups can be set to match any in one or more fields.
*/
diff -urN linux-4.9.37/drivers/net/usb/cdc_ether.c linux-4.9.y/drivers/net/usb/cdc_ether.c
--- linux-4.9.37/drivers/net/usb/cdc_ether.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/net/usb/cdc_ether.c 2021-06-07 13:01:33.000000000 +0300
@@ -310,6 +310,26 @@
return -ENODEV;
}
+ return 0;
+
+bad_desc:
+ dev_info(&dev->udev->dev, "bad CDC descriptors\n");
+ return -ENODEV;
+}
+EXPORT_SYMBOL_GPL(usbnet_generic_cdc_bind);
+
+
+/* like usbnet_generic_cdc_bind() but handles filter initialization
+ * correctly
+ */
+int usbnet_ether_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+ int rv;
+
+ rv = usbnet_generic_cdc_bind(dev, intf);
+ if (rv < 0)
+ goto bail_out;
+
/* Some devices don't initialise properly. In particular
* the packet filter is not reset. There are devices that
* don't do reset all the way. So the packet filter should
@@ -317,13 +337,10 @@
*/
usbnet_cdc_update_filter(dev);
- return 0;
-
-bad_desc:
- dev_info(&dev->udev->dev, "bad CDC descriptors\n");
- return -ENODEV;
+bail_out:
+ return rv;
}
-EXPORT_SYMBOL_GPL(usbnet_generic_cdc_bind);
+EXPORT_SYMBOL_GPL(usbnet_ether_cdc_bind);
void usbnet_cdc_unbind(struct usbnet *dev, struct usb_interface *intf)
{
@@ -417,7 +434,7 @@
BUILD_BUG_ON((sizeof(((struct usbnet *)0)->data)
< sizeof(struct cdc_state)));
- status = usbnet_generic_cdc_bind(dev, intf);
+ status = usbnet_ether_cdc_bind(dev, intf);
if (status < 0)
return status;
diff -urN linux-4.9.37/drivers/net/wan/.gitignore linux-4.9.y/drivers/net/wan/.gitignore
--- linux-4.9.37/drivers/net/wan/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/net/wan/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-wanxlfw.inc
diff -urN linux-4.9.37/drivers/of/unittest-data/.gitignore linux-4.9.y/drivers/of/unittest-data/.gitignore
--- linux-4.9.37/drivers/of/unittest-data/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/of/unittest-data/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,2 +0,0 @@
-testcases.dtb
-testcases.dtb.S
diff -urN linux-4.9.37/drivers/phy/goke/Kconfig linux-4.9.y/drivers/phy/goke/Kconfig
--- linux-4.9.37/drivers/phy/goke/Kconfig 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/phy/goke/Kconfig 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,26 @@
+config PHY_GOKE_USBP2
+ tristate "GOKE USBP2 PHY Driver"
+ select GENERIC_PHY
+ default n
+ help
+ Support for PHY on goke Socs. This Phy supports
+ USB 1.5Mb/s, USB 12Mb/s, USB 480Mb/s speeds. It suppots one
+ USB host port to accept one USB device. Support init the phy
+ and adjust phy Eye Diagram.
+
+menuconfig USB_MODE_OPTION
+ bool "goke USB related configuration"
+
+if USB_MODE_OPTION
+
+config USB_DRD0_IN_HOST
+ bool "USB DRD0 Mode Select HOST"
+ help
+ Select whether the USB drd0 is working in host mode.
+
+config USB_DRD0_IN_DEVICE
+ bool "USB DRD0 Mode Select DEVICE"
+ help
+ Select whether the USB drd0 is working in device mode.
+
+endif # USB_MODE_OPTION
diff -urN linux-4.9.37/drivers/phy/goke/Makefile linux-4.9.y/drivers/phy/goke/Makefile
--- linux-4.9.37/drivers/phy/goke/Makefile 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/phy/goke/Makefile 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1 @@
+obj-$(CONFIG_PHY_GOKE_USBP2) += phy-goke-usbp2.o
diff -urN linux-4.9.37/drivers/phy/goke/phy-goke-usb.h linux-4.9.y/drivers/phy/goke/phy-goke-usb.h
--- linux-4.9.37/drivers/phy/goke/phy-goke-usb.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/phy/goke/phy-goke-usb.h 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#ifndef USB2_INCLUDE_PHY_H
+#define USB2_INCLUDE_PHY_H
+
+extern void bsp_usb_phy_on(struct phy *phy);
+extern void bsp_usb_phy_off(struct phy *phy);
+extern void bsp_usb3_phy_on(struct phy *phy);
+extern void bsp_usb3_phy_off(struct phy *phy);
+
+
+struct bsp_priv {
+ void __iomem *sys_ctrl;
+ void __iomem *peri_ctrl;
+ void __iomem *combphy_base;
+ void __iomem *misc_ctrl;
+ unsigned int phyid;
+ void __iomem *ctrl_base;
+ void __iomem *switch_base;
+};
+
+typedef enum mode {
+ PCIE_X2 = 0,
+ PCIE_X1,
+ USB3
+} combphy_mode;
+
+#define U_LEVEL1 10
+#define U_LEVEL2 20
+#define U_LEVEL3 30
+#define U_LEVEL4 50
+#define U_LEVEL5 100
+#define U_LEVEL6 200
+#define U_LEVEL7 300
+#define U_LEVEL8 500
+
+#define M_LEVEL1 2
+#define M_LEVEL2 5
+#define M_LEVEL3 10
+#define M_LEVEL4 20
+#define M_LEVEL5 50
+#define M_LEVEL6 100
+#define M_LEVEL7 200
+
+#define __1K__ 0x400
+#define __2K__ 0x800
+#define __4K__ 0x1000
+#define __8K__ 0x2000
+#define __64K__ 0x10000
+
+#define CRG_REGBASE_NODE_IDX 0
+#define MISC_REGBASE_NODE_IDX 1
+#define CTRL_REGBASE_NODE_IDX 2
+#define PHY_REGBASE_NODE_IDX 3
+
+#endif /* USB2_INCLUDE_PHY_H */
diff -urN linux-4.9.37/drivers/phy/goke/phy-goke-usbp2.c linux-4.9.y/drivers/phy/goke/phy-goke-usbp2.c
--- linux-4.9.37/drivers/phy/goke/phy-goke-usbp2.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/phy/goke/phy-goke-usbp2.c 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,758 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+#include <linux/clk-provider.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+#include <linux/usb/ch9.h>
+
+#include "phy-goke-usb.h"
+
+#define USBP2_PHY_TRIM_OFFSET 0x0008
+#define USBP2_PHY_TRIM_MASK 0x1f00
+#define USBP2_PHY_TRIM_VAL(a) (((a) << 8) & USBP2_PHY_TRIM_MASK)
+
+#define USBP2_PHY_SVB_OFFSET 0x0000
+#define USBP2_PHY_SVB_MASK 0x0f000000
+#define USBP2_PHY_SVB_VAL(a) (((a) << 24) & USBP2_PHY_SVB_MASK)
+
+struct bsp_usbp2_priv {
+ void __iomem *crg_base;
+ void __iomem *phy_base;
+ void __iomem *pin_base;
+ struct phy *phy;
+ struct device *dev;
+ struct clk **clks;
+ int num_clocks;
+ u32 phy_pll_offset;
+ u32 phy_pll_mask;
+ u32 phy_pll_val;
+ u32 crg_offset;
+ u32 crg_defal_mask;
+ u32 crg_defal_val;
+ u32 vbus_offset;
+ u32 vbus_val;
+ int vbus_flag;
+ u32 pwren_offset;
+ u32 pwren_val;
+ int pwren_flag;
+ u32 ana_cfg_0_eye_val;
+ u32 ana_cfg_0_offset;
+ int ana_cfg_0_flag;
+ u32 ana_cfg_2_eye_val;
+ u32 ana_cfg_2_offset;
+ int ana_cfg_2_flag;
+ u32 ana_cfg_4_eye_val;
+ u32 ana_cfg_4_offset;
+ int ana_cfg_4_flag;
+ struct reset_control *usb_phy_tpor_rst;
+ struct reset_control *usb_phy_por_rst;
+ u32 trim_otp_addr;
+ u32 trim_otp_mask;
+ u32 trim_otp_bit_offset;
+ u32 trim_otp_min;
+ u32 trim_otp_max;
+ int trim_flag;
+ u32 svb_otp_addr;
+ u32 svb_otp_predev5_min;
+ u32 svb_otp_predev5_max;
+ u32 svb_phy_predev5_val;
+ int svb_predev5_flag;
+ u32 svb_otp_predev4_min;
+ u32 svb_otp_predev4_max;
+ u32 svb_phy_predev4_val;
+ int svb_predev4_flag;
+ u32 svb_otp_predev3_min;
+ u32 svb_otp_predev3_max;
+ u32 svb_phy_predev3_val;
+ int svb_predev3_flag;
+ u32 svb_otp_predev2_min;
+ u32 svb_otp_predev2_max;
+ u32 svb_phy_predev2_val;
+ int svb_predev2_flag;
+ int svb_flag;
+};
+
+void bsp_usbp2_def_all_exist(struct bsp_usbp2_priv *priv)
+{
+ if (priv == NULL)
+ return;
+
+ /* All parameters exist by default */
+ priv->vbus_flag = 1;
+
+ priv->pwren_flag = 1;
+
+ priv->ana_cfg_0_flag = 1;
+
+ priv->ana_cfg_2_flag = 1;
+
+ priv->ana_cfg_4_flag = 1;
+
+ priv->trim_flag = 1;
+
+ priv->svb_predev5_flag = 1;
+
+ priv->svb_predev4_flag = 1;
+
+ priv->svb_predev3_flag = 1;
+
+ priv->svb_predev2_flag = 1;
+
+ priv->svb_flag = 1;
+}
+
+void bsp_usbp2_get_eye_para(struct device *dev, struct bsp_usbp2_priv *priv)
+{
+ unsigned int ret;
+
+ if ((dev == NULL) || (priv == NULL))
+ return;
+
+ /*
+ * Get phy eye parameters,if you want to change them,please open
+ * dtsi file and modify parameters at phy node.
+ */
+ ret = of_property_read_u32(dev->of_node, "ana_cfg_0_eye_val",
+ &(priv->ana_cfg_0_eye_val));
+ if (ret)
+ priv->ana_cfg_0_flag = 0;
+
+ ret = of_property_read_u32(dev->of_node, "ana_cfg_0_offset",
+ &(priv->ana_cfg_0_offset));
+ if (ret)
+ priv->ana_cfg_0_flag = 0;
+
+ ret = of_property_read_u32(dev->of_node, "ana_cfg_2_eye_val",
+ &(priv->ana_cfg_2_eye_val));
+ if (ret)
+ priv->ana_cfg_2_flag = 0;
+
+ ret = of_property_read_u32(dev->of_node, "ana_cfg_2_offset",
+ &(priv->ana_cfg_2_offset));
+ if (ret)
+ priv->ana_cfg_2_flag = 0;
+
+ ret = of_property_read_u32(dev->of_node, "ana_cfg_4_eye_val",
+ &(priv->ana_cfg_4_eye_val));
+ if (ret)
+ priv->ana_cfg_4_flag = 0;
+
+ ret = of_property_read_u32(dev->of_node, "ana_cfg_4_offset",
+ &(priv->ana_cfg_4_offset));
+ if (ret)
+ priv->ana_cfg_4_flag = 0;
+}
+
+void bsp_usbp2_phy_eye_config(struct bsp_usbp2_priv *priv)
+{
+ if (priv == NULL)
+ return;
+
+ if (priv->ana_cfg_0_flag)
+ writel(priv->ana_cfg_0_eye_val, priv->phy_base + priv->ana_cfg_0_offset);
+
+ if (priv->ana_cfg_2_flag)
+ writel(priv->ana_cfg_2_eye_val, priv->phy_base + priv->ana_cfg_2_offset);
+
+ if (priv->ana_cfg_4_flag)
+ writel(priv->ana_cfg_4_eye_val, priv->phy_base + priv->ana_cfg_4_offset);
+}
+
+void bsp_usbp2_get_trim_para(struct device *dev, struct bsp_usbp2_priv *priv)
+{
+ unsigned int ret;
+
+ if ((dev == NULL) || (priv == NULL))
+ return;
+
+ /* get phy trim parameters */
+ ret = of_property_read_u32(dev->of_node, "trim_otp_addr",
+ &(priv->trim_otp_addr));
+ if (ret)
+ priv->trim_flag = 0;
+
+ ret = of_property_read_u32(dev->of_node, "trim_otp_mask",
+ &(priv->trim_otp_mask));
+ if (ret)
+ priv->trim_flag = 0;
+
+ ret = of_property_read_u32(dev->of_node, "trim_otp_bit_offset",
+ &(priv->trim_otp_bit_offset));
+ if (ret)
+ priv->trim_flag = 0;
+
+ ret = of_property_read_u32(dev->of_node, "trim_otp_min", &(priv->trim_otp_min));
+ if (ret)
+ priv->trim_flag = 0;
+
+ ret = of_property_read_u32(dev->of_node, "trim_otp_max", &(priv->trim_otp_max));
+ if (ret)
+ priv->trim_flag = 0;
+}
+
+void bsp_usbp2_phy_trim_config(struct bsp_usbp2_priv *priv)
+{
+ unsigned int trim_otp_val;
+ unsigned int reg;
+ void __iomem *phy_trim = NULL;
+
+ if (priv == NULL)
+ return;
+
+ if (priv->trim_flag) {
+ phy_trim = ioremap_nocache(priv->trim_otp_addr, __1K__);
+ if (phy_trim == NULL)
+ return;
+
+ reg = readl(phy_trim);
+ trim_otp_val = (reg & priv->trim_otp_mask);
+ if ((trim_otp_val >= priv->trim_otp_min) &&
+ (trim_otp_val <= priv->trim_otp_max)) {
+ /* set trim value to phy */
+ reg = readl(priv->phy_base + USBP2_PHY_TRIM_OFFSET);
+ reg &= ~USBP2_PHY_TRIM_MASK;
+ reg |= USBP2_PHY_TRIM_VAL(trim_otp_val >> priv->trim_otp_bit_offset);
+ writel(reg, priv->phy_base + USBP2_PHY_TRIM_OFFSET);
+ }
+ iounmap(phy_trim);
+ }
+}
+
+void bsp_usbp2_get_svb_para_1(struct device *dev, struct bsp_usbp2_priv *priv)
+{
+ unsigned int ret;
+
+ if ((dev == NULL) || (priv == NULL))
+ return;
+
+ /* get phy svb parmteters */
+ ret = of_property_read_u32(dev->of_node, "svb_otp_addr", &(priv->svb_otp_addr));
+ if (ret)
+ priv->svb_flag = 0;
+
+ ret = of_property_read_u32(dev->of_node, "svb_otp_predev5_min",
+ &(priv->svb_otp_predev5_min));
+ if (ret)
+ priv->svb_predev5_flag = 0;
+
+ ret = of_property_read_u32(dev->of_node, "svb_otp_predev5_max",
+ &(priv->svb_otp_predev5_max));
+ if (ret)
+ priv->svb_predev5_flag = 0;
+
+ ret = of_property_read_u32(dev->of_node, "svb_phy_predev5_val",
+ &(priv->svb_phy_predev5_val));
+ if (ret)
+ priv->svb_predev5_flag = 0;
+
+ ret = of_property_read_u32(dev->of_node, "svb_otp_predev4_min",
+ &(priv->svb_otp_predev4_min));
+ if (ret)
+ priv->svb_predev4_flag = 0;
+
+ ret = of_property_read_u32(dev->of_node, "svb_otp_predev4_max",
+ &(priv->svb_otp_predev4_max));
+ if (ret)
+ priv->svb_predev4_flag = 0;
+
+ ret = of_property_read_u32(dev->of_node, "svb_phy_predev4_val",
+ &(priv->svb_phy_predev4_val));
+ if (ret)
+ priv->svb_predev4_flag = 0;
+}
+
+void bsp_usbp2_get_svb_para_2(struct device *dev, struct bsp_usbp2_priv *priv)
+{
+ unsigned int ret;
+
+ if ((dev == NULL) || (priv == NULL))
+ return;
+
+ ret = of_property_read_u32(dev->of_node, "svb_otp_predev3_min",
+ &(priv->svb_otp_predev3_min));
+ if (ret)
+ priv->svb_predev3_flag = 0;
+
+ ret = of_property_read_u32(dev->of_node, "svb_otp_predev3_max",
+ &(priv->svb_otp_predev3_max));
+ if (ret)
+ priv->svb_predev3_flag = 0;
+
+ ret = of_property_read_u32(dev->of_node, "svb_phy_predev3_val",
+ &(priv->svb_phy_predev3_val));
+ if (ret)
+ priv->svb_predev3_flag = 0;
+
+ ret = of_property_read_u32(dev->of_node, "svb_otp_predev2_min",
+ &(priv->svb_otp_predev2_min));
+ if (ret)
+ priv->svb_predev2_flag = 0;
+
+ ret = of_property_read_u32(dev->of_node, "svb_otp_predev2_max",
+ &(priv->svb_otp_predev2_max));
+ if (ret)
+ priv->svb_predev2_flag = 0;
+
+ ret = of_property_read_u32(dev->of_node, "svb_phy_predev2_val",
+ &(priv->svb_phy_predev2_val));
+ if (ret)
+ priv->svb_predev2_flag = 0;
+}
+
+void bsp_usbp2_phy_svb_config(struct bsp_usbp2_priv *priv)
+{
+ unsigned int reg;
+ unsigned int ret;
+ void __iomem *phy_svb = NULL;
+
+ if (priv == NULL)
+ return;
+
+ if (priv->svb_flag) {
+ phy_svb = ioremap_nocache(priv->svb_otp_addr, __1K__);
+ if (phy_svb == NULL)
+ return;
+
+ ret = readl(phy_svb);
+ reg = readl(priv->phy_base + USBP2_PHY_SVB_OFFSET);
+ reg &= ~USBP2_PHY_SVB_MASK;
+ if ((ret >= priv->svb_otp_predev5_min) &&
+ (ret < priv->svb_otp_predev5_max) && (priv->svb_predev5_flag))
+ reg |= USBP2_PHY_SVB_VAL(priv->svb_phy_predev5_val);
+ else if ((ret >= priv->svb_otp_predev4_min) &&
+ (ret < priv->svb_otp_predev4_max) && (priv->svb_predev4_flag))
+ reg |= USBP2_PHY_SVB_VAL(priv->svb_phy_predev4_val);
+ else if ((ret >= priv->svb_otp_predev3_min) &&
+ (ret <= priv->svb_otp_predev3_max) && (priv->svb_predev3_flag))
+ reg |= USBP2_PHY_SVB_VAL(priv->svb_phy_predev3_val);
+ else if ((ret > priv->svb_otp_predev2_min) &&
+ (ret <= priv->svb_otp_predev2_max) && (priv->svb_predev2_flag))
+ reg |= USBP2_PHY_SVB_VAL(priv->svb_phy_predev2_val);
+ else
+ reg |= USBP2_PHY_SVB_VAL(priv->svb_phy_predev4_val);
+
+ writel(reg, priv->phy_base + USBP2_PHY_SVB_OFFSET);
+ iounmap(phy_svb);
+ }
+}
+
+static void bsp_usb_vbus_and_pwren_config(struct device *dev, struct bsp_usbp2_priv *priv)
+{
+ unsigned int ret;
+
+ if ((dev == NULL) || (priv == NULL))
+ return;
+
+ /* Some chips do not have VBUS encapsulation and need to be configured */
+ ret = of_property_read_u32(dev->of_node, "vbus_offset", &(priv->vbus_offset));
+ if (ret)
+ priv->vbus_flag = 0;
+
+ ret = of_property_read_u32(dev->of_node, "vbus_val", &(priv->vbus_val));
+ if (ret)
+ priv->vbus_flag = 0;
+
+ /* Some chips do not have PWREN encapsulation and need to be configured */
+ ret = of_property_read_u32(dev->of_node, "pwren_offset", &(priv->pwren_offset));
+ if (ret)
+ priv->pwren_flag = 0;
+
+ ret = of_property_read_u32(dev->of_node, "pwren_val", &(priv->pwren_val));
+ if (ret)
+ priv->pwren_flag = 0;
+
+ if (priv->vbus_flag)
+ writel(priv->vbus_val, priv->pin_base + priv->vbus_offset);
+
+ udelay(U_LEVEL2);
+
+ if (priv->pwren_flag)
+ writel(priv->pwren_val, priv->pin_base + priv->pwren_offset);
+
+ udelay(U_LEVEL2);
+}
+
+static int bsp_usbp2_get_pll_clk(struct device *dev,
+ struct bsp_usbp2_priv *priv)
+{
+ unsigned int ret;
+
+ if ((dev == NULL) || (priv == NULL))
+ return -EINVAL;
+
+ /* Get phy pll clk config parameters from the phy node of the dtsi file */
+ ret = of_property_read_u32(dev->of_node, "phy_pll_offset",
+ &(priv->phy_pll_offset));
+ if (ret) {
+ dev_err(dev, "get phy_pll_offset failed: %d\n", ret);
+ return ret;
+ }
+
+ ret = of_property_read_u32(dev->of_node, "phy_pll_mask", &(priv->phy_pll_mask));
+ if (ret) {
+ dev_err(dev, "get phy_pll_mask failed: %d\n", ret);
+ return ret;
+ }
+
+ ret = of_property_read_u32(dev->of_node, "phy_pll_val", &(priv->phy_pll_val));
+ if (ret) {
+ dev_err(dev, "get phy_pll_val failed: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int bsp_usbp2_set_crg_val(struct device *dev,
+ struct bsp_usbp2_priv *priv)
+{
+ unsigned int ret;
+ unsigned int reg;
+
+ if ((dev == NULL) || (priv == NULL))
+ return -EINVAL;
+
+ /* Get CRG default value from the phy node of the dtsi file */
+ ret = of_property_read_u32(dev->of_node, "crg_offset", &(priv->crg_offset));
+ if (ret) {
+ dev_err(dev, "get crg_offset failed: %d\n", ret);
+ return ret;
+ }
+
+ ret = of_property_read_u32(dev->of_node, "crg_defal_mask",
+ &(priv->crg_defal_mask));
+ if (ret) {
+ dev_err(dev, "get crg_defal_mask failed: %d\n", ret);
+ return ret;
+ }
+
+ ret = of_property_read_u32(dev->of_node, "crg_defal_val",
+ &(priv->crg_defal_val));
+ if (ret) {
+ dev_err(dev, "get crg_defal_val failed: %d\n", ret);
+ return ret;
+ }
+
+ /* write phy crg default value */
+ reg = readl(priv->crg_base + priv->crg_offset);
+ reg &= ~priv->crg_defal_mask;
+ reg |= priv->crg_defal_val;
+ writel(reg, priv->crg_base + priv->crg_offset);
+
+ return 0;
+}
+
+static int bsp_usbp2_phy_get_para(struct device *dev,
+ struct bsp_usbp2_priv *priv)
+{
+ unsigned int ret;
+
+ if ((dev == NULL) || (priv == NULL))
+ return -EINVAL;
+
+ bsp_usbp2_def_all_exist(priv);
+
+ ret = bsp_usbp2_get_pll_clk(dev, priv);
+ if (ret) {
+ dev_err(dev, "get pll clk failed: %d\n", ret);
+ return ret;
+ }
+
+ bsp_usbp2_get_trim_para(dev, priv);
+ bsp_usbp2_get_eye_para(dev, priv);
+ bsp_usbp2_get_svb_para_1(dev, priv);
+ bsp_usbp2_get_svb_para_2(dev, priv);
+
+ return 0;
+}
+
+static int bsp_usbp2_phy_get_clks(struct bsp_usbp2_priv *priv, int count)
+{
+ struct device *dev = priv->dev;
+ struct device_node *np = dev->of_node;
+ int i;
+
+ priv->num_clocks = count;
+
+ if (!count)
+ return 0;
+
+ priv->clks =
+ devm_kcalloc(dev, priv->num_clocks, sizeof(struct clk *), GFP_KERNEL);
+ if (priv->clks == NULL)
+ return -ENOMEM;
+
+ for (i = 0; i < priv->num_clocks; i++) {
+ struct clk *clk;
+
+ clk = of_clk_get(np, i);
+ if (IS_ERR(clk)) {
+ while (--i >= 0)
+ clk_put(priv->clks[i]);
+
+ devm_kfree(dev, priv->clks);
+ priv->clks = NULL;
+ return PTR_ERR(clk);
+ }
+
+ priv->clks[i] = clk;
+ }
+ return 0;
+}
+
+static int bsp_usbp2_clk_rst_config(struct platform_device *pdev,
+ struct bsp_usbp2_priv *priv)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = pdev->dev.of_node;
+ unsigned int ret;
+
+ ret = bsp_usbp2_phy_get_clks(priv, of_clk_get_parent_count(np));
+ if (ret) {
+ dev_err(dev, "get phy clk failed\n");
+ return ret;
+ }
+
+ priv->usb_phy_tpor_rst = devm_reset_control_get(dev, "phy_tpor_reset");
+ if (IS_ERR_OR_NULL(priv->usb_phy_tpor_rst)) {
+ dev_err(dev, "get phy_tpor_reset failed: %d\n", ret);
+ return PTR_ERR(priv->usb_phy_tpor_rst);
+ }
+
+ priv->usb_phy_por_rst = devm_reset_control_get(dev, "phy_por_reset");
+ if (IS_ERR_OR_NULL(priv->usb_phy_por_rst)) {
+ dev_err(dev, "get phy_por_reset failed: %d\n", ret);
+ return PTR_ERR(priv->usb_phy_por_rst);;
+ }
+
+ return 0;
+}
+
+static int bsp_usbp2_iomap(struct device_node *np,
+ struct bsp_usbp2_priv *priv)
+{
+ if ((np == NULL) || (priv == NULL))
+ return -EINVAL;
+
+ priv->phy_base = of_iomap(np, 0);
+ if (IS_ERR(priv->phy_base))
+ return -ENOMEM;
+
+ priv->crg_base = of_iomap(np, 1);
+ if (IS_ERR(priv->crg_base)) {
+ iounmap(priv->phy_base);
+ return -ENOMEM;
+ }
+
+ priv->pin_base = of_iomap(np, 2);
+ if (IS_ERR(priv->pin_base)) {
+ iounmap(priv->phy_base);
+ iounmap(priv->crg_base);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static int bsp_usbp2_phy_init(struct phy *phy)
+{
+ struct bsp_usbp2_priv *priv = phy_get_drvdata(phy);
+ int i, ret;
+ unsigned int reg;
+
+ for (i = 0; i < priv->num_clocks; i++) {
+ ret = clk_prepare_enable(priv->clks[i]);
+ if (ret < 0) {
+ while (--i >= 0) {
+ clk_disable_unprepare(priv->clks[i]);
+ clk_put(priv->clks[i]);
+ }
+ }
+ }
+
+ udelay(U_LEVEL5);
+
+ /* undo por reset */
+ ret = reset_control_deassert(priv->usb_phy_por_rst);
+ if (ret)
+ return ret;
+
+ /* pll out clk */
+ reg = readl(priv->phy_base + priv->phy_pll_offset);
+ reg &= ~priv->phy_pll_mask;
+ reg |= priv->phy_pll_val;
+ writel(reg, priv->phy_base + priv->phy_pll_offset);
+
+ mdelay(M_LEVEL1);
+
+ /* undo tpor reset */
+ ret = reset_control_deassert(priv->usb_phy_tpor_rst);
+ if (ret)
+ return ret;
+
+ udelay(U_LEVEL6);
+
+ bsp_usbp2_phy_eye_config(priv);
+
+ bsp_usbp2_phy_trim_config(priv);
+
+ bsp_usbp2_phy_svb_config(priv);
+ return 0;
+}
+
+static int bsp_usbp2_phy_exit(struct phy *phy)
+{
+ struct bsp_usbp2_priv *priv = phy_get_drvdata(phy);
+ int i, ret;
+
+ for (i = 0; i < priv->num_clocks; i++)
+ clk_disable_unprepare(priv->clks[i]);
+
+ ret = reset_control_assert(priv->usb_phy_por_rst);
+ if (ret)
+ return ret;
+
+ ret = reset_control_assert(priv->usb_phy_tpor_rst);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static const struct phy_ops bsp_usbp2_phy_ops = {
+ .init = bsp_usbp2_phy_init,
+ .exit = bsp_usbp2_phy_exit,
+ .owner = THIS_MODULE,
+};
+
+static int bsp_usbp2_phy_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct phy *phy = NULL;
+ struct bsp_usbp2_priv *priv = NULL;
+ struct device_node *np = pdev->dev.of_node;
+ struct phy_provider *phy_provider = NULL;
+ unsigned int ret;
+
+ phy = devm_phy_create(dev, dev->of_node, &bsp_usbp2_phy_ops);
+ if (IS_ERR(phy))
+ return PTR_ERR(phy);
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (priv == NULL)
+ return -ENOMEM;
+
+ ret = bsp_usbp2_iomap(np, priv);
+ if (ret) {
+ devm_kfree(dev, priv);
+ priv = NULL;
+
+ return -ENOMEM;
+ }
+
+ platform_set_drvdata(pdev, priv);
+ priv->dev = dev;
+
+ ret = bsp_usbp2_clk_rst_config(pdev, priv);
+ if (ret)
+ goto xvp_unmap;
+
+ ret = bsp_usbp2_phy_get_para(dev, priv);
+ if (ret)
+ goto xvp_unmap;
+
+ bsp_usb_vbus_and_pwren_config(dev, priv);
+
+ ret = bsp_usbp2_set_crg_val(dev, priv);
+ if (ret)
+ goto xvp_unmap;
+
+ platform_set_drvdata(pdev, priv);
+ phy_set_drvdata(phy, priv);
+
+ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+ if (IS_ERR(phy_provider)) {
+ ret = PTR_ERR(phy_provider);
+ goto xvp_unmap;
+ }
+
+ return 0;
+xvp_unmap:
+ iounmap(priv->phy_base);
+ iounmap(priv->crg_base);
+ iounmap(priv->pin_base);
+
+ devm_kfree(dev, priv);
+ priv = NULL;
+
+ return ret;
+}
+
+static int bsp_usbp2_phy_remove(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct bsp_usbp2_priv *priv = platform_get_drvdata(pdev);
+ int i;
+
+ for (i = 0; i < priv->num_clocks; i++)
+ clk_put(priv->clks[i]);
+
+ iounmap(priv->phy_base);
+ iounmap(priv->crg_base);
+ iounmap(priv->pin_base);
+
+ devm_kfree(dev, priv);
+ priv = NULL;
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int bsp_usbp2_phy_suspend(struct device *dev)
+{
+ struct phy *phy = dev_get_drvdata(dev);
+
+ if (bsp_usbp2_phy_exit(phy))
+ return -1;
+
+ return 0;
+}
+
+static int bsp_usbp2_phy_resume(struct device *dev)
+{
+ struct phy *phy = dev_get_drvdata(dev);
+
+ if (bsp_usbp2_phy_init(phy))
+ return -1;
+
+ return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static SIMPLE_DEV_PM_OPS(bsp_usb_pm_ops, bsp_usbp2_phy_suspend,
+ bsp_usbp2_phy_resume);
+
+static const struct of_device_id bsp_usbp2_phy_of_match[] = {
+ { .compatible = "goke,usbp2-phy" },
+ {},
+};
+
+static struct platform_driver bsp_usbp2_phy_driver = {
+ .probe = bsp_usbp2_phy_probe,
+ .remove = bsp_usbp2_phy_remove,
+ .driver = {
+ .name = "goke-usbp2-phy",
+ .pm = &bsp_usb_pm_ops,
+ .of_match_table = bsp_usbp2_phy_of_match,
+ }
+};
+module_platform_driver(bsp_usbp2_phy_driver);
+MODULE_DESCRIPTION("GOKE USB PHY driver");
+MODULE_ALIAS("platform:usbp2-phy");
+MODULE_LICENSE("GPL v2");
diff -urN linux-4.9.37/drivers/phy/Kconfig linux-4.9.y/drivers/phy/Kconfig
--- linux-4.9.37/drivers/phy/Kconfig 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/phy/Kconfig 2021-06-07 13:01:34.000000000 +0300
@@ -481,6 +481,7 @@
If unsure, say N.
source "drivers/phy/tegra/Kconfig"
+source "drivers/phy/goke/Kconfig"
config PHY_NS2_PCIE
tristate "Broadcom Northstar2 PCIe PHY driver"
diff -urN linux-4.9.37/drivers/phy/Makefile linux-4.9.y/drivers/phy/Makefile
--- linux-4.9.37/drivers/phy/Makefile 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/phy/Makefile 2021-06-07 13:01:34.000000000 +0300
@@ -59,4 +59,5 @@
obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o
obj-$(CONFIG_PHY_CYGNUS_PCIE) += phy-bcm-cygnus-pcie.o
obj-$(CONFIG_ARCH_TEGRA) += tegra/
+obj-$(CONFIG_ARCH_GOKE) += goke/
obj-$(CONFIG_PHY_NS2_PCIE) += phy-bcm-ns2-pcie.o
diff -urN linux-4.9.37/drivers/power/reset/goke-reboot.c linux-4.9.y/drivers/power/reset/goke-reboot.c
--- linux-4.9.37/drivers/power/reset/goke-reboot.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/power/reset/goke-reboot.c 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/reboot.h>
+
+#include <asm/proc-fns.h>
+
+static void __iomem *base;
+static u32 reboot_offset;
+
+static int bsp_restart_handler(struct notifier_block *this,
+ unsigned long mode, void *cmd)
+{
+ writel_relaxed(0xdeadbeef, base + reboot_offset);
+
+ while (1)
+ cpu_do_idle();
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block bsp_restart_nb = {
+ .notifier_call = bsp_restart_handler,
+ .priority = 128,
+};
+
+static int bsp_reboot_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ int err;
+
+ base = of_iomap(np, 0);
+ if (!base) {
+ WARN(1, "failed to map base address");
+ return -ENODEV;
+ }
+
+ if (of_property_read_u32(np, "reboot-offset", &reboot_offset) < 0) {
+ pr_err("failed to find reboot-offset property\n");
+ iounmap(base);
+ return -EINVAL;
+ }
+
+ err = register_restart_handler(&bsp_restart_nb);
+ if (err) {
+ dev_err(&pdev->dev, "cannot register restart handler (err=%d)\n",
+ err);
+ iounmap(base);
+ }
+
+ return err;
+}
+
+static const struct of_device_id bsp_reboot_of_match[] = {
+ { .compatible = "goke,sysctrl" },
+ {}
+};
+
+static struct platform_driver bsp_reboot_driver = {
+ .probe = bsp_reboot_probe,
+ .driver = {
+ .name = "goke-reboot",
+ .of_match_table = bsp_reboot_of_match,
+ },
+};
+module_platform_driver(bsp_reboot_driver);
diff -urN linux-4.9.37/drivers/power/reset/Kconfig linux-4.9.y/drivers/power/reset/Kconfig
--- linux-4.9.37/drivers/power/reset/Kconfig 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/power/reset/Kconfig 2021-06-07 13:01:34.000000000 +0300
@@ -67,6 +67,12 @@
Say Y here if you have a Broadcom STB board and you wish
to have restart support.
+config POWER_RESET_GOKE
+ bool "Goke power-off driver"
+ depends on ARCH_GOKE
+ help
+ Reboot support for Goke boards.
+
config POWER_RESET_GPIO
bool "GPIO power-off driver"
depends on OF_GPIO
diff -urN linux-4.9.37/drivers/power/reset/Makefile linux-4.9.y/drivers/power/reset/Makefile
--- linux-4.9.37/drivers/power/reset/Makefile 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/power/reset/Makefile 2021-06-07 13:01:34.000000000 +0300
@@ -5,6 +5,7 @@
obj-$(CONFIG_POWER_RESET_AXXIA) += axxia-reset.o
obj-$(CONFIG_POWER_RESET_BRCMKONA) += brcm-kona-reset.o
obj-$(CONFIG_POWER_RESET_BRCMSTB) += brcmstb-reboot.o
+obj-$(CONFIG_POWER_RESET_GOKE) += goke-reboot.o
obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
obj-$(CONFIG_POWER_RESET_GPIO_RESTART) += gpio-restart.o
obj-$(CONFIG_POWER_RESET_HISI) += hisi-reboot.o
diff -urN linux-4.9.37/drivers/pwm/Kconfig linux-4.9.y/drivers/pwm/Kconfig
--- linux-4.9.37/drivers/pwm/Kconfig 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/pwm/Kconfig 2021-06-07 13:01:34.000000000 +0300
@@ -175,6 +175,14 @@
To compile this driver as a module, choose M here: the module
will be called pwm-fsl-ftm.
+config PWM_GOKE
+ tristate "Goke PWM support"
+ help
+ Generic PWM framework driver for Goke SoCs.
+
+ To compile this driver as a module, choose M here: the module
+ will be called pwm-goke.
+
config PWM_IMG
tristate "Imagination Technologies PWM driver"
depends on HAS_IOMEM
diff -urN linux-4.9.37/drivers/pwm/Makefile linux-4.9.y/drivers/pwm/Makefile
--- linux-4.9.37/drivers/pwm/Makefile 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/pwm/Makefile 2021-06-07 13:01:34.000000000 +0300
@@ -15,6 +15,7 @@
obj-$(CONFIG_PWM_CROS_EC) += pwm-cros-ec.o
obj-$(CONFIG_PWM_EP93XX) += pwm-ep93xx.o
obj-$(CONFIG_PWM_FSL_FTM) += pwm-fsl-ftm.o
+obj-$(CONFIG_PWM_GOKE) += pwm-goke.o
obj-$(CONFIG_PWM_IMG) += pwm-img.o
obj-$(CONFIG_PWM_IMX) += pwm-imx.o
obj-$(CONFIG_PWM_JZ4740) += pwm-jz4740.o
diff -urN linux-4.9.37/drivers/pwm/pwm-goke.c linux-4.9.y/drivers/pwm/pwm-goke.c
--- linux-4.9.37/drivers/pwm/pwm-goke.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/pwm/pwm-goke.c 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/reset.h>
+
+#define PWM_CFG0_ADDR(x) (((x)*0x20) + 0x0)
+#define PWM_CFG1_ADDR(x) (((x)*0x20) + 0x4)
+#define PWM_CFG2_ADDR(x) (((x)*0x20) + 0x8)
+#define PWM_CTRL_ADDR(x) (((x)*0x20) + 0xC)
+
+#define PWM_ENABLE_SHIFT 0
+#define PWM_ENABLE_MASK BIT(0)
+
+#define PWM_POLARITY_SHIFT 1
+#define PWM_POLARITY_MASK BIT(1)
+
+#define PWM_KEEP_SHIFT 2
+#define PWM_KEEP_MASK BIT(2)
+
+#define PWM_PERIOD_MASK GENMASK(31, 0)
+#define PWM_DUTY_MASK GENMASK(31, 0)
+
+struct goke_pwm_chip {
+ struct pwm_chip chip;
+ struct clk *clk;
+ void __iomem *base;
+ struct reset_control *rstc;
+};
+
+struct goke_pwm_soc {
+ u32 num_pwms;
+};
+
+static const struct goke_pwm_soc pwm_soc[1] = {
+ { .num_pwms = 2 },
+};
+
+static inline struct goke_pwm_chip *to_goke_pwm_chip(struct pwm_chip *chip)
+{
+ return container_of(chip, struct goke_pwm_chip, chip);
+}
+
+static void goke_pwm_set_bits(void __iomem *base, u32 offset,
+ u32 mask, u32 data)
+{
+ void __iomem *address = base + offset;
+ u32 value;
+
+ value = readl(address);
+ value &= ~mask;
+ value |= (data & mask);
+ writel(value, address);
+}
+
+static void goke_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+ struct goke_pwm_chip *bsp_pwm_chip = to_goke_pwm_chip(chip);
+
+ goke_pwm_set_bits(bsp_pwm_chip->base, PWM_CTRL_ADDR(pwm->hwpwm),
+ PWM_ENABLE_MASK, 0x1);
+}
+
+static void goke_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+ struct goke_pwm_chip *bsp_pwm_chip = to_goke_pwm_chip(chip);
+
+ goke_pwm_set_bits(bsp_pwm_chip->base, PWM_CTRL_ADDR(pwm->hwpwm),
+ PWM_ENABLE_MASK, 0x0);
+}
+
+static void goke_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
+ int duty_cycle_ns, int period_ns)
+{
+ struct goke_pwm_chip *bsp_pwm_chip = to_goke_pwm_chip(chip);
+ u32 duty;
+ u64 period, freq;
+
+ freq = div_u64(clk_get_rate(bsp_pwm_chip->clk), 1000000);
+
+ period = div_u64(freq * period_ns, 1000);
+ duty = div_u64(period * duty_cycle_ns, period_ns);
+
+ goke_pwm_set_bits(bsp_pwm_chip->base, PWM_CFG0_ADDR(pwm->hwpwm),
+ PWM_PERIOD_MASK, period);
+
+ goke_pwm_set_bits(bsp_pwm_chip->base, PWM_CFG1_ADDR(pwm->hwpwm),
+ PWM_DUTY_MASK, duty);
+}
+
+static void goke_pwm_set_polarity(struct pwm_chip *chip,
+ struct pwm_device *pwm,
+ enum pwm_polarity polarity)
+{
+ struct goke_pwm_chip *bsp_pwm_chip = to_goke_pwm_chip(chip);
+
+ if (polarity == PWM_POLARITY_INVERSED)
+ goke_pwm_set_bits(bsp_pwm_chip->base, PWM_CTRL_ADDR(pwm->hwpwm),
+ PWM_POLARITY_MASK, (0x1 << PWM_POLARITY_SHIFT));
+ else
+ goke_pwm_set_bits(bsp_pwm_chip->base, PWM_CTRL_ADDR(pwm->hwpwm),
+ PWM_POLARITY_MASK, (0x0 << PWM_POLARITY_SHIFT));
+}
+
+static void goke_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_state *state) {
+ struct goke_pwm_chip *bsp_pwm_chip = to_goke_pwm_chip(chip);
+ void __iomem *base;
+ u32 freq;
+ u64 value;
+
+ freq = div_u64(clk_get_rate(bsp_pwm_chip->clk), 1000000);
+ base = bsp_pwm_chip->base;
+
+ value = readl(base + PWM_CFG0_ADDR(pwm->hwpwm));
+ state->period = div_u64(value * 1000, freq);
+
+ value = readl(base + PWM_CFG1_ADDR(pwm->hwpwm));
+ state->duty_cycle = div_u64(value * 1000, freq);
+
+ value = readl(base + PWM_CTRL_ADDR(pwm->hwpwm));
+ state->enabled = (PWM_ENABLE_MASK & value);
+}
+
+static int goke_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_state *state)
+{
+ if (state->polarity != pwm->state.polarity) {
+ goke_pwm_set_polarity(chip, pwm, state->polarity);
+ }
+
+ if (state->period != pwm->state.period ||
+ state->duty_cycle != pwm->state.duty_cycle) {
+ goke_pwm_config(chip, pwm, state->duty_cycle, state->period);
+ }
+
+ if (state->enabled != pwm->state.enabled) {
+ if (state->enabled) {
+ goke_pwm_enable(chip, pwm);
+ }
+ else {
+ goke_pwm_disable(chip, pwm);
+ }
+ }
+
+ return 0;
+}
+
+static struct pwm_ops goke_pwm_ops = {
+ .get_state = goke_pwm_get_state,
+ .apply = goke_pwm_apply,
+
+ .owner = THIS_MODULE,
+};
+
+static int goke_pwm_probe(struct platform_device *pdev)
+{
+ const struct goke_pwm_soc *soc =
+ of_device_get_match_data(&pdev->dev);
+ struct goke_pwm_chip *pwm_chip;
+ struct resource *res;
+ int ret;
+ int i;
+
+ pwm_chip = devm_kzalloc(&pdev->dev, sizeof(*pwm_chip), GFP_KERNEL);
+ if (pwm_chip == NULL) {
+ return -ENOMEM;
+ }
+
+ pwm_chip->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(pwm_chip->clk)) {
+ dev_err(&pdev->dev, "getting clock failed with %ld\n",
+ PTR_ERR(pwm_chip->clk));
+ return PTR_ERR(pwm_chip->clk);
+ }
+
+ pwm_chip->chip.ops = &goke_pwm_ops;
+ pwm_chip->chip.dev = &pdev->dev;
+ pwm_chip->chip.base = -1;
+ pwm_chip->chip.npwm = soc->num_pwms;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ pwm_chip->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(pwm_chip->base)) {
+ return PTR_ERR(pwm_chip->base);
+ }
+
+ ret = clk_prepare_enable(pwm_chip->clk);
+ if (ret < 0) {
+ return ret;
+ }
+
+ pwm_chip->rstc = devm_reset_control_get(&pdev->dev, NULL);
+ if (IS_ERR(pwm_chip->rstc)) {
+ clk_disable_unprepare(pwm_chip->clk);
+ return PTR_ERR(pwm_chip->rstc);
+ }
+
+ reset_control_assert(pwm_chip->rstc);
+ msleep(30);
+ reset_control_deassert(pwm_chip->rstc);
+
+ ret = pwmchip_add(&pwm_chip->chip);
+ if (ret < 0) {
+ clk_disable_unprepare(pwm_chip->clk);
+ return ret;
+ }
+
+ for (i = 0; i < pwm_chip->chip.npwm; i++) {
+ goke_pwm_set_bits(pwm_chip->base, PWM_CTRL_ADDR(i),
+ PWM_KEEP_MASK, (0x1 << PWM_KEEP_SHIFT));
+ }
+
+ platform_set_drvdata(pdev, pwm_chip);
+
+ return 0;
+}
+
+static int goke_pwm_remove(struct platform_device *pdev)
+{
+ struct goke_pwm_chip *pwm_chip;
+
+ pwm_chip = platform_get_drvdata(pdev);
+
+ reset_control_assert(pwm_chip->rstc);
+ msleep(30);
+ reset_control_deassert(pwm_chip->rstc);
+
+ clk_disable_unprepare(pwm_chip->clk);
+
+ return pwmchip_remove(&pwm_chip->chip);
+}
+
+static const struct of_device_id goke_pwm_of_match[] = {
+ { .compatible = "goke,goke-pwm" },
+ { .compatible = "goke,pwm", .data = &pwm_soc[0] }, {}
+};
+MODULE_DEVICE_TABLE(of, goke_pwm_of_match);
+
+static struct platform_driver goke_pwm_driver = {
+ .driver = {
+ .name = "goke-pwm",
+ .of_match_table = goke_pwm_of_match,
+ },
+ .probe = goke_pwm_probe,
+ .remove = goke_pwm_remove,
+};
+module_platform_driver(goke_pwm_driver);
+
+MODULE_AUTHOR("Goke");
+MODULE_DESCRIPTION("Goke SoCs PWM driver");
+MODULE_LICENSE("GPL");
diff -urN linux-4.9.37/drivers/rtc/Kconfig linux-4.9.y/drivers/rtc/Kconfig
--- linux-4.9.37/drivers/rtc/Kconfig 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/rtc/Kconfig 2021-06-07 13:01:34.000000000 +0300
@@ -3,7 +3,7 @@
#
config RTC_LIB
- bool
+ bool "Real Time Clock LIB"
config RTC_MC146818_LIB
bool
@@ -824,6 +824,14 @@
# requires <asm/mc146818rtc.h> defining CMOS_READ/CMOS_WRITE, and a
# global rtc_lock ... it's not yet just another platform_device.
+config RTC_DRV_GOKE
+ tristate "Goke RTC support"
+ help
+ Generic RTC framework driver for Goke SoCs.
+
+ To compile this driver as a module, choose M here: the module
+ will be called rtc.
+
config RTC_DRV_CMOS
tristate "PC-style 'CMOS'"
depends on X86 || ARM || M32R || PPC || MIPS || SPARC64 || MN10300
diff -urN linux-4.9.37/drivers/rtc/Makefile linux-4.9.y/drivers/rtc/Makefile
--- linux-4.9.37/drivers/rtc/Makefile 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/rtc/Makefile 2021-06-07 13:01:34.000000000 +0300
@@ -68,6 +68,7 @@
obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o
obj-$(CONFIG_RTC_DRV_GEMINI) += rtc-gemini.o
obj-$(CONFIG_RTC_DRV_GENERIC) += rtc-generic.o
+obj-$(CONFIG_RTC_DRV_GOKE) += rtc-goke.o
obj-$(CONFIG_RTC_DRV_HID_SENSOR_TIME) += rtc-hid-sensor-time.o
obj-$(CONFIG_RTC_DRV_HYM8563) += rtc-hym8563.o
obj-$(CONFIG_RTC_DRV_IMXDI) += rtc-imxdi.o
diff -urN linux-4.9.37/drivers/rtc/rtc-goke.c linux-4.9.y/drivers/rtc/rtc-goke.c
--- linux-4.9.37/drivers/rtc/rtc-goke.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/rtc/rtc-goke.c 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,586 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#include <linux/bcd.h>
+#include <linux/bitops.h>
+#include <linux/log2.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/rtc.h>
+#include <linux/version.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+union u_spi_rw {
+ struct {
+ unsigned int spi_wdata : 8; /* [7:0] */
+ unsigned int spi_rdata : 8; /* [15:8] */
+ unsigned int spi_addr : 7; /* [22:16] */
+ unsigned int spi_rw : 1; /* [23] */
+ unsigned int spi_start : 1; /* [24] */
+ unsigned int reserved : 6; /* [30:25] */
+ unsigned int spi_busy : 1; /* [31] */
+ } bits;
+ unsigned int u32;
+};
+
+#define SPI_CLK_DIV (0x000)
+#define SPI_RW (0x004)
+
+#define SPI_WRITE (0)
+#define SPI_READ (1)
+
+/* RTC REG */
+#define RTC_10MS_COUN 0x00
+#define RTC_S_COUNT 0x01
+#define RTC_M_COUNT 0x02
+#define RTC_H_COUNT 0x03
+#define RTC_D_COUNT_L 0x04
+#define RTC_D_COUNT_H 0x05
+
+#define RTC_MR_10MS 0x06
+#define RTC_MR_S 0x07
+#define RTC_MR_M 0x08
+#define RTC_MR_H 0x09
+#define RTC_MR_D_L 0x0A
+#define RTC_MR_D_H 0x0B
+
+#define RTC_LR_10MS 0x0C
+#define RTC_LR_S 0x0D
+#define RTC_LR_M 0x0E
+#define RTC_LR_H 0x0F
+#define RTC_LR_D_L 0x10
+#define RTC_LR_D_H 0x11
+
+#define RTC_LORD 0x12
+
+#define RTC_IMSC 0x13
+#define RTC_INT_CLR 0x14
+#define RTC_INT 0x15
+#define RTC_INT_RAW 0x16
+
+#define RTC_CLK 0x17
+#define RTC_POR_N 0x18
+#define RTC_SAR_CTRL 0x1A
+#define RTC_CLK_CFG 0x1B
+
+#define RTC_FREQ_H 0x51
+#define RTC_FREQ_L 0x52
+
+#if defined(CONFIG_ARCH_GK7205V200) || defined(CONFIG_ARCH_GK7205V300) || \
+ defined(CONFIG_ARCH_GK7202V300) || defined(CONFIG_ARCH_GK7605V100)
+
+#define RTC_REG_LOCK1 0x64
+#define RTC_REG_LOCK2 0x65
+#define RTC_REG_LOCK3 0x66
+#define RTC_REG_LOCK4 0x67
+#endif
+
+
+#define FREQ_H_DEFAULT 0x8
+#define FREQ_L_DEFAULT 0x1B
+
+#define LV_CTL_DEFAULT 0x20
+#define CLK_DIV_DEFAULT 0x4
+#define INT_RST_DEFAULT 0x0
+#define INT_MSK_DEFAULT 0x4
+
+#define AIE_INT_MASK BIT(0)
+#define LV_INT_MASK BIT(1)
+#define REG_LOAD_STAT BIT(0)
+#define REG_LOCK_STAT BIT(1)
+#define REG_LOCK_BYPASS BIT(2)
+
+#define RTC_RW_RETRY_CNT 5
+#define SPI_RW_RETRY_CNT 500
+#define RTC_SLEEP_TIME_MS 20
+
+#define DATE_TO_SEC(d, h, m, s) (s + m*60 + h*60*60 + d*24*60*60)
+#define SEC_TO_DAY(s) (s/(60*60*24))
+
+struct goke_rtc {
+ struct rtc_device *rtc_dev;
+ void __iomem *regs;
+ int rtc_irq;
+};
+
+static int goke_spi_write(void *spi_reg, unsigned char reg,
+ unsigned char val)
+{
+ union u_spi_rw w_data, r_data;
+ int cnt = SPI_RW_RETRY_CNT;
+
+ r_data.u32 = 0;
+ w_data.u32 = 0;
+
+ w_data.bits.spi_wdata = val;
+ w_data.bits.spi_addr = reg;
+ w_data.bits.spi_rw = SPI_WRITE;
+ w_data.bits.spi_start = 0x1;
+
+ writel(w_data.u32, (spi_reg+SPI_RW));
+
+ do
+ r_data.u32 = readl(spi_reg+SPI_RW);
+ while (r_data.bits.spi_busy && (--cnt));
+
+ if (r_data.bits.spi_busy)
+ return -EIO;
+
+ return 0;
+}
+
+
+static int goke_spi_rtc_write(void *spi_reg, unsigned char reg,
+ unsigned char val)
+{
+ return goke_spi_write(spi_reg, reg, val);
+}
+
+static int goke_spi_read(void *spi_reg, unsigned char reg,
+ unsigned char *val)
+{
+ union u_spi_rw w_data, r_data;
+ int cnt = SPI_RW_RETRY_CNT;
+
+ r_data.u32 = 0;
+ w_data.u32 = 0;
+ w_data.bits.spi_addr = reg;
+ w_data.bits.spi_rw = SPI_READ;
+ w_data.bits.spi_start = 0x1;
+
+ writel(w_data.u32, (spi_reg+SPI_RW));
+
+ do
+ r_data.u32 = readl(spi_reg+SPI_RW);
+ while (r_data.bits.spi_busy && (--cnt));
+
+ if (r_data.bits.spi_busy)
+ return -EIO;
+
+ *val = r_data.bits.spi_rdata;
+
+ return 0;
+}
+
+static int goke_spi_rtc_read(void *spi_reg, unsigned char reg,
+ unsigned char *val)
+{
+ return goke_spi_read(spi_reg, reg, val);
+}
+
+static int goke_rtc_read_time(struct device *dev, struct rtc_time *time)
+{
+ struct goke_rtc *rtc = dev_get_drvdata(dev);
+ unsigned char dayl = 0, dayh = 0;
+ unsigned char second = 0, minute = 0, hour = 0;
+ unsigned long seconds = 0;
+ unsigned int day = 0;
+ unsigned char raw_value = 0;
+ int cnt = RTC_RW_RETRY_CNT;
+ unsigned int ret = 0;
+
+ ret = (unsigned int)goke_spi_rtc_read(rtc->regs, RTC_INT_RAW, &raw_value);
+ if (ret) {
+ dev_err(dev, "IO err.\n");
+ return ret;
+ }
+
+ if (raw_value & LV_INT_MASK) {
+ //dev_err(dev, "low voltage detected, date/time is not reliable.\n");
+ (unsigned int)goke_spi_write(rtc->regs, RTC_INT_CLR, 1);
+ //return -EINVAL;
+ }
+
+ ret |= (unsigned int)goke_spi_rtc_read(rtc->regs, RTC_LORD, &raw_value);
+ if (raw_value & REG_LOCK_BYPASS)
+ ret |= (unsigned int)goke_spi_rtc_write(rtc->regs, RTC_LORD,
+ (~(REG_LOCK_BYPASS)) & raw_value);
+
+ ret |= (unsigned int)goke_spi_rtc_read(rtc->regs, RTC_LORD, &raw_value);
+ /* lock the time */
+ ret |= (unsigned int)goke_spi_rtc_write(rtc->regs, RTC_LORD,
+ (REG_LOCK_STAT) | raw_value);
+ /* wait rtc load flag */
+ do {
+ ret |= (unsigned int)goke_spi_rtc_read(rtc->regs, RTC_LORD, &raw_value);
+ msleep(RTC_SLEEP_TIME_MS);
+ } while ((ret || (raw_value & REG_LOCK_STAT)) && (--cnt));
+
+ if (!ret && (raw_value & REG_LOCK_STAT))
+ return -EBUSY;
+
+ ret |= (unsigned int)goke_spi_rtc_read(rtc->regs, RTC_S_COUNT, &second);
+ ret |= (unsigned int)goke_spi_rtc_read(rtc->regs, RTC_M_COUNT, &minute);
+ ret |= (unsigned int)goke_spi_rtc_read(rtc->regs, RTC_H_COUNT, &hour);
+ ret |= (unsigned int)goke_spi_rtc_read(rtc->regs, RTC_D_COUNT_L, &dayl);
+ ret |= (unsigned int)goke_spi_rtc_read(rtc->regs, RTC_D_COUNT_H, &dayh);
+
+ if (ret) {
+ dev_err(dev, "IO err.\n");
+ return ret;
+ }
+
+ day = (dayl | (dayh << 8));
+ seconds = DATE_TO_SEC(day, hour, minute, second);
+
+ rtc_time_to_tm(seconds, time);
+
+ return rtc_valid_tm(time);
+}
+
+static int goke_rtc_set_time(struct device *dev, struct rtc_time *time)
+{
+ struct goke_rtc *rtc = dev_get_drvdata(dev);
+ unsigned int ret = 0;
+ unsigned int days;
+ unsigned long seconds = 0;
+ unsigned int cnt = RTC_RW_RETRY_CNT;
+ unsigned char raw_value = 0;
+
+ ret = rtc_tm_to_time(time, &seconds);
+ if (ret)
+ return ret;
+ days = SEC_TO_DAY(seconds);
+
+ ret |= (unsigned int)goke_spi_rtc_write(rtc->regs, RTC_LR_10MS, 0);
+ ret |= (unsigned int)goke_spi_rtc_write(rtc->regs, RTC_LR_S, time->tm_sec);
+ ret |= (unsigned int)goke_spi_rtc_write(rtc->regs, RTC_LR_M, time->tm_min);
+ ret |= (unsigned int)goke_spi_rtc_write(rtc->regs, RTC_LR_H, time->tm_hour);
+ ret |= (unsigned int)goke_spi_rtc_write(rtc->regs, RTC_LR_D_L, (days & 0xFF));
+ ret |= (unsigned int)goke_spi_rtc_write(rtc->regs, RTC_LR_D_H, (days >> 8));
+
+ ret |= (unsigned int)goke_spi_rtc_write(rtc->regs, RTC_LORD,
+ (raw_value | REG_LOAD_STAT));
+ /* wait rtc load flag */
+ do {
+ ret |= (unsigned int)goke_spi_rtc_read(rtc->regs, RTC_LORD, &raw_value);
+ msleep(RTC_SLEEP_TIME_MS);
+ } while ((ret || (raw_value & REG_LOAD_STAT)) && (--cnt));
+
+ if (!ret && (raw_value & REG_LOAD_STAT))
+ return -EBUSY;
+
+ if (ret)
+ dev_err(dev, "IO err.\n");
+
+ return ret;
+}
+
+static int goke_rtc_read_alarm(struct device *dev,
+ struct rtc_wkalrm *alrm)
+{
+ struct goke_rtc *rtc = dev_get_drvdata(dev);
+ unsigned char dayl = 0, dayh = 0;
+ unsigned char second = 0, minute = 0, hour = 0;
+ unsigned long seconds = 0;
+ unsigned int day = 0;
+ unsigned char int_state = 0;
+ unsigned int ret = 0;
+
+ memset(alrm, 0, sizeof(struct rtc_wkalrm));
+
+ ret |= (unsigned int)goke_spi_rtc_read(rtc->regs, RTC_MR_S, &second);
+ ret |= (unsigned int)goke_spi_rtc_read(rtc->regs, RTC_MR_M, &minute);
+ ret |= (unsigned int)goke_spi_rtc_read(rtc->regs, RTC_MR_H, &hour);
+ ret |= (unsigned int)goke_spi_rtc_read(rtc->regs, RTC_MR_D_L, &dayl);
+ ret |= (unsigned int)goke_spi_rtc_read(rtc->regs, RTC_MR_D_H, &dayh);
+
+ day = (unsigned int)(dayl | (dayh << 8));
+ seconds = DATE_TO_SEC(day, hour, minute, second);
+
+ rtc_time_to_tm(seconds, &alrm->time);
+
+ ret |= (unsigned int)goke_spi_rtc_read(rtc->regs, RTC_IMSC, &int_state);
+ if (ret) {
+ dev_err(dev, "IO err.\n");
+ return ret;
+ }
+
+ alrm->enabled = !!(int_state & AIE_INT_MASK);
+ alrm->pending = alrm->enabled;
+
+ return 0;
+}
+
+static int goke_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct goke_rtc *rtc = dev_get_drvdata(dev);
+ unsigned int days;
+ unsigned long seconds = 0;
+ unsigned char val = 0;
+ unsigned int ret = 0;
+
+ rtc_tm_to_time(&alrm->time, &seconds);
+
+ days = SEC_TO_DAY(seconds);
+
+ ret |= (unsigned int)goke_spi_rtc_write(rtc->regs, RTC_MR_10MS, 0);
+ ret |= (unsigned int)goke_spi_rtc_write(rtc->regs, RTC_MR_S, alrm->time.tm_sec);
+ ret |= (unsigned int)goke_spi_rtc_write(rtc->regs, RTC_MR_M, alrm->time.tm_min);
+ ret |= (unsigned int)goke_spi_rtc_write(rtc->regs, RTC_MR_H, alrm->time.tm_hour);
+ ret |= (unsigned int)goke_spi_rtc_write(rtc->regs, RTC_MR_D_L, (days & 0xFF));
+ ret |= (unsigned int)goke_spi_rtc_write(rtc->regs, RTC_MR_D_H, (days >> 8));
+
+ ret |= (unsigned int)goke_spi_rtc_read(rtc->regs, RTC_IMSC, &val);
+ if (alrm->enabled)
+ ret |= (unsigned int)goke_spi_rtc_write(rtc->regs, RTC_IMSC,
+ val | AIE_INT_MASK);
+ else
+ ret |= (unsigned int)goke_spi_rtc_write(rtc->regs, RTC_IMSC,
+ val & ~AIE_INT_MASK);
+
+ if (ret) {
+ dev_err(dev, "IO err.\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int goke_rtc_alarm_irq_enable(struct device *dev,
+ unsigned int enabled)
+{
+ struct goke_rtc *rtc = dev_get_drvdata(dev);
+ unsigned char val = 0;
+ unsigned int ret = 0;
+
+ ret |= (unsigned int)goke_spi_rtc_read(rtc->regs, RTC_IMSC, &val);
+ if (enabled)
+ ret |= (unsigned int)goke_spi_rtc_write(rtc->regs, RTC_IMSC,
+ val | AIE_INT_MASK);
+ else
+ ret |= (unsigned int)goke_spi_rtc_write(rtc->regs, RTC_IMSC,
+ val & ~AIE_INT_MASK);
+
+ if (ret) {
+ dev_err(dev, "IO err.\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+
+/*
+ * interrupt function
+ * do nothing. left for future
+ */
+static irqreturn_t goke_rtc_alm_interrupt(int irq, void *data)
+{
+ struct goke_rtc *rtc = (struct goke_rtc *)data;
+ unsigned char val = 0;
+ unsigned int ret = 0;
+
+ ret |= (unsigned int)goke_spi_read(rtc->regs, RTC_INT, &val);
+ ret |= (unsigned int)goke_spi_write(rtc->regs, RTC_INT_CLR, AIE_INT_MASK);
+
+ if (ret) {
+ dev_err(&rtc->rtc_dev->dev, "IO err.\n");
+ return ret;
+ }
+
+ if (val & AIE_INT_MASK)
+ rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF);
+
+ return IRQ_HANDLED;
+}
+
+#define FREQ_MAX_VAL 3277000
+#define FREQ_MIN_VAL 3276000
+
+static int goke_rtc_ioctl(struct device *dev,
+ unsigned int cmd, unsigned long arg)
+{
+ struct goke_rtc *rtc = dev_get_drvdata(dev);
+ unsigned int ret = 0;
+
+ switch (cmd) {
+ case RTC_PLL_SET: {
+ char freq_l, freq_h;
+ struct rtc_pll_info pll_info;
+
+ if (copy_from_user(&pll_info, (struct rtc_pll_info *)(uintptr_t)arg,
+ sizeof(struct rtc_pll_info)))
+ return -EFAULT;
+
+ /* freq = 32700 + (freq /3052)*100 */
+ if (pll_info.pll_value > FREQ_MAX_VAL
+ || pll_info.pll_value < FREQ_MIN_VAL)
+ return -EINVAL;
+
+ pll_info.pll_value = (pll_info.pll_value - 3270000)
+ * 3052 / 10000;
+
+ freq_l = (char)((unsigned int)pll_info.pll_value & 0xff);
+ freq_h = (char)(((unsigned int)pll_info.pll_value >> 8) & 0xf);
+
+ ret |= (unsigned int)goke_spi_rtc_write(rtc->regs, RTC_FREQ_H, freq_h);
+ ret |= (unsigned int)goke_spi_rtc_write(rtc->regs, RTC_FREQ_L, freq_l);
+
+ if (ret) {
+ dev_err(dev, "IO err.\n");
+ return ret;
+ }
+
+ return 0;
+ }
+ case RTC_PLL_GET: {
+ char freq_l, freq_h;
+ struct rtc_pll_info pll_info;
+
+ ret |= (unsigned int)goke_spi_rtc_read(rtc->regs, RTC_FREQ_H, &freq_h);
+ ret |= (unsigned int)goke_spi_rtc_read(rtc->regs, RTC_FREQ_L, &freq_l);
+
+ if (ret) {
+ dev_err(dev, "IO err.\n");
+ return ret;
+ }
+
+ pll_info.pll_value = (((unsigned char)freq_h & 0xf) << 8) + freq_l;
+ pll_info.pll_value = 3270000
+ + (pll_info.pll_value * 10000) / 3052;
+
+ pll_info.pll_max = FREQ_MAX_VAL;
+ pll_info.pll_min = FREQ_MIN_VAL;
+
+ if (copy_to_user((void __user *)(uintptr_t)arg,
+ &pll_info, sizeof(struct rtc_pll_info)))
+ return -EFAULT;
+
+ return 0;
+ }
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
+static const struct rtc_class_ops goke_rtc_ops = {
+ .read_time = goke_rtc_read_time,
+ .set_time = goke_rtc_set_time,
+ .read_alarm = goke_rtc_read_alarm,
+ .set_alarm = goke_rtc_set_alarm,
+ .alarm_irq_enable = goke_rtc_alarm_irq_enable,
+ .ioctl = goke_rtc_ioctl,
+};
+
+static int goke_rtc_init(struct goke_rtc *rtc)
+{
+ void *spi_reg = rtc->regs;
+ unsigned int ret = 0;
+ unsigned char val = 0;
+ /*
+ * clk div value = (apb_clk/spi_clk)/2-1,
+ * apb clk = 100MHz, spi_clk = 10MHz,so value= 0x4
+ */
+ writel(CLK_DIV_DEFAULT, (spi_reg+SPI_CLK_DIV));
+
+ ret |= (unsigned int)goke_spi_rtc_write(spi_reg, RTC_IMSC, INT_MSK_DEFAULT);
+ ret |= (unsigned int)goke_spi_rtc_write(spi_reg, RTC_SAR_CTRL, LV_CTL_DEFAULT);
+
+#if defined(CONFIG_ARCH_GK7205V200) || defined(CONFIG_ARCH_GK7205V300) || \
+ defined(CONFIG_ARCH_GK7202V300) || defined(CONFIG_ARCH_GK7605V100)
+ /* default driver capability */
+ ret |= (unsigned int)goke_spi_rtc_write(spi_reg, RTC_REG_LOCK4, 0x5A);
+ ret |= (unsigned int)goke_spi_rtc_write(spi_reg, RTC_REG_LOCK3, 0x5A);
+ ret |= (unsigned int)goke_spi_rtc_write(spi_reg, RTC_REG_LOCK2, 0xAB);
+ ret |= (unsigned int)goke_spi_rtc_write(spi_reg, RTC_REG_LOCK1, 0xCD);
+#endif
+
+ /*driver capability */
+ ret |= (unsigned int)goke_spi_rtc_write(spi_reg, RTC_CLK_CFG, 0x01);
+
+ /* default FREQ COEF */
+ ret |= (unsigned int)goke_spi_rtc_write(spi_reg, RTC_FREQ_H, FREQ_H_DEFAULT);
+ ret |= (unsigned int)goke_spi_rtc_write(spi_reg, RTC_FREQ_L, FREQ_L_DEFAULT);
+
+ ret |= (unsigned int)goke_spi_rtc_read(spi_reg, RTC_INT_RAW, &val);
+ if (ret) {
+ dev_err(&rtc->rtc_dev->dev, "IO err.\n");
+ return ret;
+ }
+
+ if (val & LV_INT_MASK) {
+ /* dev_err(&rtc->rtc_dev->dev,
+ "low voltage detected, date/time is not reliable.\n"); */
+ goke_spi_write(rtc->regs, RTC_INT_CLR, 1);
+ }
+
+ return ret;
+}
+
+static int goke_rtc_probe(struct platform_device *pdev)
+{
+ struct resource *mem = NULL;
+ struct goke_rtc *rtc;
+ int ret;
+
+ rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
+ if (!rtc)
+ return -ENOMEM;
+
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ rtc->regs = devm_ioremap_resource(&pdev->dev, mem);
+ if (IS_ERR((const void *)rtc->regs)) {
+ dev_err(&pdev->dev, "could not map I/O memory\n");
+ return PTR_ERR((const void *)rtc->regs);
+ }
+
+ rtc->rtc_irq = platform_get_irq(pdev, 0);
+ ret = devm_request_irq(&pdev->dev, rtc->rtc_irq,
+ goke_rtc_alm_interrupt, 0, pdev->name, rtc);
+ if (ret) {
+ dev_err(&pdev->dev, "could not request irq %d\n", rtc->rtc_irq);
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, rtc);
+ rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, pdev->name,
+ &goke_rtc_ops, THIS_MODULE);
+ if (IS_ERR(rtc->rtc_dev)) {
+ dev_err(&pdev->dev, "could not register rtc device\n");
+ return PTR_ERR(rtc->rtc_dev);
+ }
+
+ if (goke_rtc_init(rtc)) {
+ dev_err(&pdev->dev, "goke_rtc_init failed.\n");
+ return -EIO;
+ }
+
+ dev_info(&pdev->dev, "RTC driver for goke enabled\n");
+
+ return 0;
+}
+
+static int goke_rtc_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static const struct of_device_id goke_rtc_match[] = {
+ { .compatible = "goke,rtc" },
+ {},
+};
+
+static struct platform_driver goke_rtc_driver = {
+ .probe = goke_rtc_probe,
+ .remove = goke_rtc_remove,
+ .driver = {
+ .name = "goke_rtc",
+ .of_match_table = goke_rtc_match,
+ },
+};
+
+module_platform_driver(goke_rtc_driver);
+
+
+MODULE_AUTHOR("Goke");
+MODULE_DESCRIPTION("Goke RTC driver");
+MODULE_LICENSE("GPL v2");
+
diff -urN linux-4.9.37/drivers/scsi/aic7xxx/.gitignore linux-4.9.y/drivers/scsi/aic7xxx/.gitignore
--- linux-4.9.37/drivers/scsi/aic7xxx/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/scsi/aic7xxx/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,6 +0,0 @@
-aic79xx_reg.h
-aic79xx_reg_print.c
-aic79xx_seq.h
-aic7xxx_reg.h
-aic7xxx_reg_print.c
-aic7xxx_seq.h
diff -urN linux-4.9.37/drivers/scsi/.gitignore linux-4.9.y/drivers/scsi/.gitignore
--- linux-4.9.37/drivers/scsi/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/scsi/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-53c700_d.h
diff -urN linux-4.9.37/drivers/scsi/scsi_lib.c linux-4.9.y/drivers/scsi/scsi_lib.c
--- linux-4.9.37/drivers/scsi/scsi_lib.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/scsi/scsi_lib.c 2021-06-07 13:01:34.000000000 +0300
@@ -1420,7 +1420,7 @@
if (scsi_host_in_recovery(shost))
return 0;
- busy = atomic_inc_return(&shost->host_busy) - 1;
+ busy = atomic_read(&shost->host_busy);
if (atomic_read(&shost->host_blocked) > 0) {
if (busy)
goto starved;
@@ -1429,7 +1429,7 @@
* unblock after host_blocked iterates to zero
*/
if (atomic_dec_return(&shost->host_blocked) > 0)
- goto out_dec;
+ goto out;
SCSI_LOG_MLQUEUE(3,
shost_printk(KERN_INFO, shost,
@@ -1449,6 +1449,7 @@
spin_unlock_irq(shost->host_lock);
}
+ atomic_inc(&shost->host_busy);
return 1;
starved:
@@ -1456,8 +1457,7 @@
if (list_empty(&sdev->starved_entry))
list_add_tail(&sdev->starved_entry, &shost->starved_list);
spin_unlock_irq(shost->host_lock);
-out_dec:
- atomic_dec(&shost->host_busy);
+out:
return 0;
}
diff -urN linux-4.9.37/drivers/spi/spi.c linux-4.9.y/drivers/spi/spi.c
--- linux-4.9.37/drivers/spi/spi.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/spi/spi.c 2021-06-07 13:01:34.000000000 +0300
@@ -323,11 +323,125 @@
return 0;
}
+#ifdef CONFIG_PM_SLEEP
+static int spi_legacy_suspend(struct device *dev, pm_message_t message)
+{
+ int value = 0;
+ struct spi_driver *drv = to_spi_driver(dev->driver);
+
+ /* suspend will stop irqs and dma; no more i/o */
+ if (drv) {
+ if (drv->suspend)
+ value = drv->suspend(to_spi_device(dev), message);
+ else
+ dev_dbg(dev, "... can't suspend\n");
+ }
+ return value;
+}
+
+static int spi_legacy_resume(struct device *dev)
+{
+ int value = 0;
+ struct spi_driver *drv = to_spi_driver(dev->driver);
+
+ /* resume may restart the i/o queue */
+ if (drv) {
+ if (drv->resume)
+ value = drv->resume(to_spi_device(dev));
+ else
+ dev_dbg(dev, "... can't resume\n");
+ }
+ return value;
+}
+
+static int spi_pm_suspend(struct device *dev)
+{
+ const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+
+ if (pm)
+ return pm_generic_suspend(dev);
+ else
+ return spi_legacy_suspend(dev, PMSG_SUSPEND);
+}
+
+static int spi_pm_resume(struct device *dev)
+{
+ const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+
+ if (pm)
+ return pm_generic_resume(dev);
+ else
+ return spi_legacy_resume(dev);
+}
+
+static int spi_pm_freeze(struct device *dev)
+{
+ const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+
+ if (pm)
+ return pm_generic_freeze(dev);
+ else
+ return spi_legacy_suspend(dev, PMSG_FREEZE);
+}
+
+static int spi_pm_thaw(struct device *dev)
+{
+ const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+
+ if (pm)
+ return pm_generic_thaw(dev);
+ else
+ return spi_legacy_resume(dev);
+}
+
+static int spi_pm_poweroff(struct device *dev)
+{
+ const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+
+ if (pm)
+ return pm_generic_poweroff(dev);
+ else
+ return spi_legacy_suspend(dev, PMSG_HIBERNATE);
+}
+
+static int spi_pm_restore(struct device *dev)
+{
+ const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+
+ if (pm)
+ return pm_generic_restore(dev);
+ else
+ return spi_legacy_resume(dev);
+}
+#else
+#define spi_pm_suspend NULL
+#define spi_pm_resume NULL
+#define spi_pm_freeze NULL
+#define spi_pm_thaw NULL
+#define spi_pm_poweroff NULL
+#define spi_pm_restore NULL
+#endif
+
+static const struct dev_pm_ops spi_pm = {
+ .suspend = spi_pm_suspend,
+ .resume = spi_pm_resume,
+ .freeze = spi_pm_freeze,
+ .thaw = spi_pm_thaw,
+ .poweroff = spi_pm_poweroff,
+ .restore = spi_pm_restore,
+ SET_RUNTIME_PM_OPS(
+ pm_generic_runtime_suspend,
+ pm_generic_runtime_resume,
+ NULL
+ )
+};
+
struct bus_type spi_bus_type = {
.name = "spi",
.dev_groups = spi_dev_groups,
.match = spi_match_device,
.uevent = spi_uevent,
+ .pm = &spi_pm,
};
EXPORT_SYMBOL_GPL(spi_bus_type);
diff -urN linux-4.9.37/drivers/spi/spi-pl022.c linux-4.9.y/drivers/spi/spi-pl022.c
--- linux-4.9.37/drivers/spi/spi-pl022.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/spi/spi-pl022.c 2021-06-07 13:01:34.000000000 +0300
@@ -43,6 +43,7 @@
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/pinctrl/consumer.h>
+#include <linux/of_address.h>
/*
* This macro is used to define some register default values.
@@ -136,6 +137,18 @@
/* This one is only in the PL023 variant */
#define SSP_CR1_MASK_FBCLKDEL_ST (0x7UL << 13)
+#ifdef CONFIG_ARCH_GOKE
+/*
+ * The Goke version of this block adds some bits
+ * in SSP_CR1
+ */
+#define SSP_CR1_MASK_BIGEND_GOKE (0x1UL << 4)
+#define SSP_CR1_MASK_ALTASENS_GOKE (0x1UL << 6)
+
+#define SSP_TX_FIFO_CR(r) (r + 0x28)
+#define SSP_RX_FIFO_CR(r) (r + 0x2C)
+#endif
+
/*
* SSP Status Register - SSP_SR
*/
@@ -296,6 +309,10 @@
#define SPI_POLLING_TIMEOUT 1000
+#ifdef CONFIG_ARCH_GOKE
+#define PL022_IDS_INDEX_GOKE 4
+#endif
+
/*
* The type of reading going on on this chip
*/
@@ -337,6 +354,15 @@
bool internal_cs_ctrl;
};
+#ifdef CONFIG_ARCH_GOKE
+struct cs_data {
+ struct resource res;
+ void __iomem *virt_addr;
+ unsigned int cs_sb;
+ unsigned int cs_mask_bit;
+};
+#endif
+
/**
* struct pl022 - This is the private SSP driver data structure
* @adev: AMBA device model hookup
@@ -346,6 +372,13 @@
* @clk: outgoing clock "SPICLK" for the SPI bus
* @master: SPI framework hookup
* @master_info: controller-specific data from machine setup
+ * @kworker: thread struct for message pump
+ * @kworker_task: pointer to task for message pump kworker thread
+ * @pump_messages: work struct for scheduling work to the message pump
+ * @queue_lock: spinlock to syncronise access to message queue
+ * @queue: message queue
+ * @busy: message pump is busy
+ * @running: message pump is running
* @pump_transfers: Tasklet used in Interrupt Transfer mode
* @cur_msg: Pointer to current spi_message being processed
* @cur_transfer: Pointer to current spi_transfer
@@ -403,6 +436,9 @@
#endif
int cur_cs;
int *chipselects;
+#ifdef CONFIG_ARCH_GOKE
+ struct cs_data *cs_data;
+#endif
};
/**
@@ -459,13 +495,41 @@
static void internal_cs_control(struct pl022 *pl022, u32 command)
{
u32 tmp;
-
+#ifdef CONFIG_ARCH_GOKE
+ struct amba_device *adev = pl022->adev;
+ struct amba_driver *adrv = container_of(adev->dev.driver,
+ struct amba_driver, drv);
+
+ if (pl022->vendor->extended_cr && (adev->periphid ==
+ adrv->id_table[PL022_IDS_INDEX_GOKE].id)) {
+ if (pl022->cs_data) {
+ tmp = readl(pl022->cs_data->virt_addr);
+ tmp &= ~(pl022->cs_data->cs_mask_bit);
+ tmp |= ((u32)pl022->cur_cs) << pl022->cs_data->cs_sb;
+ writel(tmp, pl022->cs_data->virt_addr);
+ }
+
+ if (command == SSP_CHIP_SELECT)
+ /* Enable SSP */
+ writew((readw(SSP_CR1(pl022->virtbase)) |
+ SSP_CR1_MASK_SSE),
+ SSP_CR1(pl022->virtbase));
+ else
+ /* disable SSP */
+ writew((readw(SSP_CR1(pl022->virtbase)) &
+ (~SSP_CR1_MASK_SSE)),
+ SSP_CR1(pl022->virtbase));
+ } else {
+#endif
tmp = readw(SSP_CSR(pl022->virtbase));
if (command == SSP_CHIP_SELECT)
- tmp &= ~BIT(pl022->cur_cs);
+ tmp &= ~BIT((u32)pl022->cur_cs);
else
- tmp |= BIT(pl022->cur_cs);
+ tmp |= BIT((u32)pl022->cur_cs);
writew(tmp, SSP_CSR(pl022->virtbase));
+#ifdef CONFIG_ARCH_GOKE
+ }
+#endif
}
static void pl022_cs_control(struct pl022 *pl022, u32 command)
@@ -566,8 +630,16 @@
static void restore_state(struct pl022 *pl022)
{
struct chip_data *chip = pl022->cur_chip;
+#ifdef CONFIG_ARCH_GOKE
+ struct amba_device *adev = pl022->adev;
+ struct amba_driver *adrv = container_of(adev->dev.driver,
+ struct amba_driver, drv);
+ if (pl022->vendor->extended_cr && (adev->periphid !=
+ adrv->id_table[PL022_IDS_INDEX_GOKE].id))
+#else
if (pl022->vendor->extended_cr)
+#endif
writel(chip->cr0, SSP_CR0(pl022->virtbase));
else
writew(chip->cr0, SSP_CR0(pl022->virtbase));
@@ -640,6 +712,15 @@
GEN_MASK_BITS(SSP_FEEDBACK_CLK_DELAY_NONE, SSP_CR1_MASK_FBCLKDEL_ST, 13) \
)
+#ifdef CONFIG_ARCH_GOKE
+/* Goke versions extend this register to use all 16 bits */
+#define DEFAULT_SSP_REG_CR1_GOKE ( \
+ DEFAULT_SSP_REG_CR1 | \
+ GEN_MASK_BITS(SSP_RX_MSB, SSP_CR1_MASK_BIGEND_GOKE, 4) | \
+ GEN_MASK_BITS(0x0, SSP_CR1_MASK_ALTASENS_GOKE, 6) \
+)
+#endif
+
#define DEFAULT_SSP_REG_CPSR ( \
GEN_MASK_BITS(SSP_DEFAULT_PRESCALE, SSP_CPSR_MASK_CPSDVSR, 0) \
)
@@ -659,8 +740,22 @@
writel(DEFAULT_SSP_REG_CR0_ST_PL023, SSP_CR0(pl022->virtbase));
writew(DEFAULT_SSP_REG_CR1_ST_PL023, SSP_CR1(pl022->virtbase));
} else if (pl022->vendor->extended_cr) {
+#ifdef CONFIG_ARCH_GOKE
+ struct amba_device *adev = pl022->adev;
+ struct amba_driver *adrv = container_of(adev->dev.driver,
+ struct amba_driver, drv);
+
+ if (adev->periphid == adrv->id_table[PL022_IDS_INDEX_GOKE].id) {
+ writew(DEFAULT_SSP_REG_CR0, SSP_CR0(pl022->virtbase));
+ writew(DEFAULT_SSP_REG_CR1_GOKE,
+ SSP_CR1(pl022->virtbase));
+ } else {
+#endif
writel(DEFAULT_SSP_REG_CR0_ST, SSP_CR0(pl022->virtbase));
writew(DEFAULT_SSP_REG_CR1_ST, SSP_CR1(pl022->virtbase));
+#ifdef CONFIG_ARCH_GOKE
+ }
+#endif
} else {
writew(DEFAULT_SSP_REG_CR0, SSP_CR0(pl022->virtbase));
writew(DEFAULT_SSP_REG_CR1, SSP_CR1(pl022->virtbase));
@@ -1803,7 +1898,7 @@
.com_mode = POLLING_TRANSFER,
.iface = SSP_INTERFACE_MOTOROLA_SPI,
.hierarchy = SSP_SLAVE,
- .slave_tx_disable = DO_NOT_DRIVE_TX,
+ .slave_tx_disable = DRIVE_TX,
.rx_lev_trig = SSP_RX_1_OR_MORE_ELEM,
.tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC,
.ctrl_len = SSP_BITS_8,
@@ -1835,6 +1930,13 @@
unsigned int bits = spi->bits_per_word;
u32 tmp;
struct device_node *np = spi->dev.of_node;
+#ifdef CONFIG_ARCH_GOKE
+ struct amba_device *adev = pl022->adev;
+ struct amba_driver *adrv = container_of(adev->dev.driver,
+ struct amba_driver, drv);
+ writel(0, SSP_TX_FIFO_CR(pl022->virtbase));
+ writel(0, SSP_RX_FIFO_CR(pl022->virtbase));
+#endif
if (!spi->max_speed_hz)
return -EINVAL;
@@ -1856,8 +1958,10 @@
if (chip_info == NULL) {
if (np) {
chip_info_dt = pl022_default_chip_info;
-
- chip_info_dt.hierarchy = SSP_MASTER;
+ if(pl022->master->slave)
+ chip_info_dt.hierarchy = SSP_SLAVE;
+ else
+ chip_info_dt.hierarchy = SSP_MASTER;
of_property_read_u32(np, "pl022,interface",
&chip_info_dt.iface);
of_property_read_u32(np, "pl022,com-mode",
@@ -1977,7 +2081,12 @@
chip->cpsr = clk_freq.cpsdvsr;
/* Special setup for the ST micro extended control registers */
+#ifdef CONFIG_ARCH_GOKE
+ if (pl022->vendor->extended_cr && (adev->periphid !=
+ adrv->id_table[PL022_IDS_INDEX_GOKE].id)) {
+#else
if (pl022->vendor->extended_cr) {
+#endif
u32 etx;
if (pl022->vendor->pl023) {
@@ -2011,6 +2120,22 @@
SSP_CR1_MASK_RXIFLSEL_ST, 7);
SSP_WRITE_BITS(chip->cr1, chip_info->tx_lev_trig,
SSP_CR1_MASK_TXIFLSEL_ST, 10);
+#ifdef CONFIG_ARCH_GOKE
+ } else if (pl022->vendor->extended_cr && (adev->periphid ==
+ adrv->id_table[PL022_IDS_INDEX_GOKE].id)) {
+ SSP_WRITE_BITS(chip->cr0, bits - 1,
+ SSP_CR0_MASK_DSS, 0);
+ SSP_WRITE_BITS(chip->cr0, chip_info->iface,
+ SSP_CR0_MASK_FRF, 4);
+
+ if (spi->mode & SPI_LSB_FIRST)
+ tmp = !!SPI_LSB_FIRST;
+ else
+ tmp = !SPI_LSB_FIRST;
+
+ SSP_WRITE_BITS(chip->cr1, tmp, SSP_CR1_MASK_BIGEND_GOKE, 4);
+ SSP_WRITE_BITS(chip->cr1, 0x0, SSP_CR1_MASK_ALTASENS_GOKE, 6);
+#endif
} else {
SSP_WRITE_BITS(chip->cr0, bits - 1,
SSP_CR0_MASK_DSS, 0);
@@ -2099,11 +2224,14 @@
static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
{
struct device *dev = &adev->dev;
+ struct amba_driver *adrv = container_of(adev->dev.driver,
+ struct amba_driver, drv);
struct pl022_ssp_controller *platform_info =
dev_get_platdata(&adev->dev);
struct spi_master *master;
struct pl022 *pl022 = NULL; /*Data for this driver */
struct device_node *np = adev->dev.of_node;
+ unsigned int slave_mode;
int status = 0, i, num_cs;
dev_info(&adev->dev,
@@ -2156,12 +2284,62 @@
master->rt = platform_info->rt;
master->dev.of_node = dev->of_node;
+ if (of_property_read_u32(np, "pl022,slave_mode",
+ &slave_mode) == 0) {
+ if (slave_mode == 1){
+ master->slave = true;
+ } else if (slave_mode == 0) {
+ master->slave = false;
+ } else {
+ dev_err(&adev->dev, "spi Master/Slave mode err!!!\n");
+ goto err_no_gpio;
+ }
+
+ }
+
if (platform_info->num_chipselect && platform_info->chipselects) {
for (i = 0; i < num_cs; i++)
pl022->chipselects[i] = platform_info->chipselects[i];
} else if (pl022->vendor->internal_cs_ctrl) {
for (i = 0; i < num_cs; i++)
pl022->chipselects[i] = i;
+
+#ifdef CONFIG_ARCH_GOKE
+ if ((adev->periphid == adrv->id_table[PL022_IDS_INDEX_GOKE].id)
+ && pl022->vendor->extended_cr
+ && (num_cs > 1)) {
+ pl022->cs_data = devm_kzalloc(dev,
+ sizeof(struct cs_data),
+ GFP_KERNEL);
+ if (!pl022->cs_data) {
+ status = -ENOMEM;
+ goto err_no_mem;
+ }
+
+ if (of_address_to_resource(np, 1,
+ &pl022->cs_data->res)) {
+ status = -EPROBE_DEFER;
+ goto err_no_gpio;
+ }
+
+ if (of_property_read_u32(np, "spi_cs_sb",
+ &pl022->cs_data->cs_sb)) {
+ status = -EPROBE_DEFER;
+ goto err_no_gpio;
+ }
+
+ if (of_property_read_u32(np, "spi_cs_mask_bit",
+ &pl022->cs_data->cs_mask_bit)) {
+ status = -EPROBE_DEFER;
+ goto err_no_gpio;
+ }
+
+ pl022->cs_data->virt_addr = devm_ioremap(dev,
+ pl022->cs_data->res.start,
+ resource_size(&adev->res));
+ } else
+ pl022->cs_data = NULL;
+#endif
} else if (IS_ENABLED(CONFIG_OF)) {
for (i = 0; i < num_cs; i++) {
int cs_gpio = of_get_named_gpio(np, "cs-gpios", i);
@@ -2288,6 +2466,11 @@
err_no_ioremap:
amba_release_regions(adev);
err_no_ioregion:
+#ifdef CONFIG_ARCH_GOKE
+ if (pl022->cs_data)
+ release_mem_region(pl022->cs_data->res.start,
+ resource_size(&pl022->cs_data->res));
+#endif
err_no_gpio:
err_no_mem:
spi_master_put(master);
@@ -2314,6 +2497,11 @@
clk_disable_unprepare(pl022->clk);
amba_release_regions(adev);
+#ifdef CONFIG_ARCH_GOKE
+ if (pl022->cs_data)
+ release_mem_region(pl022->cs_data->res.start,
+ resource_size(&pl022->cs_data->res));
+#endif
tasklet_disable(&pl022->pump_transfers);
return 0;
}
@@ -2390,13 +2578,13 @@
};
static struct vendor_data vendor_arm = {
- .fifodepth = 8,
+ .fifodepth = 256,
.max_bpw = 16,
.unidir = false,
- .extended_cr = false,
+ .extended_cr = true,
.pl023 = false,
.loopback = true,
- .internal_cs_ctrl = false,
+ .internal_cs_ctrl = true,
};
static struct vendor_data vendor_st = {
@@ -2433,7 +2621,7 @@
{
/*
* ARM PL022 variant, this has a 16bit wide
- * and 8 locations deep TX/RX FIFO
+ * and 256 locations deep TX/RX FIFO
*/
.id = 0x00041022,
.mask = 0x000fffff,
diff -urN linux-4.9.37/drivers/staging/greybus/tools/.gitignore linux-4.9.y/drivers/staging/greybus/tools/.gitignore
--- linux-4.9.37/drivers/staging/greybus/tools/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/staging/greybus/tools/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-loopback_test
diff -urN linux-4.9.37/drivers/tty/serial/amba-pl011.c linux-4.9.y/drivers/tty/serial/amba-pl011.c
--- linux-4.9.37/drivers/tty/serial/amba-pl011.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/tty/serial/amba-pl011.c 2021-06-07 13:01:34.000000000 +0300
@@ -109,12 +109,20 @@
static unsigned int get_fifosize_arm(struct amba_device *dev)
{
+#ifdef CONFIG_ARCH_GOKE
+ return 64;
+#else
return amba_rev(dev) < 3 ? 16 : 32;
+#endif
}
static struct vendor_data vendor_arm = {
.reg_offset = pl011_std_offsets,
+#ifdef CONFIG_ARCH_GOKE
+ .ifls = UART011_IFLS_RX1_8|UART011_IFLS_TX1_8,
+#else
.ifls = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8,
+#endif
.fr_busy = UART01x_FR_BUSY,
.fr_dsr = UART01x_FR_DSR,
.fr_cts = UART01x_FR_CTS,
@@ -405,7 +413,11 @@
pl011_reg_to_offset(uap, REG_DR),
.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
.direction = DMA_MEM_TO_DEV,
+#ifdef CONFIG_ARCH_GOKE
+ .dst_maxburst = 7,
+#else
.dst_maxburst = uap->fifosize >> 1,
+#endif
.device_fc = false,
};
struct dma_chan *chan;
@@ -461,7 +473,11 @@
pl011_reg_to_offset(uap, REG_DR),
.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
.direction = DMA_DEV_TO_MEM,
+#ifdef CONFIG_ARCH_GOKE
+ .src_maxburst = 7,
+#else
.src_maxburst = uap->fifosize >> 2,
+#endif
.device_fc = false,
};
struct dma_slave_caps caps;
diff -urN linux-4.9.37/drivers/tty/vt/.gitignore linux-4.9.y/drivers/tty/vt/.gitignore
--- linux-4.9.37/drivers/tty/vt/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/tty/vt/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,2 +0,0 @@
-consolemap_deftbl.c
-defkeymap.c
diff -urN linux-4.9.37/drivers/tty/vt/selection.c linux-4.9.y/drivers/tty/vt/selection.c
--- linux-4.9.37/drivers/tty/vt/selection.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/tty/vt/selection.c 2021-06-07 13:01:34.000000000 +0300
@@ -13,6 +13,7 @@
#include <linux/tty.h>
#include <linux/sched.h>
#include <linux/mm.h>
+#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/types.h>
@@ -40,6 +41,7 @@
static int sel_end;
static int sel_buffer_lth;
static char *sel_buffer;
+static DEFINE_MUTEX(sel_lock);
/* clear_selection, highlight and highlight_pointer can be called
from interrupt (via scrollback/front) */
@@ -163,7 +165,7 @@
char *bp, *obp;
int i, ps, pe, multiplier;
u16 c;
- int mode;
+ int mode, ret = 0;
poke_blanked_console();
@@ -203,6 +205,7 @@
pe = tmp;
}
+ mutex_lock(&sel_lock);
if (sel_cons != vc_cons[fg_console].d) {
clear_selection();
sel_cons = vc_cons[fg_console].d;
@@ -248,9 +251,10 @@
break;
case TIOCL_SELPOINTER:
highlight_pointer(pe);
- return 0;
+ goto unlock;
default:
- return -EINVAL;
+ ret = -EINVAL;
+ goto unlock;
}
/* remove the pointer */
@@ -272,7 +276,7 @@
else if (new_sel_start == sel_start)
{
if (new_sel_end == sel_end) /* no action required */
- return 0;
+ goto unlock;
else if (new_sel_end > sel_end) /* extend to right */
highlight(sel_end + 2, new_sel_end);
else /* contract from right */
@@ -299,7 +303,8 @@
if (!bp) {
printk(KERN_WARNING "selection: kmalloc() failed\n");
clear_selection();
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto unlock;
}
kfree(sel_buffer);
sel_buffer = bp;
@@ -324,7 +329,9 @@
}
}
sel_buffer_lth = bp - sel_buffer;
- return 0;
+unlock:
+ mutex_unlock(&sel_lock);
+ return ret;
}
/* Insert the contents of the selection buffer into the
@@ -352,10 +359,13 @@
tty_buffer_lock_exclusive(&vc->port);
add_wait_queue(&vc->paste_wait, &wait);
+ mutex_lock(&sel_lock);
while (sel_buffer && sel_buffer_lth > pasted) {
set_current_state(TASK_INTERRUPTIBLE);
if (tty_throttled(tty)) {
+ mutex_unlock(&sel_lock);
schedule();
+ mutex_lock(&sel_lock);
continue;
}
__set_current_state(TASK_RUNNING);
@@ -364,6 +374,7 @@
count);
pasted += count;
}
+ mutex_unlock(&sel_lock);
remove_wait_queue(&vc->paste_wait, &wait);
__set_current_state(TASK_RUNNING);
diff -urN linux-4.9.37/drivers/usb/core/devices.c linux-4.9.y/drivers/usb/core/devices.c
--- linux-4.9.37/drivers/usb/core/devices.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/core/devices.c 2021-06-07 13:01:34.000000000 +0300
@@ -182,14 +182,8 @@
dir = usb_endpoint_dir_in(desc) ? 'I' : 'O';
- if (speed == USB_SPEED_HIGH) {
- switch (usb_endpoint_maxp(desc) & (0x03 << 11)) {
- case 1 << 11:
- bandwidth = 2; break;
- case 2 << 11:
- bandwidth = 3; break;
- }
- }
+ if (speed == USB_SPEED_HIGH)
+ bandwidth = usb_endpoint_maxp_mult(desc);
/* this isn't checking for illegal values */
switch (usb_endpoint_type(desc)) {
diff -urN linux-4.9.37/drivers/usb/core/hub.c linux-4.9.y/drivers/usb/core/hub.c
--- linux-4.9.37/drivers/usb/core/hub.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/core/hub.c 2021-06-07 13:01:34.000000000 +0300
@@ -1345,6 +1345,10 @@
ret = -ENODEV;
goto fail;
} else if (hub->descriptor->bNbrPorts == 0) {
+ if (!hdev->parent) {
+ dev_info(hub_dev, "hub can't support USB3.0\n");
+ return -ENODEV;
+ }
message = "hub doesn't have any ports!";
ret = -ENODEV;
goto fail;
diff -urN linux-4.9.37/drivers/usb/core/urb.c linux-4.9.y/drivers/usb/core/urb.c
--- linux-4.9.37/drivers/usb/core/urb.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/core/urb.c 2021-06-07 13:01:34.000000000 +0300
@@ -407,11 +407,8 @@
}
/* "high bandwidth" mode, 1-3 packets/uframe? */
- if (dev->speed == USB_SPEED_HIGH) {
- int mult = 1 + ((max >> 11) & 0x03);
- max &= 0x07ff;
- max *= mult;
- }
+ if (dev->speed == USB_SPEED_HIGH)
+ max *= usb_endpoint_maxp_mult(&ep->desc);
if (urb->number_of_packets <= 0)
return -EINVAL;
diff -urN linux-4.9.37/drivers/usb/dwc3/core.c linux-4.9.y/drivers/usb/dwc3/core.c
--- linux-4.9.37/drivers/usb/dwc3/core.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/dwc3/core.c 2021-06-07 13:01:34.000000000 +0300
@@ -44,11 +44,27 @@
#include "core.h"
#include "gadget.h"
#include "io.h"
+#include "dwc3-goke.h"
#include "debug.h"
#define DWC3_DEFAULT_AUTOSUSPEND_DELAY 5000 /* ms */
+
+/*
+ * Default to the number of outstanding pipelined transfer
+ * requests is 0x3[11:8], modify the field change to 0x7.
+ */
+static void dwc3_outstanding_pipe_choose(struct dwc3 *dwc)
+{
+ u32 reg;
+
+ reg = dwc3_readl(dwc->regs, DWC3_GSBUSCFG1);
+ reg &= ~DWC3_PIPE_TRANS_LIMIT_MASK;
+ reg |= DWC3_PIPE_TRANS_LIMIT;
+ dwc3_writel(dwc->regs, DWC3_GSBUSCFG1, reg);
+}
+
/**
* dwc3_get_dr_mode - Validates and sets dr_mode
* @dwc: pointer to our context structure
@@ -305,13 +321,7 @@
struct dwc3_event_buffer *evt;
evt = dwc->ev_buf;
- dwc3_trace(trace_dwc3_core,
- "Event buf %p dma %08llx length %d\n",
- evt->buf, (unsigned long long) evt->dma,
- evt->length);
-
evt->lpos = 0;
-
dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(0),
lower_32_bits(evt->dma));
dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(0),
@@ -428,9 +438,6 @@
dwc->num_in_eps = DWC3_NUM_IN_EPS(parms);
dwc->num_out_eps = DWC3_NUM_EPS(parms) - dwc->num_in_eps;
-
- dwc3_trace(trace_dwc3_core, "found %d IN and %d OUT endpoints",
- dwc->num_in_eps, dwc->num_out_eps);
}
static void dwc3_cache_hwparams(struct dwc3 *dwc)
@@ -683,13 +690,13 @@
reg |= DWC3_GCTL_GBLHIBERNATIONEN;
break;
default:
- dwc3_trace(trace_dwc3_core, "No power optimization available\n");
+ /* nothing */
+ break;
}
/* check if current dwc3 is on simulation board */
if (dwc->hwparams.hwparams6 & DWC3_GHWPARAMS6_EN_FPGA) {
- dwc3_trace(trace_dwc3_core,
- "running on FPGA platform\n");
+ dev_info(dwc->dev, "Running with FPGA optmizations\n");
dwc->is_fpga = true;
}
@@ -982,7 +989,8 @@
*/
hird_threshold = 12;
- dwc->maximum_speed = usb_get_maximum_speed(dev);
+ dwc->maximum_speed = usb_get_max_speed(dev);
+
dwc->dr_mode = usb_get_dr_mode(dev);
dwc->hsphy_mode = of_usb_get_phy_mode(dev->of_node);
@@ -996,6 +1004,8 @@
&hird_threshold);
dwc->usb3_lpm_capable = device_property_read_bool(dev,
"snps,usb3_lpm_capable");
+ dwc->usb2_lpm_disable = device_property_read_bool(dev,
+ "snps,usb2-lpm-disable");
dwc->disable_scramble_quirk = device_property_read_bool(dev,
"snps,disable_scramble_quirk");
@@ -1026,6 +1036,16 @@
dwc->dis_del_phy_power_chg_quirk = device_property_read_bool(dev,
"snps,dis-del-phy-power-chg-quirk");
+ dwc->dis_initiate_u1 = device_property_read_bool(dev,
+ "snps,dis_initiate_u1");
+ dwc->dis_initiate_u2 = device_property_read_bool(dev,
+ "snps,dis_initiate_u2");
+
+ dwc->eps_new_init = device_property_read_bool(dev,
+ "snps,eps_new_init");
+ device_property_read_u32(dev, "eps_directions",
+ &dwc->eps_directions);
+
dwc->tx_de_emphasis_quirk = device_property_read_bool(dev,
"snps,tx_de_emphasis_quirk");
device_property_read_u8(dev, "snps,tx_de_emphasis",
@@ -1044,6 +1064,10 @@
platform_set_drvdata(pdev, dwc);
dwc3_cache_hwparams(dwc);
+ device_property_read_u32_array(dev, "eps_map",
+ dwc->dwceps_map_to_usbeps,
+ DWC3_NUM_EPS(&dwc->hwparams));
+
ret = dwc3_core_get_phy(dwc);
if (ret)
goto err0;
@@ -1087,6 +1111,8 @@
goto err4;
}
+ dwc3_outstanding_pipe_choose(dwc);
+
/* Check the maximum_speed parameter */
switch (dwc->maximum_speed) {
case USB_SPEED_LOW:
@@ -1177,6 +1203,10 @@
dwc3_free_event_buffers(dwc);
dwc3_free_scratch_buffers(dwc);
+ bsp_dwc3_exited();
+
+ dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST);
+
return 0;
}
diff -urN linux-4.9.37/drivers/usb/dwc3/core.h linux-4.9.y/drivers/usb/dwc3/core.h
--- linux-4.9.37/drivers/usb/dwc3/core.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/dwc3/core.h 2021-06-07 13:01:34.000000000 +0300
@@ -35,6 +35,8 @@
#include <linux/phy/phy.h>
#define DWC3_MSG_MAX 500
+#define DWC3_PIPE_TRANS_LIMIT_MASK (0xf << 8)
+#define DWC3_PIPE_TRANS_LIMIT (0x7 << 8)
/* Global constants */
#define DWC3_ZLP_BUF_SIZE 1024 /* size of a superspeed bulk */
@@ -386,6 +388,9 @@
#define DWC3_DSTS_RXFIFOEMPTY (1 << 17)
+#define DWC3_EVENT_PRAM_MAX_SOFFN 0x3fff
+#define DWC3_EVENT_PRAM_SOFFN_MASK 0x3fff
+
#define DWC3_DSTS_SOFFN_MASK (0x3fff << 3)
#define DWC3_DSTS_SOFFN(n) (((n) & DWC3_DSTS_SOFFN_MASK) >> 3)
@@ -488,7 +493,7 @@
#define DWC3_EP_DIRECTION_TX true
#define DWC3_EP_DIRECTION_RX false
-#define DWC3_TRB_NUM 256
+#define DWC3_TRB_NUM 4096
/**
* struct dwc3_ep - device side endpoint representation
@@ -535,7 +540,8 @@
#define DWC3_EP_WEDGE (1 << 2)
#define DWC3_EP_BUSY (1 << 4)
#define DWC3_EP_PENDING_REQUEST (1 << 5)
-#define DWC3_EP_MISSED_ISOC (1 << 6)
+#define DWC3_EP_MISSED_ISOC (1 << 6)
+#define DWC3_EP_UPDATE (1 << 7)
/* This last one is specific to EP0 */
#define DWC3_EP0_DIR_IN (1 << 31)
@@ -549,14 +555,15 @@
* By using u8 types we ensure that our % operator when incrementing
* enqueue and dequeue get optimized away by the compiler.
*/
- u8 trb_enqueue;
- u8 trb_dequeue;
+ u32 trb_enqueue;
+ u32 trb_dequeue;
u8 number;
u8 type;
u8 resource_index;
u32 allocated_requests;
u32 queued_requests;
+ u32 frame_number;
u32 interval;
char name[20];
@@ -806,6 +813,7 @@
* @start_config_issued: true when StartConfig command has been issued
* @three_stage_setup: set if we perform a three phase setup
* @usb3_lpm_capable: set if hadrware supports Link Power Management
+ * @usb2_lpm_disable: set to disable usb2 lpm
* @disable_scramble_quirk: set if we enable the disable scramble quirk
* @u2exit_lfps_quirk: set if we enable u2exit lfps quirk
* @u2ss_inp3_quirk: set if we enable P3 OK for U2/SS Inactive quirk
@@ -854,6 +862,7 @@
struct dwc3_event_buffer *ev_buf;
struct dwc3_ep *eps[DWC3_ENDPOINTS_NUM];
+ u32 dwceps_map_to_usbeps[DWC3_ENDPOINTS_NUM];
struct usb_gadget gadget;
struct usb_gadget_driver *gadget_driver;
@@ -929,6 +938,12 @@
u8 num_out_eps;
u8 num_in_eps;
+/*
+ * NOTICE: eps_directions bitmap[0~31] 0: out ep, 1: in ep
+ * and used with total ep numbers(num_out_eps + num_in_eps)
+ */
+#define DWC3_EPS_DEFAULT_DIRECTIONS 0xaaaaaaaa
+ u32 eps_directions;
void *mem;
@@ -941,6 +956,13 @@
u8 lpm_nyet_threshold;
u8 hird_threshold;
+ struct proc_dir_entry* parent_entry;
+ struct proc_dir_entry* csts_entry;
+ u8 udc_connect_status;
+ #define UDC_DISCONNECTED 0
+ #define UDC_CONNECT_HOST 1
+ #define UDC_CONNECT_CHARGER 2
+
const char *hsphy_interface;
unsigned connected:1;
@@ -956,6 +978,7 @@
unsigned setup_packet_pending:1;
unsigned three_stage_setup:1;
unsigned usb3_lpm_capable:1;
+ unsigned usb2_lpm_disable:1;
unsigned disable_scramble_quirk:1;
unsigned u2exit_lfps_quirk:1;
@@ -972,6 +995,11 @@
unsigned dis_u2_freeclk_exists_quirk:1;
unsigned dis_del_phy_power_chg_quirk:1;
+ unsigned dis_initiate_u1:1;
+ unsigned dis_initiate_u2:1;
+
+ unsigned eps_new_init:1;
+
unsigned tx_de_emphasis_quirk:1;
unsigned tx_de_emphasis:2;
};
@@ -1175,6 +1203,9 @@
{ return 0; }
#endif
+int dwc3_proc_init(struct dwc3 *dwc);
+int dwc3_proc_shutdown(struct dwc3 *dwc);
+
/* power management interface */
#if !IS_ENABLED(CONFIG_USB_DWC3_HOST)
int dwc3_gadget_suspend(struct dwc3 *dwc);
diff -urN linux-4.9.37/drivers/usb/dwc3/debugfs.c linux-4.9.y/drivers/usb/dwc3/debugfs.c
--- linux-4.9.37/drivers/usb/dwc3/debugfs.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/dwc3/debugfs.c 2021-06-07 13:01:34.000000000 +0300
@@ -689,30 +689,6 @@
return 0;
}
-static inline const char *dwc3_trb_type_string(struct dwc3_trb *trb)
-{
- switch (DWC3_TRBCTL_TYPE(trb->ctrl)) {
- case DWC3_TRBCTL_NORMAL:
- return "normal";
- case DWC3_TRBCTL_CONTROL_SETUP:
- return "control-setup";
- case DWC3_TRBCTL_CONTROL_STATUS2:
- return "control-status2";
- case DWC3_TRBCTL_CONTROL_STATUS3:
- return "control-status3";
- case DWC3_TRBCTL_CONTROL_DATA:
- return "control-data";
- case DWC3_TRBCTL_ISOCHRONOUS_FIRST:
- return "isoc-first";
- case DWC3_TRBCTL_ISOCHRONOUS:
- return "isoc";
- case DWC3_TRBCTL_LINK_TRB:
- return "link";
- default:
- return "UNKNOWN";
- }
-}
-
static int dwc3_ep_trb_ring_show(struct seq_file *s, void *unused)
{
struct dwc3_ep *dep = s->private;
@@ -733,10 +709,11 @@
for (i = 0; i < DWC3_TRB_NUM; i++) {
struct dwc3_trb *trb = &dep->trb_pool[i];
+ unsigned int type = DWC3_TRBCTL_TYPE(trb->ctrl);
seq_printf(s, "%08x%08x,%d,%s,%d,%d,%d,%d,%d,%d\n",
trb->bph, trb->bpl, trb->size,
- dwc3_trb_type_string(trb),
+ dwc3_trb_type_string(type),
!!(trb->ctrl & DWC3_TRB_CTRL_IOC),
!!(trb->ctrl & DWC3_TRB_CTRL_ISP_IMI),
!!(trb->ctrl & DWC3_TRB_CTRL_CSP),
diff -urN linux-4.9.37/drivers/usb/dwc3/debug.h linux-4.9.y/drivers/usb/dwc3/debug.h
--- linux-4.9.37/drivers/usb/dwc3/debug.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/dwc3/debug.h 2021-06-07 13:01:34.000000000 +0300
@@ -125,55 +125,344 @@
}
/**
+ * dwc3_trb_type_string - returns TRB type as a string
+ * @type: the type of the TRB
+ */
+static inline const char *dwc3_trb_type_string(unsigned int type)
+{
+ switch (type) {
+ case DWC3_TRBCTL_NORMAL:
+ return "normal";
+ case DWC3_TRBCTL_CONTROL_SETUP:
+ return "setup";
+ case DWC3_TRBCTL_CONTROL_STATUS2:
+ return "status2";
+ case DWC3_TRBCTL_CONTROL_STATUS3:
+ return "status3";
+ case DWC3_TRBCTL_CONTROL_DATA:
+ return "data";
+ case DWC3_TRBCTL_ISOCHRONOUS_FIRST:
+ return "isoc-first";
+ case DWC3_TRBCTL_ISOCHRONOUS:
+ return "isoc";
+ case DWC3_TRBCTL_LINK_TRB:
+ return "link";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+static inline const char *dwc3_ep0_state_string(enum dwc3_ep0_state state)
+{
+ switch (state) {
+ case EP0_UNCONNECTED:
+ return "Unconnected";
+ case EP0_SETUP_PHASE:
+ return "Setup Phase";
+ case EP0_DATA_PHASE:
+ return "Data Phase";
+ case EP0_STATUS_PHASE:
+ return "Status Phase";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+/**
* dwc3_gadget_event_string - returns event name
* @event: the event code
*/
-static inline const char *
-dwc3_gadget_event_string(const struct dwc3_event_devt *event)
+static inline const char *dwc3_gadget_event_string(char *str, size_t size,
+ const struct dwc3_event_devt *event)
{
- static char str[256];
enum dwc3_link_state state = event->event_info & DWC3_LINK_STATE_MASK;
switch (event->type) {
case DWC3_DEVICE_EVENT_DISCONNECT:
- sprintf(str, "Disconnect: [%s]",
+ snprintf(str, size, "Disconnect: [%s]",
dwc3_gadget_link_string(state));
break;
case DWC3_DEVICE_EVENT_RESET:
- sprintf(str, "Reset [%s]", dwc3_gadget_link_string(state));
+ snprintf(str, size, "Reset [%s]",
+ dwc3_gadget_link_string(state));
break;
case DWC3_DEVICE_EVENT_CONNECT_DONE:
- sprintf(str, "Connection Done [%s]",
+ snprintf(str, size, "Connection Done [%s]",
dwc3_gadget_link_string(state));
break;
case DWC3_DEVICE_EVENT_LINK_STATUS_CHANGE:
- sprintf(str, "Link Change [%s]",
+ snprintf(str, size, "Link Change [%s]",
dwc3_gadget_link_string(state));
break;
case DWC3_DEVICE_EVENT_WAKEUP:
- sprintf(str, "WakeUp [%s]", dwc3_gadget_link_string(state));
+ snprintf(str, size, "WakeUp [%s]",
+ dwc3_gadget_link_string(state));
break;
case DWC3_DEVICE_EVENT_EOPF:
- sprintf(str, "End-Of-Frame [%s]",
+ snprintf(str, size, "End-Of-Frame [%s]",
dwc3_gadget_link_string(state));
break;
case DWC3_DEVICE_EVENT_SOF:
- sprintf(str, "Start-Of-Frame [%s]",
+ snprintf(str, size, "Start-Of-Frame [%s]",
dwc3_gadget_link_string(state));
break;
case DWC3_DEVICE_EVENT_ERRATIC_ERROR:
- sprintf(str, "Erratic Error [%s]",
+ snprintf(str, size, "Erratic Error [%s]",
dwc3_gadget_link_string(state));
break;
case DWC3_DEVICE_EVENT_CMD_CMPL:
- sprintf(str, "Command Complete [%s]",
+ snprintf(str, size, "Command Complete [%s]",
dwc3_gadget_link_string(state));
break;
case DWC3_DEVICE_EVENT_OVERFLOW:
- sprintf(str, "Overflow [%s]", dwc3_gadget_link_string(state));
+ snprintf(str, size, "Overflow [%s]",
+ dwc3_gadget_link_string(state));
break;
default:
- sprintf(str, "UNKNOWN");
+ snprintf(str, size, "UNKNOWN");
+ }
+
+ return str;
+}
+
+static inline void dwc3_decode_get_status(__u8 t, __u16 i, __u16 l, char *str,
+ size_t size)
+{
+ switch (t & USB_RECIP_MASK) {
+ case USB_RECIP_DEVICE:
+ snprintf(str, size, "Get Device Status(Length = %d)", l);
+ break;
+ case USB_RECIP_INTERFACE:
+ snprintf(str, size, "Get Interface Status(Intf = %d, Length = %d)",
+ i, l);
+ break;
+ case USB_RECIP_ENDPOINT:
+ snprintf(str, size, "Get Endpoint Status(ep%d%s)",
+ i & ~USB_DIR_IN,
+ i & USB_DIR_IN ? "in" : "out");
+ break;
+ }
+}
+
+static inline void dwc3_decode_set_clear_feature(__u8 t, __u8 b, __u16 v,
+ __u16 i, char *str, size_t size)
+{
+ switch (t & USB_RECIP_MASK) {
+ case USB_RECIP_DEVICE:
+ snprintf(str, size, "%s Device Feature(%s%s)",
+ b == USB_REQ_CLEAR_FEATURE ? "Clear" : "Set",
+ ({char *s;
+ switch (v) {
+ case USB_DEVICE_SELF_POWERED:
+ s = "Self Powered";
+ break;
+ case USB_DEVICE_REMOTE_WAKEUP:
+ s = "Remote Wakeup";
+ break;
+ case USB_DEVICE_TEST_MODE:
+ s = "Test Mode";
+ break;
+ default:
+ s = "UNKNOWN";
+ } s; }),
+ v == USB_DEVICE_TEST_MODE ?
+ ({ char *s;
+ switch (i) {
+ case TEST_J:
+ s = ": TEST_J";
+ break;
+ case TEST_K:
+ s = ": TEST_K";
+ break;
+ case TEST_SE0_NAK:
+ s = ": TEST_SE0_NAK";
+ break;
+ case TEST_PACKET:
+ s = ": TEST_PACKET";
+ break;
+ case TEST_FORCE_EN:
+ s = ": TEST_FORCE_EN";
+ break;
+ default:
+ s = ": UNKNOWN";
+ } s; }) : "");
+ break;
+ case USB_RECIP_INTERFACE:
+ snprintf(str, size, "%s Interface Feature(%s)",
+ b == USB_REQ_CLEAR_FEATURE ? "Clear" : "Set",
+ v == USB_INTRF_FUNC_SUSPEND ?
+ "Function Suspend" : "UNKNOWN");
+ break;
+ case USB_RECIP_ENDPOINT:
+ snprintf(str, size, "%s Endpoint Feature(%s ep%d%s)",
+ b == USB_REQ_CLEAR_FEATURE ? "Clear" : "Set",
+ v == USB_ENDPOINT_HALT ? "Halt" : "UNKNOWN",
+ i & ~USB_DIR_IN,
+ i & USB_DIR_IN ? "in" : "out");
+ break;
+ }
+}
+
+static inline void dwc3_decode_set_address(__u16 v, char *str, size_t size)
+{
+ snprintf(str, size, "Set Address(Addr = %02x)", v);
+}
+
+static inline void dwc3_decode_get_set_descriptor(__u8 t, __u8 b, __u16 v,
+ __u16 i, __u16 l, char *str, size_t size)
+{
+ snprintf(str, size, "%s %s Descriptor(Index = %d, Length = %d)",
+ b == USB_REQ_GET_DESCRIPTOR ? "Get" : "Set",
+ ({ char *s;
+ switch (v >> 8) {
+ case USB_DT_DEVICE:
+ s = "Device";
+ break;
+ case USB_DT_CONFIG:
+ s = "Configuration";
+ break;
+ case USB_DT_STRING:
+ s = "String";
+ break;
+ case USB_DT_INTERFACE:
+ s = "Interface";
+ break;
+ case USB_DT_ENDPOINT:
+ s = "Endpoint";
+ break;
+ case USB_DT_DEVICE_QUALIFIER:
+ s = "Device Qualifier";
+ break;
+ case USB_DT_OTHER_SPEED_CONFIG:
+ s = "Other Speed Config";
+ break;
+ case USB_DT_INTERFACE_POWER:
+ s = "Interface Power";
+ break;
+ case USB_DT_OTG:
+ s = "OTG";
+ break;
+ case USB_DT_DEBUG:
+ s = "Debug";
+ break;
+ case USB_DT_INTERFACE_ASSOCIATION:
+ s = "Interface Association";
+ break;
+ case USB_DT_BOS:
+ s = "BOS";
+ break;
+ case USB_DT_DEVICE_CAPABILITY:
+ s = "Device Capability";
+ break;
+ case USB_DT_PIPE_USAGE:
+ s = "Pipe Usage";
+ break;
+ case USB_DT_SS_ENDPOINT_COMP:
+ s = "SS Endpoint Companion";
+ break;
+ case USB_DT_SSP_ISOC_ENDPOINT_COMP:
+ s = "SSP Isochronous Endpoint Companion";
+ break;
+ default:
+ s = "UNKNOWN";
+ break;
+ } s; }), v & 0xff, l);
+}
+
+
+static inline void dwc3_decode_get_configuration(__u16 l, char *str,
+ size_t size)
+{
+ snprintf(str, size, "Get Configuration(Length = %d)", l);
+}
+
+static inline void dwc3_decode_set_configuration(__u8 v, char *str, size_t size)
+{
+ snprintf(str, size, "Set Configuration(Config = %d)", v);
+}
+
+static inline void dwc3_decode_get_intf(__u16 i, __u16 l, char *str,
+ size_t size)
+{
+ snprintf(str, size, "Get Interface(Intf = %d, Length = %d)", i, l);
+}
+
+static inline void dwc3_decode_set_intf(__u8 v, __u16 i, char *str, size_t size)
+{
+ snprintf(str, size, "Set Interface(Intf = %d, Alt.Setting = %d)", i, v);
+}
+
+static inline void dwc3_decode_synch_frame(__u16 i, __u16 l, char *str,
+ size_t size)
+{
+ snprintf(str, size, "Synch Frame(Endpoint = %d, Length = %d)", i, l);
+}
+
+static inline void dwc3_decode_set_sel(__u16 l, char *str, size_t size)
+{
+ snprintf(str, size, "Set SEL(Length = %d)", l);
+}
+
+static inline void dwc3_decode_set_isoch_delay(__u8 v, char *str, size_t size)
+{
+ snprintf(str, size, "Set Isochronous Delay(Delay = %d ns)", v);
+}
+
+/**
+ * dwc3_decode_ctrl - returns a string represetion of ctrl request
+ */
+static inline const char *dwc3_decode_ctrl(char *str, size_t size,
+ __u8 bRequestType, __u8 bRequest, __u16 wValue, __u16 wIndex,
+ __u16 wLength)
+{
+ switch (bRequest) {
+ case USB_REQ_GET_STATUS:
+ dwc3_decode_get_status(bRequestType, wIndex, wLength, str,
+ size);
+ break;
+ case USB_REQ_CLEAR_FEATURE:
+ case USB_REQ_SET_FEATURE:
+ dwc3_decode_set_clear_feature(bRequestType, bRequest, wValue,
+ wIndex, str, size);
+ break;
+ case USB_REQ_SET_ADDRESS:
+ dwc3_decode_set_address(wValue, str, size);
+ break;
+ case USB_REQ_GET_DESCRIPTOR:
+ case USB_REQ_SET_DESCRIPTOR:
+ dwc3_decode_get_set_descriptor(bRequestType, bRequest, wValue,
+ wIndex, wLength, str, size);
+ break;
+ case USB_REQ_GET_CONFIGURATION:
+ dwc3_decode_get_configuration(wLength, str, size);
+ break;
+ case USB_REQ_SET_CONFIGURATION:
+ dwc3_decode_set_configuration(wValue, str, size);
+ break;
+ case USB_REQ_GET_INTERFACE:
+ dwc3_decode_get_intf(wIndex, wLength, str, size);
+ break;
+ case USB_REQ_SET_INTERFACE:
+ dwc3_decode_set_intf(wValue, wIndex, str, size);
+ break;
+ case USB_REQ_SYNCH_FRAME:
+ dwc3_decode_synch_frame(wIndex, wLength, str, size);
+ break;
+ case USB_REQ_SET_SEL:
+ dwc3_decode_set_sel(wLength, str, size);
+ break;
+ case USB_REQ_SET_ISOCH_DELAY:
+ dwc3_decode_set_isoch_delay(wValue, str, size);
+ break;
+ default:
+ snprintf(str, size, "%02x %02x %02x %02x %02x %02x %02x %02x",
+ bRequestType, bRequest,
+ cpu_to_le16(wValue) & 0xff,
+ cpu_to_le16(wValue) >> 8,
+ cpu_to_le16(wIndex) & 0xff,
+ cpu_to_le16(wIndex) >> 8,
+ cpu_to_le16(wLength) & 0xff,
+ cpu_to_le16(wLength) >> 8);
}
return str;
@@ -183,30 +472,52 @@
* dwc3_ep_event_string - returns event name
* @event: then event code
*/
-static inline const char *
-dwc3_ep_event_string(const struct dwc3_event_depevt *event)
+static inline const char *dwc3_ep_event_string(char *str, size_t size,
+ const struct dwc3_event_depevt *event, u32 ep0state)
{
u8 epnum = event->endpoint_number;
- static char str[256];
+ size_t len;
int status;
int ret;
- ret = sprintf(str, "ep%d%s: ", epnum >> 1,
+ ret = snprintf(str, size, "ep%d%s: ", epnum >> 1,
(epnum & 1) ? "in" : "out");
if (ret < 0)
return "UNKNOWN";
+ status = event->status;
+
switch (event->endpoint_event) {
case DWC3_DEPEVT_XFERCOMPLETE:
- strcat(str, "Transfer Complete");
+ len = strlen(str);
+ snprintf(str + len, size - len, "Transfer Complete (%c%c%c)",
+ status & DEPEVT_STATUS_SHORT ? 'S' : 's',
+ status & DEPEVT_STATUS_IOC ? 'I' : 'i',
+ status & DEPEVT_STATUS_LST ? 'L' : 'l');
+
+ len = strlen(str);
+
+ if (epnum <= 1)
+ snprintf(str + len, size - len, " [%s]",
+ dwc3_ep0_state_string(ep0state));
break;
case DWC3_DEPEVT_XFERINPROGRESS:
- strcat(str, "Transfer In-Progress");
+ len = strlen(str);
+
+ snprintf(str + len, size - len, "Transfer In Progress [%d] (%c%c%c)",
+ event->parameters,
+ status & DEPEVT_STATUS_SHORT ? 'S' : 's',
+ status & DEPEVT_STATUS_IOC ? 'I' : 'i',
+ status & DEPEVT_STATUS_LST ? 'M' : 'm');
break;
case DWC3_DEPEVT_XFERNOTREADY:
- strcat(str, "Transfer Not Ready");
- status = event->status & DEPEVT_STATUS_TRANSFER_ACTIVE;
- strcat(str, status ? " (Active)" : " (Not Active)");
+ len = strlen(str);
+
+ snprintf(str + len, size - len, "Transfer Not Ready [%d]%s",
+ event->parameters,
+ status & DEPEVT_STATUS_TRANSFER_ACTIVE ?
+ " (Active)" : " (Not Active)");
+
break;
case DWC3_DEPEVT_RXTXFIFOEVT:
strcat(str, "FIFO");
@@ -216,7 +527,7 @@
switch (status) {
case DEPEVT_STREAMEVT_FOUND:
- sprintf(str + ret, " Stream %d Found",
+ snprintf(str + ret, size - ret, " Stream %d Found",
event->parameters);
break;
case DEPEVT_STREAMEVT_NOTFOUND:
@@ -230,7 +541,7 @@
strcat(str, "Endpoint Command Complete");
break;
default:
- sprintf(str, "UNKNOWN");
+ snprintf(str, size, "UNKNOWN");
}
return str;
@@ -270,14 +581,15 @@
}
}
-static inline const char *dwc3_decode_event(u32 event)
+static inline const char *dwc3_decode_event(char *str, size_t size, u32 event,
+ u32 ep0state)
{
const union dwc3_event evt = (union dwc3_event) event;
if (evt.type.is_devspec)
- return dwc3_gadget_event_string(&evt.devt);
+ return dwc3_gadget_event_string(str, size, &evt.devt);
else
- return dwc3_ep_event_string(&evt.depevt);
+ return dwc3_ep_event_string(str, size, &evt.depevt, ep0state);
}
static inline const char *dwc3_ep_cmd_status_string(int status)
@@ -310,7 +622,6 @@
}
}
-void dwc3_trace(void (*trace)(struct va_format *), const char *fmt, ...);
#ifdef CONFIG_DEBUG_FS
extern void dwc3_debugfs_init(struct dwc3 *);
diff -urN linux-4.9.37/drivers/usb/dwc3/dwc3-goke.c linux-4.9.y/drivers/usb/dwc3/dwc3-goke.c
--- linux-4.9.37/drivers/usb/dwc3/dwc3-goke.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/usb/dwc3/dwc3-goke.c 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,359 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+#include <linux/slab.h>
+#include <linux/usb/ch9.h>
+
+#include "dwc3-goke.h"
+
+#define USB3_CTRL 0x190
+#define REG_SYS_STAT 0x8c
+#define PCIE_USB3_MODE_MASK (0x3 << 12)
+#define USB3_PCLK_OCC_SEL (0x1 << 30)
+
+#define PERI_USB3_GTXTHRCFG 0x2310000
+
+#define REG_GUSB3PIPECTL0 0xc2c0
+#define GTXTHRCFG 0xc108
+
+#define PCS_SSP_SOFT_RESET (0x1 << 31)
+#define SUSPEND_USB3_SS_PHY (0x1 << 17)
+
+#define GUSB2PHYCFG_OFFSET 0xc200
+#define GCTL_OFFSET 0xc110
+#define GUCTL_OFFSET 0xc12C
+#define GFLADJ_OFFSET 0xc630
+
+#define U2_FREECLK_EXISTS (0x1 << 30)
+#define SOFITPSYNC (0x1 << 10)
+#define REFCLKPER_MASK 0xffc00000
+#define REFCLKPER_VAL 0x29
+#define set_refclkper(a) (((a) << 22) & REFCLKPER_MASK)
+
+#define PLS1 (0x1 << 31)
+#define DECR_MASK 0x7f000000
+#define DECR_VAL 0xa
+#define set_decr(a) (((a) << 24) & DECR_MASK)
+
+#define LPM_SEL (0x1 << 23)
+#define FLADJ_MASK 0x003fff00
+#define FLADJ_VAL 0x7f0
+#define set_fladj(a) (((a) << 8) & FLADJ_MASK)
+
+#define DOUBLE_PCIE_MODE 0x0
+#define P0_PCIE_ADD_P1_USB3 (0x1 << 12)
+#define DOUBLE_USB3 (0x2 << 12)
+
+#define PCIE_X1_MODE (0x0 << 12)
+#define USB3_MODE (0x1 << 12)
+
+static struct bsp_priv *usb_priv = NULL;
+
+
+
+int usb_get_max_speed(struct device *dev)
+{
+ unsigned int ret;
+ struct device_node *np = dev->of_node;
+
+ if (np == NULL)
+ return -EINVAL;
+
+ usb_priv = kzalloc(sizeof(*usb_priv), GFP_KERNEL);
+ if (usb_priv == NULL)
+ return -ENOMEM;
+
+ usb_priv->peri_crg = of_iomap(np, DEV_NODE_FLAG1);
+ if (IS_ERR(usb_priv->peri_crg)) {
+ kfree(usb_priv);
+ usb_priv = NULL;
+ return -ENOMEM;
+ }
+
+ usb_priv->sys_ctrl = of_iomap(np, DEV_NODE_FLAG2);
+ if (IS_ERR(usb_priv->sys_ctrl)) {
+ iounmap(usb_priv->peri_crg);
+
+ kfree(usb_priv);
+ usb_priv = NULL;
+ return -ENOMEM;
+ }
+
+ ret = usb_get_maximum_speed(dev);
+
+ iounmap(usb_priv->sys_ctrl);
+ iounmap(usb_priv->peri_crg);
+
+ return ret;
+}
+EXPORT_SYMBOL(usb_get_max_speed);
+
+void bsp_dwc3_exited(void)
+{
+ kfree(usb_priv);
+ usb_priv = NULL;
+}
+EXPORT_SYMBOL(bsp_dwc3_exited);
+
+static int set_ctrl_crg_val(struct device_node *np, struct dwc3_host *host)
+{
+ unsigned int ret;
+ unsigned int reg;
+
+ if ((np == NULL) || (host == NULL))
+ return -EINVAL;
+
+ /* get usb ctrl crg para */
+ ret = of_property_read_u32(np, "crg_offset", &host->crg_offset);
+ if (ret)
+ return ret;
+
+ ret = of_property_read_u32(np, "crg_ctrl_def_mask", &host->crg_ctrl_def_mask);
+ if (ret)
+ return ret;
+
+ ret = of_property_read_u32(np, "crg_ctrl_def_val", &host->crg_ctrl_def_val);
+ if (ret)
+ return ret;
+
+ /* write usb ctrl crg default value */
+ reg = readl(host->crg_base + host->crg_offset);
+ reg &= ~host->crg_ctrl_def_mask;
+ reg |= host->crg_ctrl_def_val;
+ writel(reg, host->crg_base + host->crg_offset);
+
+ return 0;
+}
+
+static int dwc3_bsp_clk_init(struct dwc3_host *host, int count)
+{
+ struct device *dev = host->dev;
+ struct device_node *np = dev->of_node;
+ int i, ret;
+
+ if (!count)
+ return -EINVAL;
+
+ if (np == NULL)
+ return -EINVAL;
+
+ host->num_clocks = count;
+
+ host->clks = devm_kcalloc(dev, host->num_clocks, sizeof(struct clk *), GFP_KERNEL);
+ if (host->clks == NULL)
+ return -ENOMEM;
+
+ for (i = 0; i < host->num_clocks; i++) {
+ struct clk *clk;
+
+ clk = of_clk_get(np, i);
+ if (IS_ERR(clk)) {
+ while (--i >= 0)
+ clk_put(host->clks[i]);
+
+ ret = PTR_ERR(clk);
+ goto clk_free;
+ }
+
+ ret = clk_prepare_enable(clk);
+ if (ret < 0) {
+ while (--i >= 0) {
+ clk_disable_unprepare(host->clks[i]);
+ clk_put(host->clks[i]);
+ }
+ clk_put(clk);
+
+ goto clk_free;
+ }
+
+ host->clks[i] = clk;
+ }
+
+ return 0;
+clk_free:
+ devm_kfree(dev, host->clks);
+ host->clks = NULL;
+
+ return ret;
+}
+
+static void control_free_clk_config(struct dwc3_host *host)
+{
+ unsigned int reg;
+
+ if (host == NULL)
+ return;
+
+ reg = readl(host->ctrl_base + GUSB2PHYCFG_OFFSET);
+ reg &= ~U2_FREECLK_EXISTS;
+ writel(reg, host->ctrl_base + GUSB2PHYCFG_OFFSET);
+
+ reg = readl(host->ctrl_base + GCTL_OFFSET);
+ reg &= ~SOFITPSYNC;
+ writel(reg, host->ctrl_base + GCTL_OFFSET);
+
+ reg = readl(host->ctrl_base + GUCTL_OFFSET);
+ reg &= ~REFCLKPER_MASK;
+ reg |= set_refclkper(REFCLKPER_VAL);
+ writel(reg, host->ctrl_base + GUCTL_OFFSET);
+
+ reg = readl(host->ctrl_base + GFLADJ_OFFSET);
+ reg &= ~PLS1;
+ writel(reg, host->ctrl_base + GFLADJ_OFFSET);
+
+ reg = readl(host->ctrl_base + GFLADJ_OFFSET);
+ reg &= ~DECR_MASK;
+ reg |= set_decr(DECR_VAL);
+ writel(reg, host->ctrl_base + GFLADJ_OFFSET);
+
+ reg = readl(host->ctrl_base + GFLADJ_OFFSET);
+ reg |= LPM_SEL;
+ writel(reg, host->ctrl_base + GFLADJ_OFFSET);
+
+ reg = readl(host->ctrl_base + GFLADJ_OFFSET);
+ reg &= ~FLADJ_MASK;
+ reg |= set_fladj(FLADJ_VAL);
+ writel(reg, host->ctrl_base + GFLADJ_OFFSET);
+}
+
+static int dwc3_bsp_iomap(struct device_node *np, struct dwc3_host *host)
+{
+ if ((np == NULL) || (host == NULL))
+ return -EINVAL;
+
+ host->ctrl_base = of_iomap(np, DEV_NODE_FLAG0);
+ if (IS_ERR(host->ctrl_base))
+ return -ENOMEM;
+
+ host->crg_base = of_iomap(np, DEV_NODE_FLAG1);
+ if (IS_ERR(host->crg_base)) {
+ iounmap(host->ctrl_base);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static int dwc3_bsp_probe(struct platform_device *pdev)
+{
+ struct dwc3_host *host = NULL;
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ int ret, i;
+
+ host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL);
+ if (host == NULL)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, host);
+ host->dev = dev;
+
+ ret = dwc3_bsp_iomap(np, host);
+ if (ret) {
+ devm_kfree(dev, host);
+ host = NULL;
+
+ return -ENOMEM;
+ }
+
+ host->port_rst = devm_reset_control_get(dev, "vcc_reset");
+ if (IS_ERR_OR_NULL(host->port_rst)) {
+ ret = PTR_ERR(host->port_rst);
+ goto dwc3_unmap;
+ }
+
+ ret = set_ctrl_crg_val(np, host);
+ if (ret)
+ goto dwc3_unmap;
+
+ reset_control_assert(host->port_rst);
+
+ ret = dwc3_bsp_clk_init(host, of_clk_get_parent_count(np));
+ if (ret)
+ goto dwc3_unmap;
+
+ reset_control_deassert(host->port_rst);
+
+ control_free_clk_config(host);
+
+ udelay(U_LEVEL2);
+
+ ret = of_platform_populate(np, NULL, NULL, dev);
+ if (ret) {
+ for (i = 0; i < host->num_clocks; i++) {
+ clk_disable_unprepare(host->clks[i]);
+ clk_put(host->clks[i]);
+ }
+ goto dwc3_unmap;
+ }
+
+ return 0;
+dwc3_unmap:
+ iounmap(host->ctrl_base);
+ iounmap(host->crg_base);
+
+ devm_kfree(dev, host);
+ host = NULL;
+
+ return ret;
+}
+
+static int dwc3_bsp_remove(struct platform_device *pdev)
+{
+ struct dwc3_host *host = platform_get_drvdata(pdev);
+ struct device *dev = &pdev->dev;
+ int i;
+
+ for (i = 0; i < host->num_clocks; i++) {
+ clk_disable_unprepare(host->clks[i]);
+ clk_put(host->clks[i]);
+ }
+
+ reset_control_assert(host->port_rst);
+
+ of_platform_depopulate(dev);
+
+ iounmap(host->ctrl_base);
+ iounmap(host->crg_base);
+
+ devm_kfree(dev, host);
+ host = NULL;
+
+ return 0;
+}
+
+static const struct of_device_id bsp_dwc3_match[] = {
+ { .compatible = "goke,dwusb2" },
+ { .compatible = "goke,dwusb3" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, bsp_dwc3_match);
+
+static struct platform_driver dwc3_bsp_driver = {
+ .probe = dwc3_bsp_probe,
+ .remove = dwc3_bsp_remove,
+ .driver = {
+ .name = "goke-dwc3",
+ .of_match_table = bsp_dwc3_match,
+ },
+};
+module_platform_driver(dwc3_bsp_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("DesignWare USB3 of Goke");
+MODULE_AUTHOR("Goke Technologies Co., Ltd..>");
diff -urN linux-4.9.37/drivers/usb/dwc3/dwc3-goke.h linux-4.9.y/drivers/usb/dwc3/dwc3-goke.h
--- linux-4.9.37/drivers/usb/dwc3/dwc3-goke.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/usb/dwc3/dwc3-goke.h 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#ifndef USB_INCLUDE_DWC3_GOKE_H
+#define USB_INCLUDE_DWC3_GOKE_H
+
+struct bsp_priv {
+ void __iomem *peri_crg;
+ void __iomem *sys_ctrl;
+ void __iomem *misc_ctrl;
+ unsigned int speed_id;
+};
+
+struct dwc3_host {
+ struct device *dev;
+ struct clk **clks;
+ int num_clocks;
+ void __iomem *ctrl_base;
+ void __iomem *crg_base;
+ struct reset_control *port_rst;
+ u32 crg_offset;
+ u32 crg_ctrl_def_mask;
+ u32 crg_ctrl_def_val;
+};
+
+extern int usb_get_max_speed(struct device *dev);
+extern void bsp_dwc3_exited(void);
+
+#define DEV_NODE_FLAG0 0
+#define DEV_NODE_FLAG1 1
+#define DEV_NODE_FLAG2 2
+
+#define U_LEVEL2 200
+
+#endif
diff -urN linux-4.9.37/drivers/usb/dwc3/ep0.c linux-4.9.y/drivers/usb/dwc3/ep0.c
--- linux-4.9.37/drivers/usb/dwc3/ep0.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/dwc3/ep0.c 2021-06-07 13:01:34.000000000 +0300
@@ -39,22 +39,6 @@
static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
struct dwc3_ep *dep, struct dwc3_request *req);
-static const char *dwc3_ep0_state_string(enum dwc3_ep0_state state)
-{
- switch (state) {
- case EP0_UNCONNECTED:
- return "Unconnected";
- case EP0_SETUP_PHASE:
- return "Setup Phase";
- case EP0_DATA_PHASE:
- return "Data Phase";
- case EP0_STATUS_PHASE:
- return "Status Phase";
- default:
- return "UNKNOWN";
- }
-}
-
static void dwc3_ep0_prepare_one_trb(struct dwc3 *dwc, u8 epnum,
dma_addr_t buf_dma, u32 len, u32 type, bool chain)
{
@@ -92,21 +76,16 @@
int ret;
dep = dwc->eps[epnum];
- if (dep->flags & DWC3_EP_BUSY) {
- dwc3_trace(trace_dwc3_ep0, "%s still busy", dep->name);
+ if (dep->flags & DWC3_EP_BUSY)
return 0;
- }
memset(&params, 0, sizeof(params));
params.param0 = upper_32_bits(dwc->ep0_trb_addr);
params.param1 = lower_32_bits(dwc->ep0_trb_addr);
ret = dwc3_send_gadget_ep_cmd(dep, DWC3_DEPCMD_STARTTRANSFER, &params);
- if (ret < 0) {
- dwc3_trace(trace_dwc3_ep0, "%s STARTTRANSFER failed",
- dep->name);
+ if (ret < 0)
return ret;
- }
dep->flags |= DWC3_EP_BUSY;
dep->resource_index = dwc3_gadget_ep_get_transfer_index(dep);
@@ -166,9 +145,6 @@
if (dwc->ep0state == EP0_STATUS_PHASE)
__dwc3_ep0_do_control_status(dwc, dwc->eps[direction]);
- else
- dwc3_trace(trace_dwc3_ep0,
- "too early for delayed status");
return 0;
}
@@ -232,9 +208,8 @@
spin_lock_irqsave(&dwc->lock, flags);
if (!dep->endpoint.desc) {
- dwc3_trace(trace_dwc3_ep0,
- "trying to queue request %p to disabled %s",
- request, dep->name);
+ dev_err(dwc->dev, "%s: can't queue to disabled endpoint\n",
+ dep->name);
ret = -ESHUTDOWN;
goto out;
}
@@ -245,11 +220,6 @@
goto out;
}
- dwc3_trace(trace_dwc3_ep0,
- "queueing request %p to %s length %d state '%s'",
- request, dep->name, request->length,
- dwc3_ep0_state_string(dwc->ep0state));
-
ret = __dwc3_gadget_ep0_queue(dep, req);
out:
@@ -317,6 +287,24 @@
WARN_ON(ret < 0);
}
+static u32 dwc3_usbep_to_dwc3ep(struct dwc3 *dwc, u32 num)
+{
+ u32 res = 0;
+ int i = 0;
+
+ if (!dwc)
+ return 0;
+
+ for (i = 0; i < dwc->num_in_eps + dwc->num_out_eps; i++) {
+ if (dwc->dwceps_map_to_usbeps[i] == num) {
+ res = i;
+ break;
+ }
+ }
+
+ return res;
+}
+
static struct dwc3_ep *dwc3_wIndex_to_dep(struct dwc3 *dwc, __le16 wIndex_le)
{
struct dwc3_ep *dep;
@@ -327,6 +315,9 @@
if ((windex & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
epnum |= 1;
+ if (dwc->eps_new_init)
+ epnum = dwc3_usbep_to_dwc3ep(dwc, epnum);
+
dep = dwc->eps[epnum];
if (dep->flags & DWC3_EP_ENABLED)
return dep;
@@ -399,126 +390,203 @@
return __dwc3_gadget_ep0_queue(dep, &dwc->ep0_usb_req);
}
-static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
+static int dwc3_ep0_handle_u1(struct dwc3 *dwc, enum usb_device_state state,
+ int set)
+{
+ u32 reg;
+
+ if (state != USB_STATE_CONFIGURED)
+ return -EINVAL;
+ if ((dwc->speed != DWC3_DSTS_SUPERSPEED) &&
+ (dwc->speed != DWC3_DSTS_SUPERSPEED_PLUS))
+ return -EINVAL;
+
+ if (dwc->dis_initiate_u1)
+ return -EINVAL;
+
+ reg = dwc3_readl(dwc->regs, DWC3_DCTL);
+ if (set)
+ reg |= DWC3_DCTL_INITU1ENA;
+ else
+ reg &= ~DWC3_DCTL_INITU1ENA;
+ dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+
+ return 0;
+}
+
+static int dwc3_ep0_handle_u2(struct dwc3 *dwc, enum usb_device_state state,
+ int set)
+{
+ u32 reg;
+
+
+ if (state != USB_STATE_CONFIGURED)
+ return -EINVAL;
+ if ((dwc->speed != DWC3_DSTS_SUPERSPEED) &&
+ (dwc->speed != DWC3_DSTS_SUPERSPEED_PLUS))
+ return -EINVAL;
+
+ if (dwc->dis_initiate_u2)
+ return -EINVAL;
+
+ reg = dwc3_readl(dwc->regs, DWC3_DCTL);
+ if (set)
+ reg |= DWC3_DCTL_INITU2ENA;
+ else
+ reg &= ~DWC3_DCTL_INITU2ENA;
+ dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+
+ return 0;
+}
+
+static int dwc3_ep0_handle_test(struct dwc3 *dwc, enum usb_device_state state,
+ u32 wIndex, int set)
+{
+ if ((wIndex & 0xff) != 0)
+ return -EINVAL;
+ if (!set)
+ return -EINVAL;
+
+ switch (wIndex >> 8) {
+ case TEST_J:
+ case TEST_K:
+ case TEST_SE0_NAK:
+ case TEST_PACKET:
+ case TEST_FORCE_EN:
+ dwc->test_mode_nr = wIndex >> 8;
+ dwc->test_mode = true;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int dwc3_ep0_handle_device(struct dwc3 *dwc,
struct usb_ctrlrequest *ctrl, int set)
{
- struct dwc3_ep *dep;
- u32 recip;
+ enum usb_device_state state;
u32 wValue;
u32 wIndex;
- u32 reg;
- int ret;
- enum usb_device_state state;
+ int ret = 0;
wValue = le16_to_cpu(ctrl->wValue);
wIndex = le16_to_cpu(ctrl->wIndex);
- recip = ctrl->bRequestType & USB_RECIP_MASK;
state = dwc->gadget.state;
- switch (recip) {
- case USB_RECIP_DEVICE:
+ switch (wValue) {
+ case USB_DEVICE_REMOTE_WAKEUP:
+ break;
+ /*
+ * 9.4.1 says only only for SS, in AddressState only for
+ * default control pipe
+ */
+ case USB_DEVICE_U1_ENABLE:
+ ret = dwc3_ep0_handle_u1(dwc, state, set);
+ break;
+ case USB_DEVICE_U2_ENABLE:
+ ret = dwc3_ep0_handle_u2(dwc, state, set);
+ break;
+ case USB_DEVICE_LTM_ENABLE:
+ ret = -EINVAL;
+ break;
+ case USB_DEVICE_TEST_MODE:
+ ret = dwc3_ep0_handle_test(dwc, state, wIndex, set);
+ break;
+ default:
+ ret = -EINVAL;
+ }
- switch (wValue) {
- case USB_DEVICE_REMOTE_WAKEUP:
- break;
- /*
- * 9.4.1 says only only for SS, in AddressState only for
- * default control pipe
- */
- case USB_DEVICE_U1_ENABLE:
- if (state != USB_STATE_CONFIGURED)
- return -EINVAL;
- if ((dwc->speed != DWC3_DSTS_SUPERSPEED) &&
- (dwc->speed != DWC3_DSTS_SUPERSPEED_PLUS))
- return -EINVAL;
+ return ret;
+}
- reg = dwc3_readl(dwc->regs, DWC3_DCTL);
- if (set)
- reg |= DWC3_DCTL_INITU1ENA;
- else
- reg &= ~DWC3_DCTL_INITU1ENA;
- dwc3_writel(dwc->regs, DWC3_DCTL, reg);
- break;
+static int dwc3_ep0_handle_intf(struct dwc3 *dwc,
+ struct usb_ctrlrequest *ctrl, int set)
+{
+ enum usb_device_state state;
+ u32 wValue;
+ u32 wIndex;
+ int ret = 0;
- case USB_DEVICE_U2_ENABLE:
- if (state != USB_STATE_CONFIGURED)
- return -EINVAL;
- if ((dwc->speed != DWC3_DSTS_SUPERSPEED) &&
- (dwc->speed != DWC3_DSTS_SUPERSPEED_PLUS))
- return -EINVAL;
+ wValue = le16_to_cpu(ctrl->wValue);
+ wIndex = le16_to_cpu(ctrl->wIndex);
+ state = dwc->gadget.state;
- reg = dwc3_readl(dwc->regs, DWC3_DCTL);
- if (set)
- reg |= DWC3_DCTL_INITU2ENA;
- else
- reg &= ~DWC3_DCTL_INITU2ENA;
- dwc3_writel(dwc->regs, DWC3_DCTL, reg);
- break;
+ switch (wValue) {
+ case USB_INTRF_FUNC_SUSPEND:
+ if (wIndex & USB_INTRF_FUNC_SUSPEND_LP)
+ /* XXX enable Low power suspend */
+ ;
+ if (wIndex & USB_INTRF_FUNC_SUSPEND_RW)
+ /* XXX enable remote wakeup */
+ ;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int dwc3_ep0_handle_endpoint(struct dwc3 *dwc,
+ struct usb_ctrlrequest *ctrl, int set)
+{
+ struct dwc3_ep *dep;
+ enum usb_device_state state;
+ u32 wValue;
+ u32 wIndex;
+ int ret;
- case USB_DEVICE_LTM_ENABLE:
+ wValue = le16_to_cpu(ctrl->wValue);
+ wIndex = le16_to_cpu(ctrl->wIndex);
+ state = dwc->gadget.state;
+
+ switch (wValue) {
+ case USB_ENDPOINT_HALT:
+ dep = dwc3_wIndex_to_dep(dwc, ctrl->wIndex);
+ if (!dep)
return -EINVAL;
- case USB_DEVICE_TEST_MODE:
- if ((wIndex & 0xff) != 0)
- return -EINVAL;
- if (!set)
- return -EINVAL;
-
- switch (wIndex >> 8) {
- case TEST_J:
- case TEST_K:
- case TEST_SE0_NAK:
- case TEST_PACKET:
- case TEST_FORCE_EN:
- dwc->test_mode_nr = wIndex >> 8;
- dwc->test_mode = true;
- break;
- default:
- return -EINVAL;
- }
+ if (set == 0 && (dep->flags & DWC3_EP_WEDGE))
break;
- default:
+
+ ret = __dwc3_gadget_ep_set_halt(dep, set, true);
+ if (ret)
return -EINVAL;
- }
break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
+ struct usb_ctrlrequest *ctrl, int set)
+{
+ u32 recip;
+ int ret;
+ enum usb_device_state state;
+
+ recip = ctrl->bRequestType & USB_RECIP_MASK;
+ state = dwc->gadget.state;
+ switch (recip) {
+ case USB_RECIP_DEVICE:
+ ret = dwc3_ep0_handle_device(dwc, ctrl, set);
+ break;
case USB_RECIP_INTERFACE:
- switch (wValue) {
- case USB_INTRF_FUNC_SUSPEND:
- if (wIndex & USB_INTRF_FUNC_SUSPEND_LP)
- /* XXX enable Low power suspend */
- ;
- if (wIndex & USB_INTRF_FUNC_SUSPEND_RW)
- /* XXX enable remote wakeup */
- ;
- break;
- default:
- return -EINVAL;
- }
+ ret = dwc3_ep0_handle_intf(dwc, ctrl, set);
break;
-
case USB_RECIP_ENDPOINT:
- switch (wValue) {
- case USB_ENDPOINT_HALT:
- dep = dwc3_wIndex_to_dep(dwc, ctrl->wIndex);
- if (!dep)
- return -EINVAL;
- if (set == 0 && (dep->flags & DWC3_EP_WEDGE))
- break;
- ret = __dwc3_gadget_ep_set_halt(dep, set, true);
- if (ret)
- return -EINVAL;
- break;
- default:
- return -EINVAL;
- }
+ ret = dwc3_ep0_handle_endpoint(dwc, ctrl, set);
break;
-
default:
- return -EINVAL;
+ ret = -EINVAL;
}
- return 0;
+ return ret;
}
static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
@@ -529,13 +597,12 @@
addr = le16_to_cpu(ctrl->wValue);
if (addr > 127) {
- dwc3_trace(trace_dwc3_ep0, "invalid device address %d", addr);
+ dev_err(dwc->dev, "invalid device address %d\n", addr);
return -EINVAL;
}
if (state == USB_STATE_CONFIGURED) {
- dwc3_trace(trace_dwc3_ep0,
- "trying to set address when configured");
+ dev_err(dwc->dev, "can't SetAddress() from Configured State\n");
return -EINVAL;
}
@@ -595,7 +662,15 @@
* nothing is pending from application.
*/
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
- reg |= (DWC3_DCTL_ACCEPTU1ENA | DWC3_DCTL_ACCEPTU2ENA);
+ if (dwc->dis_initiate_u1)
+ reg &= (~DWC3_DCTL_ACCEPTU1ENA);
+ else
+ reg |= DWC3_DCTL_ACCEPTU1ENA;
+
+ if (dwc->dis_initiate_u2)
+ reg &= (~DWC3_DCTL_ACCEPTU2ENA);
+ else
+ reg |= DWC3_DCTL_ACCEPTU2ENA;
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
}
break;
@@ -720,35 +795,27 @@
switch (ctrl->bRequest) {
case USB_REQ_GET_STATUS:
- dwc3_trace(trace_dwc3_ep0, "USB_REQ_GET_STATUS");
ret = dwc3_ep0_handle_status(dwc, ctrl);
break;
case USB_REQ_CLEAR_FEATURE:
- dwc3_trace(trace_dwc3_ep0, "USB_REQ_CLEAR_FEATURE");
ret = dwc3_ep0_handle_feature(dwc, ctrl, 0);
break;
case USB_REQ_SET_FEATURE:
- dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_FEATURE");
ret = dwc3_ep0_handle_feature(dwc, ctrl, 1);
break;
case USB_REQ_SET_ADDRESS:
- dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_ADDRESS");
ret = dwc3_ep0_set_address(dwc, ctrl);
break;
case USB_REQ_SET_CONFIGURATION:
- dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_CONFIGURATION");
ret = dwc3_ep0_set_config(dwc, ctrl);
break;
case USB_REQ_SET_SEL:
- dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_SEL");
ret = dwc3_ep0_set_sel(dwc, ctrl);
break;
case USB_REQ_SET_ISOCH_DELAY:
- dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_ISOCH_DELAY");
ret = dwc3_ep0_set_isoch_delay(dwc, ctrl);
break;
default:
- dwc3_trace(trace_dwc3_ep0, "Forwarding to gadget driver");
ret = dwc3_ep0_delegate_req(dwc, ctrl);
break;
}
@@ -824,9 +891,6 @@
status = DWC3_TRB_SIZE_TRBSTS(trb->size);
if (status == DWC3_TRBSTS_SETUP_PENDING) {
dwc->setup_packet_pending = true;
-
- dwc3_trace(trace_dwc3_ep0, "Setup Pending received");
-
if (r)
dwc3_gadget_giveback(ep0, r, -ECONNRESET);
@@ -916,7 +980,7 @@
ret = dwc3_gadget_set_test_mode(dwc, dwc->test_mode_nr);
if (ret < 0) {
- dwc3_trace(trace_dwc3_ep0, "Invalid Test #%d",
+ dev_err(dwc->dev, "invalid test #%d\n",
dwc->test_mode_nr);
dwc3_ep0_stall_and_restart(dwc);
return;
@@ -924,10 +988,8 @@
}
status = DWC3_TRB_SIZE_TRBSTS(trb->size);
- if (status == DWC3_TRBSTS_SETUP_PENDING) {
+ if (status == DWC3_TRBSTS_SETUP_PENDING)
dwc->setup_packet_pending = true;
- dwc3_trace(trace_dwc3_ep0, "Setup Pending received");
- }
dwc->ep0state = EP0_SETUP_PHASE;
dwc3_ep0_out_start(dwc);
@@ -944,17 +1006,14 @@
switch (dwc->ep0state) {
case EP0_SETUP_PHASE:
- dwc3_trace(trace_dwc3_ep0, "Setup Phase");
dwc3_ep0_inspect_setup(dwc, event);
break;
case EP0_DATA_PHASE:
- dwc3_trace(trace_dwc3_ep0, "Data Phase");
dwc3_ep0_complete_data(dwc, event);
break;
case EP0_STATUS_PHASE:
- dwc3_trace(trace_dwc3_ep0, "Status Phase");
dwc3_ep0_complete_status(dwc, event);
break;
default:
@@ -981,10 +1040,8 @@
ret = usb_gadget_map_request(&dwc->gadget, &req->request,
dep->number);
- if (ret) {
- dwc3_trace(trace_dwc3_ep0, "failed to map request");
+ if (ret)
return;
- }
maxpacket = dep->endpoint.maxpacket;
@@ -1010,10 +1067,8 @@
} else {
ret = usb_gadget_map_request(&dwc->gadget, &req->request,
dep->number);
- if (ret) {
- dwc3_trace(trace_dwc3_ep0, "failed to map request");
+ if (ret)
return;
- }
dwc3_ep0_prepare_one_trb(dwc, dep->number, req->request.dma,
req->request.length, DWC3_TRBCTL_CONTROL_DATA,
@@ -1073,8 +1128,6 @@
{
switch (event->status) {
case DEPEVT_STATUS_CONTROL_DATA:
- dwc3_trace(trace_dwc3_ep0, "Control Data");
-
/*
* We already have a DATA transfer in the controller's cache,
* if we receive a XferNotReady(DATA) we will ignore it, unless
@@ -1087,8 +1140,7 @@
if (dwc->ep0_expect_in != event->endpoint_number) {
struct dwc3_ep *dep = dwc->eps[dwc->ep0_expect_in];
- dwc3_trace(trace_dwc3_ep0,
- "Wrong direction for Data phase");
+ dev_err(dwc->dev, "unexpected direction for Data Phase\n");
dwc3_ep0_end_control_data(dwc, dep);
dwc3_ep0_stall_and_restart(dwc);
return;
@@ -1100,13 +1152,10 @@
if (dwc->ep0_next_event != DWC3_EP0_NRDY_STATUS)
return;
- dwc3_trace(trace_dwc3_ep0, "Control Status");
-
dwc->ep0state = EP0_STATUS_PHASE;
if (dwc->delayed_status) {
WARN_ON_ONCE(event->endpoint_number != 1);
- dwc3_trace(trace_dwc3_ep0, "Delayed Status");
return;
}
@@ -1117,10 +1166,6 @@
void dwc3_ep0_interrupt(struct dwc3 *dwc,
const struct dwc3_event_depevt *event)
{
- dwc3_trace(trace_dwc3_ep0, "%s: state '%s'",
- dwc3_ep_event_string(event),
- dwc3_ep0_state_string(dwc->ep0state));
-
switch (event->endpoint_event) {
case DWC3_DEPEVT_XFERCOMPLETE:
dwc3_ep0_xfer_complete(dwc, event);
diff -urN linux-4.9.37/drivers/usb/dwc3/gadget.c linux-4.9.y/drivers/usb/dwc3/gadget.c
--- linux-4.9.37/drivers/usb/dwc3/gadget.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/dwc3/gadget.c 2021-06-07 13:01:34.000000000 +0300
@@ -35,6 +35,15 @@
#include "gadget.h"
#include "io.h"
+static void dwc3_gadget_sync_connected_status(struct dwc3 *dwc);
+static int __dwc3_gadget_get_frame(struct dwc3 *dwc);
+static void dwc3_gadget_endpoint_frame_from_event(struct dwc3_ep *dep,
+ const struct dwc3_event_depevt *event);
+static bool __dwc3_gadget_target_frame_elapsed(struct dwc3_ep *dep);
+
+#define DWC3_ALIGN_FRAME(d) (((d)->frame_number + (d)->interval) \
+ & ~((d)->interval - 1))
+
/**
* dwc3_gadget_set_test_mode - Enables USB2 Test Modes
* @dwc: pointer to our context structure
@@ -139,9 +148,6 @@
udelay(5);
}
- dwc3_trace(trace_dwc3_gadget,
- "link state change request timed out");
-
return -ETIMEDOUT;
}
@@ -153,7 +159,7 @@
* if it is point to the link TRB, wrap around to the beginning. The
* link TRB is always at the last TRB entry.
*/
-static void dwc3_ep_inc_trb(u8 *index)
+static void dwc3_ep_inc_trb(u32 *index)
{
(*index)++;
if (*index == (DWC3_TRB_NUM - 1))
@@ -247,7 +253,7 @@
struct dwc3_gadget_ep_cmd_params *params)
{
struct dwc3 *dwc = dep->dwc;
- u32 timeout = 500;
+ u32 timeout = 5000;
u32 reg;
int cmd_status = 0;
@@ -563,8 +569,6 @@
u32 reg;
int ret;
- dwc3_trace(trace_dwc3_gadget, "Enabling %s", dep->name);
-
if (!(dep->flags & DWC3_EP_ENABLED)) {
ret = dwc3_gadget_start_config(dwc, dep);
if (ret)
@@ -590,7 +594,7 @@
dwc3_writel(dwc->regs, DWC3_DALEPENA, reg);
if (usb_endpoint_xfer_control(desc))
- return 0;
+ goto out;
/* Initialize the TRB ring */
dep->trb_dequeue = 0;
@@ -608,15 +612,19 @@
trb_link->ctrl |= DWC3_TRB_CTRL_HWO;
}
+
+out:
+ trace_dwc3_gadget_ep_enable(dep);
+
return 0;
}
-static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum, bool force);
+static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force);
static void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep)
{
struct dwc3_request *req;
- dwc3_stop_active_transfer(dwc, dep->number, true);
+ dwc3_stop_active_transfer(dep, true);
/* - giveback all requests to gadget driver */
while (!list_empty(&dep->started_list)) {
@@ -645,7 +653,7 @@
struct dwc3 *dwc = dep->dwc;
u32 reg;
- dwc3_trace(trace_dwc3_gadget, "Disabling %s", dep->name);
+ trace_dwc3_gadget_ep_disable(dep);
dwc3_remove_requests(dwc, dep);
@@ -787,10 +795,7 @@
struct dwc3 *dwc = dep->dwc;
struct usb_gadget *gadget = &dwc->gadget;
enum usb_device_speed speed = gadget->speed;
-
- dwc3_trace(trace_dwc3_gadget, "%s: req %p dma %08llx length %d%s",
- dep->name, req, (unsigned long long) dma,
- length, chain ? " chain" : "");
+ unsigned int chain_skip = 0;
trb = &dep->trb_pool[dep->trb_enqueue];
@@ -816,12 +821,55 @@
case USB_ENDPOINT_XFER_ISOC:
if (!node) {
trb->ctrl = DWC3_TRBCTL_ISOCHRONOUS_FIRST;
-
+ /*
+ * USB Specification 2.0 Section 5.9.2 states that: "If
+ * there is only a single transaction in the microframe,
+ * only a DATA0 data packet PID is used. If there are
+ * two transactions per microframe, DATA1 is used for
+ * the first transaction data packet and DATA0 is used
+ * for the second transaction data packet. If there are
+ * three transactions per microframe, DATA2 is used for
+ * the first transaction data packet, DATA1 is used for
+ * the second, and DATA0 is used for the third."
+ *
+ * IOW, we should satisfy the following cases:
+ *
+ * 1) length <= maxpacket
+ * - DATA0
+ *
+ * 2) maxpacket < length <= (2 * maxpacket)
+ * - DATA1, DATA0
+ *
+ * 3) (2 * maxpacket) < length <= (3 * maxpacket)
+ * - DATA2, DATA1, DATA0
+ */
if (speed == USB_SPEED_HIGH) {
struct usb_ep *ep = &dep->endpoint;
- trb->size |= DWC3_TRB_SIZE_PCM1(ep->mult - 1);
+ //unsigned int mult = ep->mult - 1;
+ unsigned int mult = 2; //backport commit ec5bb87e4e2a1d3a35563a7bcfac9febf67aba9d
+ unsigned int maxp = usb_endpoint_maxp(ep->desc);
+
+ if (length <= (2 * maxp))
+ mult--;
+
+ if (length <= maxp)
+ mult--;
+
+ trb->size |= DWC3_TRB_SIZE_PCM1(mult);
+
+ /*
+ * If there are three transactions per mframe,
+ * and each transcation length = 1024B, no any
+ * chain trb needed, so skip it.
+ */
+ if (length == (3 * maxp))
+ chain_skip = 1;
}
+
+ if (speed == USB_SPEED_SUPER)
+ chain_skip = 1;
} else {
+ chain_skip = 1;
trb->ctrl = DWC3_TRBCTL_ISOCHRONOUS;
}
@@ -848,7 +896,7 @@
(dwc3_calc_trbs_left(dep) == 0))
trb->ctrl |= DWC3_TRB_CTRL_IOC | DWC3_TRB_CTRL_ISP_IMI;
- if (chain)
+ if ((!chain_skip) && chain)
trb->ctrl |= DWC3_TRB_CTRL_CHN;
if (usb_endpoint_xfer_bulk(dep->endpoint.desc) && dep->stream_capable)
@@ -868,9 +916,9 @@
* index is 0, we will wrap backwards, skip the link TRB, and return
* the one just before that.
*/
-static struct dwc3_trb *dwc3_ep_prev_trb(struct dwc3_ep *dep, u8 index)
+static struct dwc3_trb *dwc3_ep_prev_trb(struct dwc3_ep *dep, u32 index)
{
- u8 tmp = index;
+ u32 tmp = index;
if (!tmp)
tmp = DWC3_TRB_NUM - 1;
@@ -881,7 +929,7 @@
static u32 dwc3_calc_trbs_left(struct dwc3_ep *dep)
{
struct dwc3_trb *tmp;
- u8 trbs_left;
+ u32 trbs_left;
/*
* If enqueue & dequeue are equal than it is either full or empty.
@@ -910,11 +958,13 @@
static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep,
struct dwc3_request *req)
{
+ struct dwc3 *dwc = dep->dwc;
+ struct usb_gadget *gadget = &dwc->gadget;
+ enum usb_device_speed speed = gadget->speed;
struct scatterlist *sg = req->sg;
struct scatterlist *s;
- unsigned int length;
+ unsigned int length, i;
dma_addr_t dma;
- int i;
for_each_sg(sg, s, req->num_pending_sgs, i) {
unsigned chain = true;
@@ -925,8 +975,11 @@
if (sg_is_last(s))
chain = false;
- dwc3_prepare_one_trb(dep, req, dma, length,
- chain, i);
+ if ((speed == USB_SPEED_HIGH) &&
+ usb_endpoint_xfer_isoc(dep->endpoint.desc))
+ dwc3_prepare_one_trb(dep, req, dma, length, chain, 0);
+ else
+ dwc3_prepare_one_trb(dep, req, dma, length, chain, i);
if (!dwc3_calc_trbs_left(dep))
break;
@@ -994,11 +1047,22 @@
memset(&params, 0, sizeof(params));
- if (starting) {
+ if (starting && !(dep->flags&DWC3_EP_UPDATE)) {
params.param0 = upper_32_bits(req->trb_dma);
params.param1 = lower_32_bits(req->trb_dma);
- cmd = DWC3_DEPCMD_STARTTRANSFER |
- DWC3_DEPCMD_PARAM(cmd_param);
+
+ if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
+ while (__dwc3_gadget_target_frame_elapsed(dep))
+ dep->frame_number = DWC3_ALIGN_FRAME(dep);
+
+ dep->frame_number = DWC3_ALIGN_FRAME(dep);
+ cmd_param = dep->frame_number;
+ }
+
+ cmd = DWC3_DEPCMD_STARTTRANSFER | DWC3_DEPCMD_PARAM(cmd_param);
+
+ if (usb_endpoint_xfer_isoc(dep->endpoint.desc))
+ dep->flags |= DWC3_EP_UPDATE;
} else {
cmd = DWC3_DEPCMD_UPDATETRANSFER |
DWC3_DEPCMD_PARAM(dep->resource_index);
@@ -1027,34 +1091,36 @@
return 0;
}
-static void __dwc3_gadget_start_isoc(struct dwc3 *dwc,
- struct dwc3_ep *dep, u32 cur_uf)
-{
- u32 uf;
+static bool __dwc3_gadget_target_frame_elapsed(struct dwc3_ep *dep) {
+ u16 cframe = __dwc3_gadget_get_frame(dep->dwc);
+ u16 eframe = dep->frame_number & DWC3_EVENT_PRAM_SOFFN_MASK;
+
+ if (eframe == cframe)
+ return true;
+
+ return (((eframe - cframe) & DWC3_EVENT_PRAM_SOFFN_MASK)
+ > DWC3_EVENT_PRAM_MAX_SOFFN / 2);
+}
+static void __dwc3_gadget_start_isoc(struct dwc3_ep *dep)
+{
if (list_empty(&dep->pending_list)) {
- dwc3_trace(trace_dwc3_gadget,
- "ISOC ep %s run out for requests",
- dep->name);
dep->flags |= DWC3_EP_PENDING_REQUEST;
return;
}
- /* 4 micro frames in the future */
- uf = cur_uf + dep->interval * 4;
+ while (__dwc3_gadget_target_frame_elapsed(dep))
+ dep->frame_number = DWC3_ALIGN_FRAME(dep);
- __dwc3_gadget_kick_transfer(dep, uf);
+ dep->frame_number = DWC3_ALIGN_FRAME(dep);
+ __dwc3_gadget_kick_transfer(dep, dep->frame_number);
}
-static void dwc3_gadget_start_isoc(struct dwc3 *dwc,
- struct dwc3_ep *dep, const struct dwc3_event_depevt *event)
+static void dwc3_gadget_start_isoc(struct dwc3_ep *dep,
+ const struct dwc3_event_depevt *event)
{
- u32 cur_uf, mask;
-
- mask = ~(dep->interval - 1);
- cur_uf = event->parameters & mask;
-
- __dwc3_gadget_start_isoc(dwc, dep, cur_uf);
+ dwc3_gadget_endpoint_frame_from_event(dep, event);
+ __dwc3_gadget_start_isoc(dep);
}
static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
@@ -1063,16 +1129,15 @@
int ret;
if (!dep->endpoint.desc) {
- dwc3_trace(trace_dwc3_gadget,
- "trying to queue request %p to disabled %s",
- &req->request, dep->endpoint.name);
+ dev_err(dwc->dev, "%s: can't queue to disabled endpoint\n",
+ dep->name);
return -ESHUTDOWN;
}
if (WARN(req->dep != dep, "request %pK belongs to '%s'\n",
&req->request, req->dep->name)) {
- dwc3_trace(trace_dwc3_gadget, "request %pK belongs to '%s'",
- &req->request, req->dep->name);
+ dev_err(dwc->dev, "%s: request %p belongs to '%s'\n",
+ dep->name, &req->request, req->dep->name);
return -EINVAL;
}
@@ -1106,7 +1171,7 @@
if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
if ((dep->flags & DWC3_EP_PENDING_REQUEST) &&
list_empty(&dep->started_list)) {
- dwc3_stop_active_transfer(dwc, dep->number, true);
+ dwc3_stop_active_transfer(dep, true);
dep->flags = DWC3_EP_ENABLED;
}
return 0;
@@ -1116,10 +1181,6 @@
return 0;
ret = __dwc3_gadget_kick_transfer(dep, 0);
- if (ret && ret != -EBUSY)
- dwc3_trace(trace_dwc3_gadget,
- "%s: failed to kick transfers",
- dep->name);
if (ret == -EBUSY)
ret = 0;
@@ -1138,7 +1199,6 @@
struct usb_request *request;
struct usb_ep *ep = &dep->endpoint;
- dwc3_trace(trace_dwc3_gadget, "queueing ZLP");
request = dwc3_gadget_ep_alloc_request(ep, GFP_ATOMIC);
if (!request)
return -ENOMEM;
@@ -1197,6 +1257,10 @@
spin_lock_irqsave(&dwc->lock, flags);
+
+ if (list_empty(&dep->pending_list) && list_empty(&dep->started_list) )
+ goto out0 ;
+
list_for_each_entry(r, &dep->pending_list, list) {
if (r == req)
break;
@@ -1209,7 +1273,7 @@
}
if (r == req) {
/* wait until it is processed */
- dwc3_stop_active_transfer(dwc, dep->number, true);
+ dwc3_stop_active_transfer(dep, true);
goto out1;
}
dev_err(dwc->dev, "request %pK was not queued to %s\n",
@@ -1247,9 +1311,6 @@
unsigned transfer_in_flight;
unsigned started;
- if (dep->flags & DWC3_EP_STALL)
- return 0;
-
if (dep->number > 1)
trb = dwc3_ep_prev_trb(dep, dep->trb_enqueue);
else
@@ -1260,9 +1321,6 @@
if (!protocol && ((dep->direction && transfer_in_flight) ||
(!dep->direction && started))) {
- dwc3_trace(trace_dwc3_gadget,
- "%s: pending request, cannot halt",
- dep->name);
return -EAGAIN;
}
@@ -1274,8 +1332,6 @@
else
dep->flags |= DWC3_EP_STALL;
} else {
- if (!(dep->flags & DWC3_EP_STALL))
- return 0;
ret = dwc3_send_clear_stall_ep_cmd(dep);
if (ret)
@@ -1355,15 +1411,21 @@
/* -------------------------------------------------------------------------- */
-static int dwc3_gadget_get_frame(struct usb_gadget *g)
+static int __dwc3_gadget_get_frame(struct dwc3 *dwc)
{
- struct dwc3 *dwc = gadget_to_dwc(g);
u32 reg;
reg = dwc3_readl(dwc->regs, DWC3_DSTS);
return DWC3_DSTS_SOFFN(reg);
}
+static int dwc3_gadget_get_frame(struct usb_gadget *g)
+{
+ struct dwc3 *dwc = gadget_to_dwc(g);
+
+ return __dwc3_gadget_get_frame(dwc);
+}
+
static int __dwc3_gadget_wakeup(struct dwc3 *dwc)
{
int retries;
@@ -1384,10 +1446,8 @@
speed = reg & DWC3_DSTS_CONNECTSPD;
if ((speed == DWC3_DSTS_SUPERSPEED) ||
- (speed == DWC3_DSTS_SUPERSPEED_PLUS)) {
- dwc3_trace(trace_dwc3_gadget, "no wakeup on SuperSpeed");
+ (speed == DWC3_DSTS_SUPERSPEED_PLUS))
return 0;
- }
link_state = DWC3_DSTS_USBLNKST(reg);
@@ -1396,9 +1456,6 @@
case DWC3_LINK_STATE_U3: /* in HS, means SUSPEND */
break;
default:
- dwc3_trace(trace_dwc3_gadget,
- "can't wakeup from '%s'",
- dwc3_gadget_link_string(link_state));
return -EINVAL;
}
@@ -1503,11 +1560,6 @@
if (!timeout)
return -ETIMEDOUT;
- dwc3_trace(trace_dwc3_gadget, "gadget %s data soft-%s",
- dwc->gadget_driver
- ? dwc->gadget_driver->function : "no-function",
- is_on ? "connect" : "disconnect");
-
return 0;
}
@@ -1677,6 +1729,7 @@
/* begin to receive SETUP packets */
dwc->ep0state = EP0_SETUP_PHASE;
+ dwc->link_state = DWC3_LINK_STATE_SS_DIS;
dwc3_ep0_out_start(dwc);
dwc3_gadget_enable_irq(dwc);
@@ -1767,6 +1820,81 @@
.udc_stop = dwc3_gadget_stop,
};
+static int dwc3_gadget_init_hw_all_endpoints(struct dwc3 *dwc)
+{
+ struct dwc3_ep *dep;
+ struct dwc3_hwparams *parms = &dwc->hwparams;
+ u32 direction = dwc->eps_directions;
+ u8 num_eps = DWC3_NUM_EPS(parms);
+ u8 num_in_eps = 0;
+ u8 num_out_eps = 0;
+ u8 epnum = 0;
+ u8 i;
+
+ if (!direction)
+ direction = DWC3_EPS_DEFAULT_DIRECTIONS;
+
+ for (i = 0; i < num_eps; i++) {
+ if (direction & 0x1)
+ epnum = (num_in_eps++ << 1) + 1;
+ else
+ epnum = (num_out_eps++ << 1);
+
+ dep = kzalloc(sizeof(*dep), GFP_KERNEL);
+ if (!dep)
+ return -ENOMEM;
+
+ dep->dwc = dwc;
+ dep->number = epnum;
+ dep->direction = !!(direction & 0x1);
+ dep->regs = dwc->regs + DWC3_DEP_BASE(i);
+ dwc->eps[i] = dep;
+
+ snprintf(dep->name, sizeof(dep->name), "ep%d%s", epnum >> 1,
+ (epnum & 1) ? "in" : "out");
+
+ dep->endpoint.name = dep->name;
+ spin_lock_init(&dep->lock);
+
+ if (epnum == 0 || epnum == 1) {
+ usb_ep_set_maxpacket_limit(&dep->endpoint, 512);
+ dep->endpoint.maxburst = 1;
+ dep->endpoint.ops = &dwc3_gadget_ep0_ops;
+ if (!epnum)
+ dwc->gadget.ep0 = &dep->endpoint;
+ } else {
+ int ret;
+
+ usb_ep_set_maxpacket_limit(&dep->endpoint, 1024);
+ dep->endpoint.max_streams = 15;
+ dep->endpoint.ops = &dwc3_gadget_ep_ops;
+ list_add_tail(&dep->endpoint.ep_list,
+ &dwc->gadget.ep_list);
+
+ ret = dwc3_alloc_trb_pool(dep);
+ if (ret)
+ return ret;
+ }
+
+ if (epnum == 0 || epnum == 1) {
+ dep->endpoint.caps.type_control = true;
+ } else {
+ dep->endpoint.caps.type_iso = true;
+ dep->endpoint.caps.type_bulk = true;
+ dep->endpoint.caps.type_int = true;
+ }
+
+ dep->endpoint.caps.dir_in = !!(direction & 0x1);
+ dep->endpoint.caps.dir_out = !(direction & 0x1);
+ direction = (direction >> 1);
+
+ INIT_LIST_HEAD(&dep->pending_list);
+ INIT_LIST_HEAD(&dep->started_list);
+ }
+
+ return 0;
+}
+
/* -------------------------------------------------------------------------- */
static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc,
@@ -1794,8 +1922,6 @@
dep->endpoint.name = dep->name;
spin_lock_init(&dep->lock);
- dwc3_trace(trace_dwc3_gadget, "initializing %s", dep->name);
-
if (epnum == 0 || epnum == 1) {
usb_ep_set_maxpacket_limit(&dep->endpoint, 512);
dep->endpoint.maxburst = 1;
@@ -1840,17 +1966,24 @@
INIT_LIST_HEAD(&dwc->gadget.ep_list);
+ if (dwc->eps_new_init) {
+ ret = dwc3_gadget_init_hw_all_endpoints(dwc);
+ if (ret < 0) {
+ dev_err(dwc->dev, "failed to initialize OUT endpoints\n");
+ return ret;
+ }
+ return 0;
+ }
+
ret = dwc3_gadget_init_hw_endpoints(dwc, dwc->num_out_eps, 0);
if (ret < 0) {
- dwc3_trace(trace_dwc3_gadget,
- "failed to allocate OUT endpoints");
+ dev_err(dwc->dev, "failed to initialize OUT endpoints\n");
return ret;
}
ret = dwc3_gadget_init_hw_endpoints(dwc, dwc->num_in_eps, 1);
if (ret < 0) {
- dwc3_trace(trace_dwc3_gadget,
- "failed to allocate IN endpoints");
+ dev_err(dwc->dev, "failed to initialize IN endpoints\n");
return ret;
}
@@ -1886,14 +2019,12 @@
/* -------------------------------------------------------------------------- */
-static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep,
- struct dwc3_request *req, struct dwc3_trb *trb,
- const struct dwc3_event_depevt *event, int status,
- int chain)
+static int __dwc3_cleanup_done_trbs(struct dwc3_ep *dep, struct dwc3_request *req,
+ struct dwc3_trb *trb, const struct dwc3_event_depevt *event,
+ int status, int chain)
{
unsigned int count;
unsigned int s_pkt = 0;
- unsigned int trb_status;
dwc3_ep_inc_deq(dep);
@@ -1922,37 +2053,6 @@
req->request.actual += count;
if (dep->direction) {
- if (count) {
- trb_status = DWC3_TRB_SIZE_TRBSTS(trb->size);
- if (trb_status == DWC3_TRBSTS_MISSED_ISOC) {
- dwc3_trace(trace_dwc3_gadget,
- "%s: incomplete IN transfer",
- dep->name);
- /*
- * If missed isoc occurred and there is
- * no request queued then issue END
- * TRANSFER, so that core generates
- * next xfernotready and we will issue
- * a fresh START TRANSFER.
- * If there are still queued request
- * then wait, do not issue either END
- * or UPDATE TRANSFER, just attach next
- * request in pending_list during
- * giveback.If any future queued request
- * is successfully transferred then we
- * will issue UPDATE TRANSFER for all
- * request in the pending_list.
- */
- dep->flags |= DWC3_EP_MISSED_ISOC;
- } else {
- dev_err(dwc->dev, "incomplete IN transfer %s\n",
- dep->name);
- status = -ECONNRESET;
- }
- } else {
- dep->flags &= ~DWC3_EP_MISSED_ISOC;
- }
- } else {
if (count && (event->status & DEPEVT_STATUS_SHORT))
s_pkt = 1;
}
@@ -1967,7 +2067,7 @@
return 0;
}
-static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
+static int dwc3_cleanup_done_reqs(struct dwc3_ep *dep,
const struct dwc3_event_depevt *event, int status)
{
struct dwc3_request *req, *n;
@@ -1994,14 +2094,14 @@
req->sg = sg_next(s);
req->num_pending_sgs--;
- ret = __dwc3_cleanup_done_trbs(dwc, dep, req, trb,
+ ret = __dwc3_cleanup_done_trbs(dep, req, trb,
event, status, chain);
if (ret)
break;
}
} else {
trb = &dep->trb_pool[dep->trb_dequeue];
- ret = __dwc3_cleanup_done_trbs(dwc, dep, req, trb,
+ ret = __dwc3_cleanup_done_trbs(dep, req, trb,
event, status, chain);
}
@@ -2045,9 +2145,9 @@
* flag, so that END TRANSFER is issued when an
* entry is added into request list.
*/
- dep->flags = DWC3_EP_PENDING_REQUEST;
+ dep->flags |= DWC3_EP_PENDING_REQUEST;
} else {
- dwc3_stop_active_transfer(dwc, dep->number, true);
+ dwc3_stop_active_transfer(dep, true);
dep->flags = DWC3_EP_ENABLED;
}
return 1;
@@ -2059,19 +2159,28 @@
return 1;
}
-static void dwc3_endpoint_transfer_complete(struct dwc3 *dwc,
- struct dwc3_ep *dep, const struct dwc3_event_depevt *event)
+static void dwc3_gadget_endpoint_frame_from_event(struct dwc3_ep *dep,
+ const struct dwc3_event_depevt *event)
+{
+ dep->frame_number = event->parameters;
+}
+
+static void dwc3_endpoint_transfer_complete(struct dwc3_ep *dep,
+ const struct dwc3_event_depevt *event)
{
+ struct dwc3 *dwc = dep->dwc;
unsigned status = 0;
int clean_busy;
u32 is_xfer_complete;
+ dwc3_gadget_endpoint_frame_from_event(dep, event);
+
is_xfer_complete = (event->endpoint_event == DWC3_DEPEVT_XFERCOMPLETE);
if (event->status & DEPEVT_STATUS_BUSERR)
status = -ECONNRESET;
- clean_busy = dwc3_cleanup_done_reqs(dwc, dep, event, status);
+ clean_busy = dwc3_cleanup_done_reqs(dep, event, status);
if (clean_busy && (!dep->endpoint.desc || is_xfer_complete ||
usb_endpoint_xfer_isoc(dep->endpoint.desc)))
dep->flags &= ~DWC3_EP_BUSY;
@@ -2109,12 +2218,16 @@
if (!dep->endpoint.desc)
return;
- if (!usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
+ if (!usb_endpoint_xfer_isoc(dep->endpoint.desc) || (dep->flags&DWC3_EP_ENABLED)) {
int ret;
-
- ret = __dwc3_gadget_kick_transfer(dep, 0);
- if (!ret || ret == -EBUSY)
- return;
+ if (usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
+ (!(dep->flags & (DWC3_EP_BUSY | DWC3_EP_UPDATE)))) {
+ __dwc3_gadget_start_isoc(dep);
+ } else {
+ ret = __dwc3_gadget_kick_transfer(dep, 0);
+ if (!ret || ret == -EBUSY)
+ return;
+ }
}
}
@@ -2139,37 +2252,24 @@
dep->resource_index = 0;
if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
- dwc3_trace(trace_dwc3_gadget,
- "%s is an Isochronous endpoint",
- dep->name);
+ dev_err(dwc->dev, "XferComplete for Isochronous endpoint\n");
return;
}
- dwc3_endpoint_transfer_complete(dwc, dep, event);
+ dwc3_endpoint_transfer_complete(dep, event);
break;
case DWC3_DEPEVT_XFERINPROGRESS:
- dwc3_endpoint_transfer_complete(dwc, dep, event);
+ dwc3_endpoint_transfer_complete(dep, event);
break;
case DWC3_DEPEVT_XFERNOTREADY:
if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
- dwc3_gadget_start_isoc(dwc, dep, event);
+ dwc3_gadget_start_isoc(dep, event);
} else {
- int active;
int ret;
- active = event->status & DEPEVT_STATUS_TRANSFER_ACTIVE;
-
- dwc3_trace(trace_dwc3_gadget, "%s: reason %s",
- dep->name, active ? "Transfer Active"
- : "Transfer Not Active");
-
ret = __dwc3_gadget_kick_transfer(dep, 0);
if (!ret || ret == -EBUSY)
return;
-
- dwc3_trace(trace_dwc3_gadget,
- "%s: failed to kick transfers",
- dep->name);
}
break;
@@ -2179,26 +2279,9 @@
dep->name);
return;
}
-
- switch (event->status) {
- case DEPEVT_STREAMEVT_FOUND:
- dwc3_trace(trace_dwc3_gadget,
- "Stream %d found and started",
- event->parameters);
-
- break;
- case DEPEVT_STREAMEVT_NOTFOUND:
- /* FALLTHROUGH */
- default:
- dwc3_trace(trace_dwc3_gadget,
- "unable to find suitable stream");
- }
break;
case DWC3_DEPEVT_RXTXFIFOEVT:
- dwc3_trace(trace_dwc3_gadget, "%s FIFO Overrun", dep->name);
- break;
case DWC3_DEPEVT_EPCMDCMPLT:
- dwc3_trace(trace_dwc3_gadget, "Endpoint Command Complete");
break;
}
}
@@ -2242,15 +2325,13 @@
}
}
-static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum, bool force)
+static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force)
{
- struct dwc3_ep *dep;
+ struct dwc3 *dwc = dep->dwc;
struct dwc3_gadget_ep_cmd_params params;
u32 cmd;
int ret;
- dep = dwc->eps[epnum];
-
if (!dep->resource_index)
return;
@@ -2596,8 +2677,6 @@
(pwropt != DWC3_GHWPARAMS1_EN_PWROPT_HIB)) {
if ((dwc->link_state == DWC3_LINK_STATE_U3) &&
(next == DWC3_LINK_STATE_RESUME)) {
- dwc3_trace(trace_dwc3_gadget,
- "ignoring transition U3 -> Resume");
return;
}
}
@@ -2731,11 +2810,7 @@
break;
case DWC3_DEVICE_EVENT_EOPF:
/* It changed to be suspend event for version 2.30a and above */
- if (dwc->revision < DWC3_REVISION_230A) {
- dwc3_trace(trace_dwc3_gadget, "End of Periodic Frame");
- } else {
- dwc3_trace(trace_dwc3_gadget, "U3/L1-L2 Suspend Event");
-
+ if (dwc->revision >= DWC3_REVISION_230A) {
/*
* Ignore suspend event until the gadget enters into
* USB_STATE_CONFIGURED state.
@@ -2746,26 +2821,21 @@
}
break;
case DWC3_DEVICE_EVENT_SOF:
- dwc3_trace(trace_dwc3_gadget, "Start of Periodic Frame");
- break;
case DWC3_DEVICE_EVENT_ERRATIC_ERROR:
- dwc3_trace(trace_dwc3_gadget, "Erratic Error");
- break;
case DWC3_DEVICE_EVENT_CMD_CMPL:
- dwc3_trace(trace_dwc3_gadget, "Command Complete");
- break;
case DWC3_DEVICE_EVENT_OVERFLOW:
- dwc3_trace(trace_dwc3_gadget, "Overflow");
break;
+
default:
dev_WARN(dwc->dev, "UNKNOWN IRQ %d\n", event->type);
}
+ dwc3_gadget_sync_connected_status(dwc);
}
static void dwc3_process_event_entry(struct dwc3 *dwc,
const union dwc3_event *event)
{
- trace_dwc3_event(event->raw);
+ trace_dwc3_event(event->raw, dwc);
/* Endpoint IRQ, handle it and return early */
if (event->type.is_devspec == 0) {
@@ -2984,8 +3054,7 @@
* composite.c that we are USB 2.0 + LPM ECN.
*/
if (dwc->revision < DWC3_REVISION_220A)
- dwc3_trace(trace_dwc3_gadget,
- "Changing max_speed on rev %08x",
+ dev_info(dwc->dev, "changing max_speed on rev %08x\n",
dwc->revision);
dwc->gadget.max_speed = dwc->maximum_speed;
@@ -3005,6 +3074,8 @@
if (ret)
goto err5;
+ dwc3_proc_init(dwc);
+
ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget);
if (ret) {
dev_err(dwc->dev, "failed to register udc\n");
@@ -3042,6 +3113,8 @@
{
usb_del_gadget_udc(&dwc->gadget);
+ dwc3_proc_shutdown(dwc);
+
dwc3_gadget_free_endpoints(dwc);
dma_free_coherent(dwc->dev, DWC3_EP0_BOUNCE_SIZE,
@@ -3106,3 +3179,70 @@
enable_irq(dwc->irq_gadget);
}
}
+
+/*
+ * dwc3_gadget_sync_connected_status() function just for
+ * user space get udc connected status. and this function
+ * just report three status: Disconnected, Connected host,
+ * Connected charger.
+ *
+ * After some tests, report connected udc connected status by
+ * DSTS register, [21:18]USB Link Status and [2:0] Connect Speed.
+ *
+ * How to identify whitch status is the UDC connected?
+ * 1. Host connected:
+ * Host would reset udc, so dwc3 core get reset event interrupt,
+ * dwc3_gadget_reset_interrupt() set dwc->connected = true,
+ * so check connected host by dwc->connected == true
+ *
+ * 2. Disconnected:
+ * When vbus detect 5V lose, dwc3 core generated a disconnect event intr.
+ * dwc3_gadget_disconnect_interrupt() set dwc->connected = false.
+ * so check disconnected by dwc->connected == false
+ *
+ * 3. Charger connected: (Fixedme)
+ * As dwc3 core size, DP keep pullup register when connected to charger.
+ * no any port reset action created, so dwc3 would entry FullSpeed mode.
+ * so chect connected charger by FullSpeed && dwc->connectd == false
+ *
+ */
+static void dwc3_gadget_sync_connected_status(struct dwc3 *dwc)
+{
+ u32 reg;
+ u8 speed;
+ u8 state;
+ static int prev = UDC_DISCONNECTED;
+
+ reg = dwc3_readl(dwc->regs, DWC3_DSTS);
+ speed = reg & DWC3_DSTS_CONNECTSPD;
+ state = DWC3_DSTS_USBLNKST(reg);
+
+ /*
+ * step1 check is connected host?
+ */
+ if (dwc->connected == true) {
+ if (prev != UDC_CONNECT_HOST)
+ dwc->udc_connect_status = UDC_CONNECT_HOST;
+ goto out;
+ }
+
+ /*
+ * step2 disconectd status && fullspeed mode,
+ * as connected charger.
+ */
+ if ((speed == DWC3_DSTS_FULLSPEED) && (state != DWC3_LINK_STATE_SS_DIS)) {
+ if (prev != UDC_CONNECT_CHARGER)
+ dwc->udc_connect_status = UDC_CONNECT_CHARGER;
+ goto out;
+ }
+
+ /*
+ * step3 not host and charger connected, so just
+ * disconnectd.
+ */
+ if (prev != UDC_DISCONNECTED)
+ dwc->udc_connect_status = UDC_DISCONNECTED;
+
+out:
+ prev = dwc->udc_connect_status;
+}
diff -urN linux-4.9.37/drivers/usb/dwc3/host.c linux-4.9.y/drivers/usb/dwc3/host.c
--- linux-4.9.37/drivers/usb/dwc3/host.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/dwc3/host.c 2021-06-07 13:01:34.000000000 +0300
@@ -21,7 +21,7 @@
int dwc3_host_init(struct dwc3 *dwc)
{
- struct property_entry props[3];
+ struct property_entry props[4];
struct platform_device *xhci;
int ret, irq;
struct resource *res;
@@ -93,6 +93,9 @@
if (dwc->usb3_lpm_capable)
props[prop_idx++].name = "usb3-lpm-capable";
+ if (dwc->usb2_lpm_disable)
+ props[prop_idx++].name = "usb2-lpm-disable";
+
/**
* WORKAROUND: dwc3 revisions <=3.00a have a limitation
* where Port Disable command doesn't work.
diff -urN linux-4.9.37/drivers/usb/dwc3/io.h linux-4.9.y/drivers/usb/dwc3/io.h
--- linux-4.9.37/drivers/usb/dwc3/io.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/dwc3/io.h 2021-06-07 13:01:34.000000000 +0300
@@ -40,8 +40,7 @@
* documentation, so we revert it back to the proper addresses, the
* same way they are described on SNPS documentation
*/
- dwc3_trace(trace_dwc3_readl, "addr %p value %08x",
- base - DWC3_GLOBALS_REGS_START + offset, value);
+ trace_dwc3_readl(base - DWC3_GLOBALS_REGS_START, offset, value);
return value;
}
@@ -60,8 +59,7 @@
* documentation, so we revert it back to the proper addresses, the
* same way they are described on SNPS documentation
*/
- dwc3_trace(trace_dwc3_writel, "addr %p value %08x",
- base - DWC3_GLOBALS_REGS_START + offset, value);
+ trace_dwc3_writel(base - DWC3_GLOBALS_REGS_START, offset, value);
}
#endif /* __DRIVERS_USB_DWC3_IO_H */
diff -urN linux-4.9.37/drivers/usb/dwc3/Makefile linux-4.9.y/drivers/usb/dwc3/Makefile
--- linux-4.9.37/drivers/usb/dwc3/Makefile 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/dwc3/Makefile 2021-06-07 13:01:34.000000000 +0300
@@ -1,9 +1,12 @@
# define_trace.h needs to know how to find our header
CFLAGS_trace.o := -I$(src)
-obj-$(CONFIG_USB_DWC3) += dwc3.o
+obj-$(CONFIG_USB_DWC3) += dwc3.o dwc3-goke.o
-dwc3-y := core.o debug.o trace.o
+dwc3-y := core.o proc.o
+ifneq ($(CONFIG_TRACING),)
+dwc3-y += trace.o
+endif
ifneq ($(filter y,$(CONFIG_USB_DWC3_HOST) $(CONFIG_USB_DWC3_DUAL_ROLE)),)
dwc3-y += host.o
diff -urN linux-4.9.37/drivers/usb/dwc3/proc.c linux-4.9.y/drivers/usb/dwc3/proc.c
--- linux-4.9.37/drivers/usb/dwc3/proc.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/usb/dwc3/proc.c 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+
+#include "core.h"
+
+#define DWC3_PROC_ROOT "dwc3"
+#define DWC3_PROC_CONNECTED_STATUS "csts"
+
+static struct proc_dir_entry *proc_dwc3_dir = NULL;
+static int proc_dwc3_dir_cnt = 0;
+
+static void dwc3_stats_seq_printout(struct seq_file *s)
+{
+ struct dwc3 *dwc = s->private;
+
+ switch (dwc->udc_connect_status) {
+ case UDC_CONNECT_HOST:
+ seq_puts(s, "cnt2host\n");
+ break;
+ case UDC_CONNECT_CHARGER:
+ seq_puts(s, "cnt2charger\n");
+ break;
+ default:
+ seq_puts(s, "disconnected\n");
+ break;
+ }
+}
+
+/* define parameters where showed in proc file */
+static int dwc3_stats_seq_show(struct seq_file *s, void *v)
+{
+ if (s == NULL)
+ return -EINVAL;
+
+ dwc3_stats_seq_printout(s);
+ return 0;
+}
+
+/* proc file open */
+static int dwc3_stats_proc_open(struct inode *inode, struct file *file)
+{
+ if ((inode == NULL) || (file == NULL))
+ return -EINVAL;
+
+ return single_open(file, dwc3_stats_seq_show, PDE_DATA(inode));
+};
+
+/* proc file operation */
+static const struct file_operations dwc3_stats_proc_ops = {
+ .owner = THIS_MODULE,
+ .open = dwc3_stats_proc_open,
+ .read = seq_read,
+ .release = single_release,
+};
+
+int dwc3_proc_init(struct dwc3 *dwc)
+{
+ struct proc_dir_entry *proc_entry = NULL;
+
+ if (dwc == NULL)
+ return -EINVAL;
+
+ if (proc_dwc3_dir == NULL) {
+ proc_entry = proc_mkdir(DWC3_PROC_ROOT, NULL);
+ if (proc_entry == NULL) {
+ pr_err("%s: failed to create proc file %s\n",
+ __func__, DWC3_PROC_ROOT);
+ return 1;
+ }
+ proc_dwc3_dir = proc_entry;
+ }
+ proc_dwc3_dir_cnt++;
+
+ proc_entry = proc_mkdir(to_platform_device(dwc->dev)->name, proc_dwc3_dir);
+ if (proc_entry == NULL) {
+ pr_err("%s: failed to create proc file %s\n",
+ __func__, to_platform_device(dwc->dev)->name);
+ return -1;
+ }
+ dwc->parent_entry = proc_entry;
+
+ proc_entry = proc_create_data(DWC3_PROC_CONNECTED_STATUS,
+ 0, dwc->parent_entry, &dwc3_stats_proc_ops, dwc);
+ if (proc_entry == NULL) {
+ pr_err("%s: failed to create proc file %s\n",
+ __func__, DWC3_PROC_CONNECTED_STATUS);
+ return -1;
+ }
+ dwc->csts_entry = proc_entry;
+
+ /*
+ * add here if more proc information need.
+ */
+ return 0;
+}
+
+int dwc3_proc_shutdown(struct dwc3 *dwc)
+{
+ if (proc_dwc3_dir != NULL) {
+ remove_proc_entry(DWC3_PROC_CONNECTED_STATUS, dwc->parent_entry);
+ remove_proc_entry(to_platform_device(dwc->dev)->name, proc_dwc3_dir);
+ }
+
+ if (proc_dwc3_dir_cnt)
+ proc_dwc3_dir_cnt--;
+
+ if (proc_dwc3_dir_cnt == 0) {
+ remove_proc_entry(DWC3_PROC_ROOT, NULL);
+ proc_dwc3_dir = NULL;
+ }
+
+ return 0;
+}
diff -urN linux-4.9.37/drivers/usb/dwc3/trace.h linux-4.9.y/drivers/usb/dwc3/trace.h
--- linux-4.9.37/drivers/usb/dwc3/trace.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/dwc3/trace.h 2021-06-07 13:01:34.000000000 +0300
@@ -27,57 +27,53 @@
#include "core.h"
#include "debug.h"
-DECLARE_EVENT_CLASS(dwc3_log_msg,
- TP_PROTO(struct va_format *vaf),
- TP_ARGS(vaf),
- TP_STRUCT__entry(__dynamic_array(char, msg, DWC3_MSG_MAX)),
+DECLARE_EVENT_CLASS(dwc3_log_io,
+ TP_PROTO(void *base, u32 offset, u32 value),
+ TP_ARGS(base, offset, value),
+ TP_STRUCT__entry(
+ __field(void *, base)
+ __field(u32, offset)
+ __field(u32, value)
+ ),
TP_fast_assign(
- vsnprintf(__get_str(msg), DWC3_MSG_MAX, vaf->fmt, *vaf->va);
+ __entry->base = base;
+ __entry->offset = offset;
+ __entry->value = value;
),
- TP_printk("%s", __get_str(msg))
-);
-
-DEFINE_EVENT(dwc3_log_msg, dwc3_readl,
- TP_PROTO(struct va_format *vaf),
- TP_ARGS(vaf)
-);
-
-DEFINE_EVENT(dwc3_log_msg, dwc3_writel,
- TP_PROTO(struct va_format *vaf),
- TP_ARGS(vaf)
-);
-
-DEFINE_EVENT(dwc3_log_msg, dwc3_gadget,
- TP_PROTO(struct va_format *vaf),
- TP_ARGS(vaf)
+ TP_printk("addr %p value %08x", __entry->base + __entry->offset,
+ __entry->value)
);
-DEFINE_EVENT(dwc3_log_msg, dwc3_core,
- TP_PROTO(struct va_format *vaf),
- TP_ARGS(vaf)
+DEFINE_EVENT(dwc3_log_io, dwc3_readl,
+ TP_PROTO(void *base, u32 offset, u32 value),
+ TP_ARGS(base, offset, value)
);
-DEFINE_EVENT(dwc3_log_msg, dwc3_ep0,
- TP_PROTO(struct va_format *vaf),
- TP_ARGS(vaf)
+DEFINE_EVENT(dwc3_log_io, dwc3_writel,
+ TP_PROTO(void *base, u32 offset, u32 value),
+ TP_ARGS(base, offset, value)
);
DECLARE_EVENT_CLASS(dwc3_log_event,
- TP_PROTO(u32 event),
- TP_ARGS(event),
+ TP_PROTO(u32 event, struct dwc3 *dwc),
+ TP_ARGS(event, dwc),
TP_STRUCT__entry(
__field(u32, event)
+ __field(u32, ep0state)
+ __dynamic_array(char, str, DWC3_MSG_MAX)
),
TP_fast_assign(
__entry->event = event;
+ __entry->ep0state = dwc->ep0state;
),
TP_printk("event (%08x): %s", __entry->event,
- dwc3_decode_event(__entry->event))
+ dwc3_decode_event(__get_str(str), DWC3_MSG_MAX,
+ __entry->event, __entry->ep0state))
);
DEFINE_EVENT(dwc3_log_event, dwc3_event,
- TP_PROTO(u32 event),
- TP_ARGS(event)
+ TP_PROTO(u32 event, struct dwc3 *dwc),
+ TP_ARGS(event, dwc)
);
DECLARE_EVENT_CLASS(dwc3_log_ctrl,
@@ -89,6 +85,7 @@
__field(__u16, wValue)
__field(__u16, wIndex)
__field(__u16, wLength)
+ __dynamic_array(char, str, DWC3_MSG_MAX)
),
TP_fast_assign(
__entry->bRequestType = ctrl->bRequestType;
@@ -97,10 +94,10 @@
__entry->wIndex = le16_to_cpu(ctrl->wIndex);
__entry->wLength = le16_to_cpu(ctrl->wLength);
),
- TP_printk("bRequestType %02x bRequest %02x wValue %04x wIndex %04x wLength %d",
- __entry->bRequestType, __entry->bRequest,
- __entry->wValue, __entry->wIndex,
- __entry->wLength
+ TP_printk("%s", dwc3_decode_ctrl(__get_str(str), DWC3_MSG_MAX,
+ __entry->bRequestType,
+ __entry->bRequest, __entry->wValue,
+ __entry->wIndex, __entry->wLength)
)
);
@@ -113,7 +110,7 @@
TP_PROTO(struct dwc3_request *req),
TP_ARGS(req),
TP_STRUCT__entry(
- __dynamic_array(char, name, DWC3_MSG_MAX)
+ __string(name, req->dep->name)
__field(struct dwc3_request *, req)
__field(unsigned, actual)
__field(unsigned, length)
@@ -123,7 +120,7 @@
__field(int, no_interrupt)
),
TP_fast_assign(
- snprintf(__get_str(name), DWC3_MSG_MAX, "%s", req->dep->name);
+ __assign_str(name, req->dep->name);
__entry->req = req;
__entry->actual = req->request.actual;
__entry->length = req->request.length;
@@ -179,7 +176,7 @@
__entry->param = param;
__entry->status = status;
),
- TP_printk("cmd '%s' [%d] param %08x --> status: %s",
+ TP_printk("cmd '%s' [%x] param %08x --> status: %s",
dwc3_gadget_generic_cmd_string(__entry->cmd),
__entry->cmd, __entry->param,
dwc3_gadget_generic_cmd_status_string(__entry->status)
@@ -196,7 +193,7 @@
struct dwc3_gadget_ep_cmd_params *params, int cmd_status),
TP_ARGS(dep, cmd, params, cmd_status),
TP_STRUCT__entry(
- __dynamic_array(char, name, DWC3_MSG_MAX)
+ __string(name, dep->name)
__field(unsigned int, cmd)
__field(u32, param0)
__field(u32, param1)
@@ -204,14 +201,14 @@
__field(int, cmd_status)
),
TP_fast_assign(
- snprintf(__get_str(name), DWC3_MSG_MAX, "%s", dep->name);
+ __assign_str(name, dep->name);
__entry->cmd = cmd;
__entry->param0 = params->param0;
__entry->param1 = params->param1;
__entry->param2 = params->param2;
__entry->cmd_status = cmd_status;
),
- TP_printk("%s: cmd '%s' [%d] params %08x %08x %08x --> status: %s",
+ TP_printk("%s: cmd '%s' [%x] params %08x %08x %08x --> status: %s",
__get_str(name), dwc3_gadget_ep_cmd_string(__entry->cmd),
__entry->cmd, __entry->param0,
__entry->param1, __entry->param2,
@@ -229,7 +226,7 @@
TP_PROTO(struct dwc3_ep *dep, struct dwc3_trb *trb),
TP_ARGS(dep, trb),
TP_STRUCT__entry(
- __dynamic_array(char, name, DWC3_MSG_MAX)
+ __string(name, dep->name)
__field(struct dwc3_trb *, trb)
__field(u32, allocated)
__field(u32, queued)
@@ -237,9 +234,10 @@
__field(u32, bph)
__field(u32, size)
__field(u32, ctrl)
+ __field(u32, type)
),
TP_fast_assign(
- snprintf(__get_str(name), DWC3_MSG_MAX, "%s", dep->name);
+ __assign_str(name, dep->name);
__entry->trb = trb;
__entry->allocated = dep->allocated_requests;
__entry->queued = dep->queued_requests;
@@ -247,47 +245,40 @@
__entry->bph = trb->bph;
__entry->size = trb->size;
__entry->ctrl = trb->ctrl;
+ __entry->type = usb_endpoint_type(dep->endpoint.desc);
),
- TP_printk("%s: %d/%d trb %p buf %08x%08x size %d ctrl %08x (%c%c%c%c:%c%c:%s)",
+ TP_printk("%s: %d/%d trb %p buf %08x%08x size %s%d ctrl %08x (%c%c%c%c:%c%c:%s)",
__get_str(name), __entry->queued, __entry->allocated,
__entry->trb, __entry->bph, __entry->bpl,
- __entry->size, __entry->ctrl,
+ ({char *s;
+ int pcm = ((__entry->size >> 24) & 3) + 1;
+ switch (__entry->type) {
+ case USB_ENDPOINT_XFER_INT:
+ case USB_ENDPOINT_XFER_ISOC:
+ switch (pcm) {
+ case 1:
+ s = "1x ";
+ break;
+ case 2:
+ s = "2x ";
+ break;
+ case 3:
+ default:
+ s = "3x ";
+ break;
+ }
+ break;
+ default:
+ s = "";
+ } s; }),
+ DWC3_TRB_SIZE_LENGTH(__entry->size), __entry->ctrl,
__entry->ctrl & DWC3_TRB_CTRL_HWO ? 'H' : 'h',
__entry->ctrl & DWC3_TRB_CTRL_LST ? 'L' : 'l',
__entry->ctrl & DWC3_TRB_CTRL_CHN ? 'C' : 'c',
__entry->ctrl & DWC3_TRB_CTRL_CSP ? 'S' : 's',
__entry->ctrl & DWC3_TRB_CTRL_ISP_IMI ? 'S' : 's',
__entry->ctrl & DWC3_TRB_CTRL_IOC ? 'C' : 'c',
- ({char *s;
- switch (__entry->ctrl & 0x3f0) {
- case DWC3_TRBCTL_NORMAL:
- s = "normal";
- break;
- case DWC3_TRBCTL_CONTROL_SETUP:
- s = "setup";
- break;
- case DWC3_TRBCTL_CONTROL_STATUS2:
- s = "status2";
- break;
- case DWC3_TRBCTL_CONTROL_STATUS3:
- s = "status3";
- break;
- case DWC3_TRBCTL_CONTROL_DATA:
- s = "data";
- break;
- case DWC3_TRBCTL_ISOCHRONOUS_FIRST:
- s = "isoc-first";
- break;
- case DWC3_TRBCTL_ISOCHRONOUS:
- s = "isoc";
- break;
- case DWC3_TRBCTL_LINK_TRB:
- s = "link";
- break;
- default:
- s = "UNKNOWN";
- break;
- } s; })
+ dwc3_trb_type_string(DWC3_TRBCTL_TYPE(__entry->ctrl))
)
);
@@ -301,6 +292,56 @@
TP_ARGS(dep, trb)
);
+DECLARE_EVENT_CLASS(dwc3_log_ep,
+ TP_PROTO(struct dwc3_ep *dep),
+ TP_ARGS(dep),
+ TP_STRUCT__entry(
+ __string(name, dep->name)
+ __field(unsigned, maxpacket)
+ __field(unsigned, maxpacket_limit)
+ __field(unsigned, max_streams)
+ __field(unsigned, maxburst)
+ __field(unsigned, flags)
+ __field(unsigned, direction)
+ __field(u8, trb_enqueue)
+ __field(u8, trb_dequeue)
+ ),
+ TP_fast_assign(
+ __assign_str(name, dep->name);
+ __entry->maxpacket = dep->endpoint.maxpacket;
+ __entry->maxpacket_limit = dep->endpoint.maxpacket_limit;
+ __entry->max_streams = dep->endpoint.max_streams;
+ __entry->maxburst = dep->endpoint.maxburst;
+ __entry->flags = dep->flags;
+ __entry->direction = dep->direction;
+ __entry->trb_enqueue = dep->trb_enqueue;
+ __entry->trb_dequeue = dep->trb_dequeue;
+ ),
+ TP_printk("%s: mps %d/%d streams %d burst %d ring %d/%d flags %c:%c%c%c%c%c:%c",
+ __get_str(name), __entry->maxpacket,
+ __entry->maxpacket_limit, __entry->max_streams,
+ __entry->maxburst, __entry->trb_enqueue,
+ __entry->trb_dequeue,
+ __entry->flags & DWC3_EP_ENABLED ? 'E' : 'e',
+ __entry->flags & DWC3_EP_STALL ? 'S' : 's',
+ __entry->flags & DWC3_EP_WEDGE ? 'W' : 'w',
+ __entry->flags & DWC3_EP_BUSY ? 'B' : 'b',
+ __entry->flags & DWC3_EP_PENDING_REQUEST ? 'P' : 'p',
+ __entry->flags & DWC3_EP_MISSED_ISOC ? 'M' : 'm',
+ __entry->direction ? '<' : '>'
+ )
+);
+
+DEFINE_EVENT(dwc3_log_ep, dwc3_gadget_ep_enable,
+ TP_PROTO(struct dwc3_ep *dep),
+ TP_ARGS(dep)
+);
+
+DEFINE_EVENT(dwc3_log_ep, dwc3_gadget_ep_disable,
+ TP_PROTO(struct dwc3_ep *dep),
+ TP_ARGS(dep)
+);
+
#endif /* __DWC3_TRACE_H */
/* this part has to be here */
diff -urN linux-4.9.37/drivers/usb/gadget/composite.c linux-4.9.y/drivers/usb/gadget/composite.c
--- linux-4.9.37/drivers/usb/gadget/composite.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/gadget/composite.c 2021-06-07 13:01:34.000000000 +0300
@@ -205,7 +205,7 @@
if (g->speed == USB_SPEED_HIGH && (usb_endpoint_xfer_isoc(_ep->desc) ||
usb_endpoint_xfer_int(_ep->desc)))
- _ep->mult = ((usb_endpoint_maxp(_ep->desc) & 0x1800) >> 11) + 1;
+ _ep->mult = usb_endpoint_maxp_mult(_ep->desc);
if (!want_comp_desc)
return 0;
@@ -315,6 +315,9 @@
list_del(&f->list);
if (f->unbind)
f->unbind(c, f);
+
+ if (f->bind_deactivated)
+ usb_function_activate(f);
}
EXPORT_SYMBOL_GPL(usb_remove_function);
@@ -956,12 +959,8 @@
f = list_first_entry(&config->functions,
struct usb_function, list);
- list_del(&f->list);
- if (f->unbind) {
- DBG(cdev, "unbind function '%s'/%p\n", f->name, f);
- f->unbind(config, f);
- /* may free memory for "f" */
- }
+
+ usb_remove_function(config, f);
}
list_del(&config->list);
if (config->unbind) {
diff -urN linux-4.9.37/drivers/usb/gadget/configfs.c linux-4.9.y/drivers/usb/gadget/configfs.c
--- linux-4.9.37/drivers/usb/gadget/configfs.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/gadget/configfs.c 2021-06-07 13:01:34.000000000 +0300
@@ -1209,6 +1209,9 @@
list_for_each_entry_safe(f, tmp, &c->functions, list) {
+ if (f->disable)
+ f->disable(f);
+
list_move_tail(&f->list, &cfg->func_list);
if (f->unbind) {
dev_dbg(&gi->cdev.gadget->dev,
@@ -1216,6 +1219,9 @@
f->name, f);
f->unbind(c, f);
}
+
+ if (f->bind_deactivated)
+ usb_function_activate(f);
}
c->next_interface_id = 0;
memset(c->interface, 0, sizeof(c->interface));
diff -urN linux-4.9.37/drivers/usb/gadget/epautoconf.c linux-4.9.y/drivers/usb/gadget/epautoconf.c
--- linux-4.9.37/drivers/usb/gadget/epautoconf.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/gadget/epautoconf.c 2021-06-07 13:01:34.000000000 +0300
@@ -82,9 +82,16 @@
}
/* Second, look at endpoints until an unclaimed one looks usable */
- list_for_each_entry (ep, &gadget->ep_list, ep_list) {
- if (usb_gadget_ep_match_desc(gadget, ep, desc, ep_comp))
- goto found_ep;
+ if (type == USB_ENDPOINT_XFER_INT) {
+ list_for_each_entry_reverse(ep, &gadget->ep_list, ep_list) {
+ if (usb_gadget_ep_match_desc(gadget, ep, desc, ep_comp))
+ goto found_ep;
+ }
+ } else {
+ list_for_each_entry(ep, &gadget->ep_list, ep_list) {
+ if (usb_gadget_ep_match_desc(gadget, ep, desc, ep_comp))
+ goto found_ep;
+ }
}
/* Fail */
diff -urN linux-4.9.37/drivers/usb/gadget/function/f_hid.c linux-4.9.y/drivers/usb/gadget/function/f_hid.c
--- linux-4.9.37/drivers/usb/gadget/function/f_hid.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/gadget/function/f_hid.c 2021-06-07 13:01:34.000000000 +0300
@@ -284,6 +284,7 @@
size_t count, loff_t *offp)
{
struct f_hidg *hidg = file->private_data;
+ struct usb_request *req;
unsigned long flags;
ssize_t status = -ENOMEM;
@@ -293,7 +294,7 @@
spin_lock_irqsave(&hidg->write_spinlock, flags);
#define WRITE_COND (!hidg->write_pending)
-
+try_again:
/* write queue */
while (!WRITE_COND) {
spin_unlock_irqrestore(&hidg->write_spinlock, flags);
@@ -308,6 +309,7 @@
}
hidg->write_pending = 1;
+ req = hidg->req;
count = min_t(unsigned, count, hidg->report_length);
spin_unlock_irqrestore(&hidg->write_spinlock, flags);
@@ -320,24 +322,38 @@
goto release_write_pending;
}
- hidg->req->status = 0;
- hidg->req->zero = 0;
- hidg->req->length = count;
- hidg->req->complete = f_hidg_req_complete;
- hidg->req->context = hidg;
+ spin_lock_irqsave(&hidg->write_spinlock, flags);
+
+ /* we our function has been disabled by host */
+ if (!hidg->req) {
+ free_ep_req(hidg->in_ep, hidg->req);
+ /*
+ * TODO
+ * Should we fail with error here?
+ */
+ goto try_again;
+ }
+
+ req->status = 0;
+ req->zero = 0;
+ req->length = count;
+ req->complete = f_hidg_req_complete;
+ req->context = hidg;
status = usb_ep_queue(hidg->in_ep, hidg->req, GFP_ATOMIC);
if (status < 0) {
ERROR(hidg->func.config->cdev,
"usb_ep_queue error on int endpoint %zd\n", status);
- goto release_write_pending;
+ goto release_write_pending_unlocked;
} else {
status = count;
}
+ spin_unlock_irqrestore(&hidg->write_spinlock, flags);
return status;
release_write_pending:
spin_lock_irqsave(&hidg->write_spinlock, flags);
+release_write_pending_unlocked:
hidg->write_pending = 0;
spin_unlock_irqrestore(&hidg->write_spinlock, flags);
@@ -541,12 +557,23 @@
kfree(list);
}
spin_unlock_irqrestore(&hidg->read_spinlock, flags);
+
+ spin_lock_irqsave(&hidg->write_spinlock, flags);
+ if (!hidg->write_pending) {
+ free_ep_req(hidg->in_ep, hidg->req);
+ hidg->write_pending = 1;
+ }
+
+ hidg->req = NULL;
+ spin_unlock_irqrestore(&hidg->write_spinlock, flags);
}
static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
{
struct usb_composite_dev *cdev = f->config->cdev;
struct f_hidg *hidg = func_to_hidg(f);
+ struct usb_request *req_in = NULL;
+ unsigned long flags;
int i, status = 0;
VDBG(cdev, "hidg_set_alt intf:%d alt:%d\n", intf, alt);
@@ -567,6 +594,12 @@
goto fail;
}
hidg->in_ep->driver_data = hidg;
+
+ req_in = hidg_alloc_ep_req(hidg->in_ep, hidg->report_length);
+ if (!req_in) {
+ status = -ENOMEM;
+ goto disable_ep_in;
+ }
}
@@ -578,12 +611,12 @@
hidg->out_ep);
if (status) {
ERROR(cdev, "config_ep_by_speed FAILED!\n");
- goto fail;
+ goto free_req_in;
}
status = usb_ep_enable(hidg->out_ep);
if (status < 0) {
- ERROR(cdev, "Enable IN endpoint FAILED!\n");
- goto fail;
+ ERROR(cdev, "Enable OUT endpoint FAILED!\n");
+ goto free_req_in;
}
hidg->out_ep->driver_data = hidg;
@@ -599,17 +632,37 @@
req->context = hidg;
status = usb_ep_queue(hidg->out_ep, req,
GFP_ATOMIC);
- if (status)
+ if (status) {
ERROR(cdev, "%s queue req --> %d\n",
hidg->out_ep->name, status);
+ free_ep_req(hidg->out_ep, req);
+ }
} else {
- usb_ep_disable(hidg->out_ep);
status = -ENOMEM;
- goto fail;
+ goto disable_out_ep;
}
}
}
+ if (hidg->in_ep != NULL) {
+ spin_lock_irqsave(&hidg->write_spinlock, flags);
+ hidg->req = req_in;
+ hidg->write_pending = 0;
+ spin_unlock_irqrestore(&hidg->write_spinlock, flags);
+
+ wake_up(&hidg->write_queue);
+ }
+ return 0;
+disable_out_ep:
+ usb_ep_disable(hidg->out_ep);
+free_req_in:
+ if (req_in)
+ free_ep_req(hidg->in_ep, req_in);
+
+disable_ep_in:
+ if (hidg->in_ep)
+ usb_ep_disable(hidg->in_ep);
+
fail:
return status;
}
@@ -658,12 +711,6 @@
goto fail;
hidg->out_ep = ep;
- /* preallocate request and buffer */
- status = -ENOMEM;
- hidg->req = alloc_ep_req(hidg->in_ep, hidg->report_length);
- if (!hidg->req)
- goto fail;
-
/* set descriptor dynamic values */
hidg_interface_desc.bInterfaceSubClass = hidg->bInterfaceSubClass;
hidg_interface_desc.bInterfaceProtocol = hidg->bInterfaceProtocol;
@@ -690,6 +737,8 @@
goto fail;
spin_lock_init(&hidg->write_spinlock);
+ hidg->write_pending = 1;
+ hidg->req = NULL;
spin_lock_init(&hidg->read_spinlock);
init_waitqueue_head(&hidg->write_queue);
init_waitqueue_head(&hidg->read_queue);
@@ -954,10 +1003,6 @@
device_destroy(hidg_class, MKDEV(major, hidg->minor));
cdev_del(&hidg->cdev);
- /* disable/free request and end point */
- usb_ep_disable(hidg->in_ep);
- free_ep_req(hidg->in_ep, hidg->req);
-
usb_free_all_descriptors(f);
}
diff -urN linux-4.9.37/drivers/usb/gadget/function/f_mass_storage.c linux-4.9.y/drivers/usb/gadget/function/f_mass_storage.c
--- linux-4.9.37/drivers/usb/gadget/function/f_mass_storage.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/gadget/function/f_mass_storage.c 2021-06-07 13:01:34.000000000 +0300
@@ -301,6 +301,7 @@
unsigned int bad_lun_okay:1;
unsigned int running:1;
unsigned int sysfs:1;
+ unsigned int actived:1;
int thread_wakeup_needed;
struct completion thread_notifier;
@@ -1371,7 +1372,7 @@
up_read(&common->filesem);
down_write(&common->filesem);
- fsg_lun_close(curlun);
+ common->actived = 0;
up_write(&common->filesem);
down_read(&common->filesem);
@@ -1815,7 +1816,7 @@
/* If the medium isn't mounted and the command needs to access
* it, return an error. */
- if (curlun && !fsg_lun_is_open(curlun) && needs_medium) {
+ if (curlun && !common->actived && needs_medium) {
curlun->sense_data = SS_MEDIUM_NOT_PRESENT;
return -EINVAL;
}
@@ -2280,6 +2281,7 @@
}
common->running = 0;
+ common->actived = 0;
if (!new_fsg || rc)
return rc;
@@ -2323,7 +2325,7 @@
bh->inreq->complete = bulk_in_complete;
bh->outreq->complete = bulk_out_complete;
}
-
+ common->actived = 1;
common->running = 1;
for (i = 0; i < ARRAY_SIZE(common->luns); ++i)
if (common->luns[i])
diff -urN linux-4.9.37/drivers/usb/gadget/function/f_uac1.c linux-4.9.y/drivers/usb/gadget/function/f_uac1.c
--- linux-4.9.37/drivers/usb/gadget/function/f_uac1.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/gadget/function/f_uac1.c 2021-06-07 13:01:34.000000000 +0300
@@ -1,24 +1,34 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
- * f_audio.c -- USB Audio class function driver
- *
- * Copyright (C) 2008 Bryan Wu <cooloney@kernel.org>
- * Copyright (C) 2008 Analog Devices, Inc
+ * f_uac1.c -- USB Audio Class 1.0 Function (using u_audio API)
*
- * Enter bugs at http://blackfin.uclinux.org/
+ * Copyright (C) 2016 Ruslan Bilovol <ruslan.bilovol@gmail.com>
*
- * Licensed under the GPL-2 or later.
+ * This driver doesn't expect any real Audio codec to be present
+ * on the device - the audio streams are simply sinked to and
+ * sourced from a virtual ALSA sound card created.
+ *
+ * This file is based on f_uac1.c which is
+ * Copyright (C) 2008 Bryan Wu <cooloney@kernel.org>
+ * Copyright (C) 2008 Analog Devices, Inc
*/
-#include <linux/slab.h>
-#include <linux/kernel.h>
+#include <linux/usb/audio.h>
#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/atomic.h>
+#include "u_audio.h"
#include "u_uac1.h"
-static int generic_set_cmd(struct usb_audio_control *con, u8 cmd, int value);
-static int generic_get_cmd(struct usb_audio_control *con, u8 cmd);
+struct f_uac1 {
+ struct g_audio g_audio;
+ u8 ac_intf, as_in_intf, as_out_intf;
+ u8 ac_alt, as_in_alt, as_out_alt; /* needed for get_alt() */
+};
+
+static inline struct f_uac1 *func_to_uac1(struct usb_function *f)
+{
+ return container_of(f, struct f_uac1, g_audio.func);
+}
/*
* DESCRIPTORS ... most are static, but strings and full
@@ -26,12 +36,27 @@
*/
/*
- * We have two interfaces- AudioControl and AudioStreaming
- * TODO: only supcard playback currently
+ * We have three interfaces - one AudioControl and two AudioStreaming
+ *
+ * The driver implements a simple UAC_1 topology.
+ * USB-OUT -> IT_1 -> OT_2 -> ALSA_Capture
+ * ALSA_Playback -> IT_3 -> OT_4 -> USB-IN
*/
-#define F_AUDIO_AC_INTERFACE 0
-#define F_AUDIO_AS_INTERFACE 1
-#define F_AUDIO_NUM_INTERFACES 1
+#define F_AUDIO_AC_INTERFACE 0
+#define F_AUDIO_AS_OUT_INTERFACE 1
+#define F_AUDIO_AS_IN_INTERFACE 2
+/* Number of streaming interfaces */
+#define F_AUDIO_NUM_INTERFACES 2
+
+static struct usb_interface_assoc_descriptor uac_iad = {
+ .bLength = sizeof(uac_iad),
+ .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION,
+ .bFirstInterface = 0,
+ .bInterfaceCount = 3,
+ .bFunctionClass = USB_CLASS_AUDIO,
+ .bFunctionSubClass = 0,
+ .bFunctionProtocol = UAC_VERSION_1,
+};
/* B.3.1 Standard AC Interface Descriptor */
static struct usb_interface_descriptor ac_interface_desc = {
@@ -46,89 +71,91 @@
* The number of AudioStreaming and MIDIStreaming interfaces
* in the Audio Interface Collection
*/
-DECLARE_UAC_AC_HEADER_DESCRIPTOR(1);
+DECLARE_UAC_AC_HEADER_DESCRIPTOR(2);
#define UAC_DT_AC_HEADER_LENGTH UAC_DT_AC_HEADER_SIZE(F_AUDIO_NUM_INTERFACES)
-/* 1 input terminal, 1 output terminal and 1 feature unit */
-#define UAC_DT_TOTAL_LENGTH (UAC_DT_AC_HEADER_LENGTH + UAC_DT_INPUT_TERMINAL_SIZE \
- + UAC_DT_OUTPUT_TERMINAL_SIZE + UAC_DT_FEATURE_UNIT_SIZE(0))
+/* 2 input terminals and 2 output terminals */
+#define UAC_DT_TOTAL_LENGTH (UAC_DT_AC_HEADER_LENGTH \
+ + 2*UAC_DT_INPUT_TERMINAL_SIZE + 2*UAC_DT_OUTPUT_TERMINAL_SIZE)
/* B.3.2 Class-Specific AC Interface Descriptor */
-static struct uac1_ac_header_descriptor_1 ac_header_desc = {
+static struct uac1_ac_header_descriptor_2 ac_header_desc = {
.bLength = UAC_DT_AC_HEADER_LENGTH,
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubtype = UAC_HEADER,
- .bcdADC = __constant_cpu_to_le16(0x0100),
- .wTotalLength = __constant_cpu_to_le16(UAC_DT_TOTAL_LENGTH),
+ .bcdADC = cpu_to_le16(0x0100),
+ .wTotalLength = cpu_to_le16(UAC_DT_TOTAL_LENGTH),
.bInCollection = F_AUDIO_NUM_INTERFACES,
.baInterfaceNr = {
- /* Interface number of the first AudioStream interface */
+ /* Interface number of the AudioStream interfaces */
[0] = 1,
+ [1] = 2,
}
};
-#define INPUT_TERMINAL_ID 1
-static struct uac_input_terminal_descriptor input_terminal_desc = {
+#define USB_OUT_IT_ID 1
+static struct uac_input_terminal_descriptor usb_out_it_desc = {
.bLength = UAC_DT_INPUT_TERMINAL_SIZE,
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubtype = UAC_INPUT_TERMINAL,
- .bTerminalID = INPUT_TERMINAL_ID,
- .wTerminalType = UAC_TERMINAL_STREAMING,
+ .bTerminalID = USB_OUT_IT_ID,
+ .wTerminalType = cpu_to_le16(UAC_TERMINAL_STREAMING),
.bAssocTerminal = 0,
- .wChannelConfig = 0x3,
+ .wChannelConfig = cpu_to_le16(0x3),
};
-DECLARE_UAC_FEATURE_UNIT_DESCRIPTOR(0);
-
-#define FEATURE_UNIT_ID 2
-static struct uac_feature_unit_descriptor_0 feature_unit_desc = {
- .bLength = UAC_DT_FEATURE_UNIT_SIZE(0),
+#define IO_OUT_OT_ID 2
+static struct uac1_output_terminal_descriptor io_out_ot_desc = {
+ .bLength = UAC_DT_OUTPUT_TERMINAL_SIZE,
.bDescriptorType = USB_DT_CS_INTERFACE,
- .bDescriptorSubtype = UAC_FEATURE_UNIT,
- .bUnitID = FEATURE_UNIT_ID,
- .bSourceID = INPUT_TERMINAL_ID,
- .bControlSize = 2,
- .bmaControls[0] = (UAC_FU_MUTE | UAC_FU_VOLUME),
-};
-
-static struct usb_audio_control mute_control = {
- .list = LIST_HEAD_INIT(mute_control.list),
- .name = "Mute Control",
- .type = UAC_FU_MUTE,
- /* Todo: add real Mute control code */
- .set = generic_set_cmd,
- .get = generic_get_cmd,
-};
-
-static struct usb_audio_control volume_control = {
- .list = LIST_HEAD_INIT(volume_control.list),
- .name = "Volume Control",
- .type = UAC_FU_VOLUME,
- /* Todo: add real Volume control code */
- .set = generic_set_cmd,
- .get = generic_get_cmd,
-};
-
-static struct usb_audio_control_selector feature_unit = {
- .list = LIST_HEAD_INIT(feature_unit.list),
- .id = FEATURE_UNIT_ID,
- .name = "Mute & Volume Control",
- .type = UAC_FEATURE_UNIT,
- .desc = (struct usb_descriptor_header *)&feature_unit_desc,
+ .bDescriptorSubtype = UAC_OUTPUT_TERMINAL,
+ .bTerminalID = IO_OUT_OT_ID,
+ .wTerminalType = cpu_to_le16(UAC_OUTPUT_TERMINAL_SPEAKER),
+ .bAssocTerminal = 0,
+ .bSourceID = USB_OUT_IT_ID,
};
-#define OUTPUT_TERMINAL_ID 3
-static struct uac1_output_terminal_descriptor output_terminal_desc = {
- .bLength = UAC_DT_OUTPUT_TERMINAL_SIZE,
+#define IO_IN_IT_ID 3
+static struct uac_input_terminal_descriptor io_in_it_desc = {
+ .bLength = UAC_DT_INPUT_TERMINAL_SIZE,
.bDescriptorType = USB_DT_CS_INTERFACE,
- .bDescriptorSubtype = UAC_OUTPUT_TERMINAL,
- .bTerminalID = OUTPUT_TERMINAL_ID,
- .wTerminalType = UAC_OUTPUT_TERMINAL_SPEAKER,
- .bAssocTerminal = FEATURE_UNIT_ID,
- .bSourceID = FEATURE_UNIT_ID,
+ .bDescriptorSubtype = UAC_INPUT_TERMINAL,
+ .bTerminalID = IO_IN_IT_ID,
+ .wTerminalType = cpu_to_le16(UAC_INPUT_TERMINAL_MICROPHONE),
+ .bAssocTerminal = 0,
+ .wChannelConfig = cpu_to_le16(0x3),
+};
+
+#define USB_IN_OT_ID 4
+static struct uac1_output_terminal_descriptor usb_in_ot_desc = {
+ .bLength = UAC_DT_OUTPUT_TERMINAL_SIZE,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubtype = UAC_OUTPUT_TERMINAL,
+ .bTerminalID = USB_IN_OT_ID,
+ .wTerminalType = cpu_to_le16(UAC_TERMINAL_STREAMING),
+ .bAssocTerminal = 0,
+ .bSourceID = IO_IN_IT_ID,
};
/* B.4.1 Standard AS Interface Descriptor */
-static struct usb_interface_descriptor as_interface_alt_0_desc = {
+static struct usb_interface_descriptor as_out_interface_alt_0_desc = {
+ .bLength = USB_DT_INTERFACE_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 0,
+ .bInterfaceClass = USB_CLASS_AUDIO,
+ .bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING,
+};
+
+static struct usb_interface_descriptor as_out_interface_alt_1_desc = {
+ .bLength = USB_DT_INTERFACE_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bAlternateSetting = 1,
+ .bNumEndpoints = 1,
+ .bInterfaceClass = USB_CLASS_AUDIO,
+ .bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING,
+};
+
+static struct usb_interface_descriptor as_in_interface_alt_0_desc = {
.bLength = USB_DT_INTERFACE_SIZE,
.bDescriptorType = USB_DT_INTERFACE,
.bAlternateSetting = 0,
@@ -137,7 +164,7 @@
.bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING,
};
-static struct usb_interface_descriptor as_interface_alt_1_desc = {
+static struct usb_interface_descriptor as_in_interface_alt_1_desc = {
.bLength = USB_DT_INTERFACE_SIZE,
.bDescriptorType = USB_DT_INTERFACE,
.bAlternateSetting = 1,
@@ -147,18 +174,27 @@
};
/* B.4.2 Class-Specific AS Interface Descriptor */
-static struct uac1_as_header_descriptor as_header_desc = {
+static struct uac1_as_header_descriptor as_out_header_desc = {
+ .bLength = UAC_DT_AS_HEADER_SIZE,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubtype = UAC_AS_GENERAL,
+ .bTerminalLink = USB_OUT_IT_ID,
+ .bDelay = 1,
+ .wFormatTag = cpu_to_le16(UAC_FORMAT_TYPE_I_PCM),
+};
+
+static struct uac1_as_header_descriptor as_in_header_desc = {
.bLength = UAC_DT_AS_HEADER_SIZE,
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubtype = UAC_AS_GENERAL,
- .bTerminalLink = INPUT_TERMINAL_ID,
+ .bTerminalLink = USB_IN_OT_ID,
.bDelay = 1,
- .wFormatTag = UAC_FORMAT_TYPE_I_PCM,
+ .wFormatTag = cpu_to_le16(UAC_FORMAT_TYPE_I_PCM),
};
DECLARE_UAC_FORMAT_TYPE_I_DISCRETE_DESC(1);
-static struct uac_format_type_i_discrete_descriptor_1 as_type_i_desc = {
+static struct uac_format_type_i_discrete_descriptor_1 as_out_type_i_desc = {
.bLength = UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(1),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubtype = UAC_FORMAT_TYPE,
@@ -184,48 +220,138 @@
.bLength = UAC_ISO_ENDPOINT_DESC_SIZE,
.bDescriptorType = USB_DT_CS_ENDPOINT,
.bDescriptorSubtype = UAC_EP_GENERAL,
- .bmAttributes = 1,
+ .bmAttributes = 1,
.bLockDelayUnits = 1,
- .wLockDelay = __constant_cpu_to_le16(1),
+ .wLockDelay = cpu_to_le16(1),
+};
+
+static struct uac_format_type_i_discrete_descriptor_1 as_in_type_i_desc = {
+ .bLength = UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(1),
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubtype = UAC_FORMAT_TYPE,
+ .bFormatType = UAC_FORMAT_TYPE_I,
+ .bSubframeSize = 2,
+ .bBitResolution = 16,
+ .bSamFreqType = 1,
+};
+
+/* Standard ISO OUT Endpoint Descriptor */
+static struct usb_endpoint_descriptor as_in_ep_desc = {
+ .bLength = USB_DT_ENDPOINT_AUDIO_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_SYNC_ASYNC
+ | USB_ENDPOINT_XFER_ISOC,
+ .wMaxPacketSize = cpu_to_le16(UAC1_OUT_EP_MAX_PACKET_SIZE),
+ .bInterval = 4,
+};
+
+/* Class-specific AS ISO OUT Endpoint Descriptor */
+static struct uac_iso_endpoint_descriptor as_iso_in_desc = {
+ .bLength = UAC_ISO_ENDPOINT_DESC_SIZE,
+ .bDescriptorType = USB_DT_CS_ENDPOINT,
+ .bDescriptorSubtype = UAC_EP_GENERAL,
+ .bmAttributes = 1,
+ .bLockDelayUnits = 0,
+ .wLockDelay = 0,
+};
+
+static struct usb_ss_ep_comp_descriptor as_ss_ep_comp = {
+ .bLength = sizeof(as_ss_ep_comp),
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+ .bMaxBurst = 0,
+ .bmAttributes = 0,
+ .wBytesPerInterval = cpu_to_le16(UAC1_OUT_EP_MAX_PACKET_SIZE),
};
static struct usb_descriptor_header *f_audio_desc[] = {
+ (struct usb_descriptor_header *)&uac_iad,
+ (struct usb_descriptor_header *)&ac_interface_desc,
+ (struct usb_descriptor_header *)&ac_header_desc,
+
+ (struct usb_descriptor_header *)&usb_out_it_desc,
+ (struct usb_descriptor_header *)&io_out_ot_desc,
+ (struct usb_descriptor_header *)&io_in_it_desc,
+ (struct usb_descriptor_header *)&usb_in_ot_desc,
+
+ (struct usb_descriptor_header *)&as_out_interface_alt_0_desc,
+ (struct usb_descriptor_header *)&as_out_interface_alt_1_desc,
+ (struct usb_descriptor_header *)&as_out_header_desc,
+
+ (struct usb_descriptor_header *)&as_out_type_i_desc,
+
+ (struct usb_descriptor_header *)&as_out_ep_desc,
+ (struct usb_descriptor_header *)&as_iso_out_desc,
+
+ (struct usb_descriptor_header *)&as_in_interface_alt_0_desc,
+ (struct usb_descriptor_header *)&as_in_interface_alt_1_desc,
+ (struct usb_descriptor_header *)&as_in_header_desc,
+
+ (struct usb_descriptor_header *)&as_in_type_i_desc,
+
+ (struct usb_descriptor_header *)&as_in_ep_desc,
+ (struct usb_descriptor_header *)&as_iso_in_desc,
+ NULL,
+};
+
+static struct usb_descriptor_header *f_audio_ss_desc[] = {
+ (struct usb_descriptor_header *)&uac_iad,
(struct usb_descriptor_header *)&ac_interface_desc,
(struct usb_descriptor_header *)&ac_header_desc,
- (struct usb_descriptor_header *)&input_terminal_desc,
- (struct usb_descriptor_header *)&output_terminal_desc,
- (struct usb_descriptor_header *)&feature_unit_desc,
-
- (struct usb_descriptor_header *)&as_interface_alt_0_desc,
- (struct usb_descriptor_header *)&as_interface_alt_1_desc,
- (struct usb_descriptor_header *)&as_header_desc,
+ (struct usb_descriptor_header *)&usb_out_it_desc,
+ (struct usb_descriptor_header *)&io_out_ot_desc,
+ (struct usb_descriptor_header *)&io_in_it_desc,
+ (struct usb_descriptor_header *)&usb_in_ot_desc,
+
+ (struct usb_descriptor_header *)&as_out_interface_alt_0_desc,
+ (struct usb_descriptor_header *)&as_out_interface_alt_1_desc,
+ (struct usb_descriptor_header *)&as_out_header_desc,
- (struct usb_descriptor_header *)&as_type_i_desc,
+ (struct usb_descriptor_header *)&as_out_type_i_desc,
(struct usb_descriptor_header *)&as_out_ep_desc,
+ (struct usb_descriptor_header *)&as_ss_ep_comp,
(struct usb_descriptor_header *)&as_iso_out_desc,
+
+ (struct usb_descriptor_header *)&as_in_interface_alt_0_desc,
+ (struct usb_descriptor_header *)&as_in_interface_alt_1_desc,
+ (struct usb_descriptor_header *)&as_in_header_desc,
+
+ (struct usb_descriptor_header *)&as_in_type_i_desc,
+
+ (struct usb_descriptor_header *)&as_in_ep_desc,
+ (struct usb_descriptor_header *)&as_ss_ep_comp,
+ (struct usb_descriptor_header *)&as_iso_in_desc,
NULL,
};
enum {
STR_AC_IF,
- STR_INPUT_TERMINAL,
- STR_INPUT_TERMINAL_CH_NAMES,
- STR_FEAT_DESC_0,
- STR_OUTPUT_TERMINAL,
- STR_AS_IF_ALT0,
- STR_AS_IF_ALT1,
+ STR_USB_OUT_IT,
+ STR_USB_OUT_IT_CH_NAMES,
+ STR_IO_OUT_OT,
+ STR_IO_IN_IT,
+ STR_IO_IN_IT_CH_NAMES,
+ STR_USB_IN_OT,
+ STR_AS_OUT_IF_ALT0,
+ STR_AS_OUT_IF_ALT1,
+ STR_AS_IN_IF_ALT0,
+ STR_AS_IN_IF_ALT1,
};
static struct usb_string strings_uac1[] = {
[STR_AC_IF].s = "AC Interface",
- [STR_INPUT_TERMINAL].s = "Input terminal",
- [STR_INPUT_TERMINAL_CH_NAMES].s = "Channels",
- [STR_FEAT_DESC_0].s = "Volume control & mute",
- [STR_OUTPUT_TERMINAL].s = "Output terminal",
- [STR_AS_IF_ALT0].s = "AS Interface",
- [STR_AS_IF_ALT1].s = "AS Interface",
+ [STR_USB_OUT_IT].s = "Playback Input terminal",
+ [STR_USB_OUT_IT_CH_NAMES].s = "Playback Channels",
+ [STR_IO_OUT_OT].s = "Playback Output terminal",
+ [STR_IO_IN_IT].s = "Capture Input terminal",
+ [STR_IO_IN_IT_CH_NAMES].s = "Capture Channels",
+ [STR_USB_IN_OT].s = "Capture Output terminal",
+ [STR_AS_OUT_IF_ALT0].s = "Playback Inactive",
+ [STR_AS_OUT_IF_ALT1].s = "Playback Active",
+ [STR_AS_IN_IF_ALT0].s = "Capture Inactive",
+ [STR_AS_IN_IF_ALT1].s = "Capture Active",
{ },
};
@@ -243,216 +369,6 @@
* This function is an ALSA sound card following USB Audio Class Spec 1.0.
*/
-/*-------------------------------------------------------------------------*/
-struct f_audio_buf {
- u8 *buf;
- int actual;
- struct list_head list;
-};
-
-static struct f_audio_buf *f_audio_buffer_alloc(int buf_size)
-{
- struct f_audio_buf *copy_buf;
-
- copy_buf = kzalloc(sizeof *copy_buf, GFP_ATOMIC);
- if (!copy_buf)
- return ERR_PTR(-ENOMEM);
-
- copy_buf->buf = kzalloc(buf_size, GFP_ATOMIC);
- if (!copy_buf->buf) {
- kfree(copy_buf);
- return ERR_PTR(-ENOMEM);
- }
-
- return copy_buf;
-}
-
-static void f_audio_buffer_free(struct f_audio_buf *audio_buf)
-{
- kfree(audio_buf->buf);
- kfree(audio_buf);
-}
-/*-------------------------------------------------------------------------*/
-
-struct f_audio {
- struct gaudio card;
-
- /* endpoints handle full and/or high speeds */
- struct usb_ep *out_ep;
-
- spinlock_t lock;
- struct f_audio_buf *copy_buf;
- struct work_struct playback_work;
- struct list_head play_queue;
-
- /* Control Set command */
- struct list_head cs;
- u8 set_cmd;
- struct usb_audio_control *set_con;
-};
-
-static inline struct f_audio *func_to_audio(struct usb_function *f)
-{
- return container_of(f, struct f_audio, card.func);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void f_audio_playback_work(struct work_struct *data)
-{
- struct f_audio *audio = container_of(data, struct f_audio,
- playback_work);
- struct f_audio_buf *play_buf;
-
- spin_lock_irq(&audio->lock);
- if (list_empty(&audio->play_queue)) {
- spin_unlock_irq(&audio->lock);
- return;
- }
- play_buf = list_first_entry(&audio->play_queue,
- struct f_audio_buf, list);
- list_del(&play_buf->list);
- spin_unlock_irq(&audio->lock);
-
- u_audio_playback(&audio->card, play_buf->buf, play_buf->actual);
- f_audio_buffer_free(play_buf);
-}
-
-static int f_audio_out_ep_complete(struct usb_ep *ep, struct usb_request *req)
-{
- struct f_audio *audio = req->context;
- struct usb_composite_dev *cdev = audio->card.func.config->cdev;
- struct f_audio_buf *copy_buf = audio->copy_buf;
- struct f_uac1_opts *opts;
- int audio_buf_size;
- int err;
-
- opts = container_of(audio->card.func.fi, struct f_uac1_opts,
- func_inst);
- audio_buf_size = opts->audio_buf_size;
-
- if (!copy_buf)
- return -EINVAL;
-
- /* Copy buffer is full, add it to the play_queue */
- if (audio_buf_size - copy_buf->actual < req->actual) {
- list_add_tail(&copy_buf->list, &audio->play_queue);
- schedule_work(&audio->playback_work);
- copy_buf = f_audio_buffer_alloc(audio_buf_size);
- if (IS_ERR(copy_buf))
- return -ENOMEM;
- }
-
- memcpy(copy_buf->buf + copy_buf->actual, req->buf, req->actual);
- copy_buf->actual += req->actual;
- audio->copy_buf = copy_buf;
-
- err = usb_ep_queue(ep, req, GFP_ATOMIC);
- if (err)
- ERROR(cdev, "%s queue req: %d\n", ep->name, err);
-
- return 0;
-
-}
-
-static void f_audio_complete(struct usb_ep *ep, struct usb_request *req)
-{
- struct f_audio *audio = req->context;
- int status = req->status;
- u32 data = 0;
- struct usb_ep *out_ep = audio->out_ep;
-
- switch (status) {
-
- case 0: /* normal completion? */
- if (ep == out_ep)
- f_audio_out_ep_complete(ep, req);
- else if (audio->set_con) {
- memcpy(&data, req->buf, req->length);
- audio->set_con->set(audio->set_con, audio->set_cmd,
- le16_to_cpu(data));
- audio->set_con = NULL;
- }
- break;
- default:
- break;
- }
-}
-
-static int audio_set_intf_req(struct usb_function *f,
- const struct usb_ctrlrequest *ctrl)
-{
- struct f_audio *audio = func_to_audio(f);
- struct usb_composite_dev *cdev = f->config->cdev;
- struct usb_request *req = cdev->req;
- u8 id = ((le16_to_cpu(ctrl->wIndex) >> 8) & 0xFF);
- u16 len = le16_to_cpu(ctrl->wLength);
- u16 w_value = le16_to_cpu(ctrl->wValue);
- u8 con_sel = (w_value >> 8) & 0xFF;
- u8 cmd = (ctrl->bRequest & 0x0F);
- struct usb_audio_control_selector *cs;
- struct usb_audio_control *con;
-
- DBG(cdev, "bRequest 0x%x, w_value 0x%04x, len %d, entity %d\n",
- ctrl->bRequest, w_value, len, id);
-
- list_for_each_entry(cs, &audio->cs, list) {
- if (cs->id == id) {
- list_for_each_entry(con, &cs->control, list) {
- if (con->type == con_sel) {
- audio->set_con = con;
- break;
- }
- }
- break;
- }
- }
-
- audio->set_cmd = cmd;
- req->context = audio;
- req->complete = f_audio_complete;
-
- return len;
-}
-
-static int audio_get_intf_req(struct usb_function *f,
- const struct usb_ctrlrequest *ctrl)
-{
- struct f_audio *audio = func_to_audio(f);
- struct usb_composite_dev *cdev = f->config->cdev;
- struct usb_request *req = cdev->req;
- int value = -EOPNOTSUPP;
- u8 id = ((le16_to_cpu(ctrl->wIndex) >> 8) & 0xFF);
- u16 len = le16_to_cpu(ctrl->wLength);
- u16 w_value = le16_to_cpu(ctrl->wValue);
- u8 con_sel = (w_value >> 8) & 0xFF;
- u8 cmd = (ctrl->bRequest & 0x0F);
- struct usb_audio_control_selector *cs;
- struct usb_audio_control *con;
-
- DBG(cdev, "bRequest 0x%x, w_value 0x%04x, len %d, entity %d\n",
- ctrl->bRequest, w_value, len, id);
-
- list_for_each_entry(cs, &audio->cs, list) {
- if (cs->id == id) {
- list_for_each_entry(con, &cs->control, list) {
- if (con->type == con_sel && con->get) {
- value = con->get(con, cmd);
- break;
- }
- }
- break;
- }
- }
-
- req->context = audio;
- req->complete = f_audio_complete;
- len = min_t(size_t, sizeof(value), len);
- memcpy(req->buf, &value, len);
-
- return len;
-}
-
static int audio_set_endpoint_req(struct usb_function *f,
const struct usb_ctrlrequest *ctrl)
{
@@ -531,14 +447,6 @@
* activation uses set_alt().
*/
switch (ctrl->bRequestType) {
- case USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE:
- value = audio_set_intf_req(f, ctrl);
- break;
-
- case USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE:
- value = audio_get_intf_req(f, ctrl);
- break;
-
case USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_ENDPOINT:
value = audio_set_endpoint_req(f, ctrl);
break;
@@ -571,143 +479,162 @@
static int f_audio_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
{
- struct f_audio *audio = func_to_audio(f);
struct usb_composite_dev *cdev = f->config->cdev;
- struct usb_ep *out_ep = audio->out_ep;
- struct usb_request *req;
- struct f_uac1_opts *opts;
- int req_buf_size, req_count, audio_buf_size;
- int i = 0, err = 0;
-
- DBG(cdev, "intf %d, alt %d\n", intf, alt);
+ struct usb_gadget *gadget = cdev->gadget;
+ struct device *dev = &gadget->dev;
+ struct f_uac1 *uac1 = func_to_uac1(f);
+ int ret = 0;
+
+ /* No i/f has more than 2 alt settings */
+ if (alt > 1) {
+ dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
+ return -EINVAL;
+ }
- opts = container_of(f->fi, struct f_uac1_opts, func_inst);
- req_buf_size = opts->req_buf_size;
- req_count = opts->req_count;
- audio_buf_size = opts->audio_buf_size;
-
- if (intf == 1) {
- if (alt == 1) {
- err = config_ep_by_speed(cdev->gadget, f, out_ep);
- if (err)
- return err;
-
- usb_ep_enable(out_ep);
- audio->copy_buf = f_audio_buffer_alloc(audio_buf_size);
- if (IS_ERR(audio->copy_buf))
- return -ENOMEM;
-
- /*
- * allocate a bunch of read buffers
- * and queue them all at once.
- */
- for (i = 0; i < req_count && err == 0; i++) {
- req = usb_ep_alloc_request(out_ep, GFP_ATOMIC);
- if (req) {
- req->buf = kzalloc(req_buf_size,
- GFP_ATOMIC);
- if (req->buf) {
- req->length = req_buf_size;
- req->context = audio;
- req->complete =
- f_audio_complete;
- err = usb_ep_queue(out_ep,
- req, GFP_ATOMIC);
- if (err)
- ERROR(cdev,
- "%s queue req: %d\n",
- out_ep->name, err);
- } else
- err = -ENOMEM;
- } else
- err = -ENOMEM;
- }
-
- } else {
- struct f_audio_buf *copy_buf = audio->copy_buf;
- if (copy_buf) {
- list_add_tail(&copy_buf->list,
- &audio->play_queue);
- schedule_work(&audio->playback_work);
- }
+ if (intf == uac1->ac_intf) {
+ /* Control I/f has only 1 AltSetting - 0 */
+ if (alt) {
+ dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
+ return -EINVAL;
}
+ return 0;
+ }
+
+ if (intf == uac1->as_out_intf) {
+ uac1->as_out_alt = alt;
+
+ if (alt)
+ ret = u_audio_start_capture(&uac1->g_audio);
+ else
+ u_audio_stop_capture(&uac1->g_audio);
+ } else if (intf == uac1->as_in_intf) {
+ uac1->as_in_alt = alt;
+
+ if (alt)
+ ret = u_audio_start_playback(&uac1->g_audio);
+ else
+ u_audio_stop_playback(&uac1->g_audio);
+ } else {
+ dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
+ return -EINVAL;
}
- return err;
+ return ret;
}
-static void f_audio_disable(struct usb_function *f)
+static int f_audio_get_alt(struct usb_function *f, unsigned intf)
{
- return;
+ struct usb_composite_dev *cdev = f->config->cdev;
+ struct usb_gadget *gadget = cdev->gadget;
+ struct device *dev = &gadget->dev;
+ struct f_uac1 *uac1 = func_to_uac1(f);
+
+ if (intf == uac1->ac_intf)
+ return uac1->ac_alt;
+ else if (intf == uac1->as_out_intf)
+ return uac1->as_out_alt;
+ else if (intf == uac1->as_in_intf)
+ return uac1->as_in_alt;
+ else
+ dev_err(dev, "%s:%d Invalid Interface %d!\n",
+ __func__, __LINE__, intf);
+
+ return -EINVAL;
}
-/*-------------------------------------------------------------------------*/
-static void f_audio_build_desc(struct f_audio *audio)
+static void f_audio_disable(struct usb_function *f)
{
- struct gaudio *card = &audio->card;
- u8 *sam_freq;
- int rate;
-
- /* Set channel numbers */
- input_terminal_desc.bNrChannels = u_audio_get_playback_channels(card);
- as_type_i_desc.bNrChannels = u_audio_get_playback_channels(card);
+ struct f_uac1 *uac1 = func_to_uac1(f);
- /* Set sample rates */
- rate = u_audio_get_playback_rate(card);
- sam_freq = as_type_i_desc.tSamFreq[0];
- memcpy(sam_freq, &rate, 3);
+ uac1->as_out_alt = 0;
+ uac1->as_in_alt = 0;
- /* Todo: Set Sample bits and other parameters */
-
- return;
+ u_audio_stop_capture(&uac1->g_audio);
}
+/*-------------------------------------------------------------------------*/
+
/* audio function driver setup/binding */
-static int
-f_audio_bind(struct usb_configuration *c, struct usb_function *f)
+static int f_audio_bind(struct usb_configuration *c, struct usb_function *f)
{
- struct usb_composite_dev *cdev = c->cdev;
- struct f_audio *audio = func_to_audio(f);
- struct usb_string *us;
- int status;
- struct usb_ep *ep = NULL;
- struct f_uac1_opts *audio_opts;
+ struct usb_composite_dev *cdev = c->cdev;
+ struct usb_gadget *gadget = cdev->gadget;
+ struct f_uac1 *uac1 = func_to_uac1(f);
+ struct g_audio *audio = func_to_g_audio(f);
+ struct f_uac1_opts *audio_opts;
+ struct usb_ep *ep = NULL;
+ struct usb_string *us;
+ u8 *sam_freq;
+ int rate;
+ int status;
audio_opts = container_of(f->fi, struct f_uac1_opts, func_inst);
- audio->card.gadget = c->cdev->gadget;
- /* set up ASLA audio devices */
- if (!audio_opts->bound) {
- status = gaudio_setup(&audio->card);
- if (status < 0)
- return status;
- audio_opts->bound = true;
- }
+
us = usb_gstrings_attach(cdev, uac1_strings, ARRAY_SIZE(strings_uac1));
if (IS_ERR(us))
return PTR_ERR(us);
+ uac_iad.iFunction = us[STR_AC_IF].id;
ac_interface_desc.iInterface = us[STR_AC_IF].id;
- input_terminal_desc.iTerminal = us[STR_INPUT_TERMINAL].id;
- input_terminal_desc.iChannelNames = us[STR_INPUT_TERMINAL_CH_NAMES].id;
- feature_unit_desc.iFeature = us[STR_FEAT_DESC_0].id;
- output_terminal_desc.iTerminal = us[STR_OUTPUT_TERMINAL].id;
- as_interface_alt_0_desc.iInterface = us[STR_AS_IF_ALT0].id;
- as_interface_alt_1_desc.iInterface = us[STR_AS_IF_ALT1].id;
+ usb_out_it_desc.iTerminal = us[STR_USB_OUT_IT].id;
+ usb_out_it_desc.iChannelNames = us[STR_USB_OUT_IT_CH_NAMES].id;
+ io_out_ot_desc.iTerminal = us[STR_IO_OUT_OT].id;
+ as_out_interface_alt_0_desc.iInterface = us[STR_AS_OUT_IF_ALT0].id;
+ as_out_interface_alt_1_desc.iInterface = us[STR_AS_OUT_IF_ALT1].id;
+ io_in_it_desc.iTerminal = us[STR_IO_IN_IT].id;
+ io_in_it_desc.iChannelNames = us[STR_IO_IN_IT_CH_NAMES].id;
+ usb_in_ot_desc.iTerminal = us[STR_USB_IN_OT].id;
+ as_in_interface_alt_0_desc.iInterface = us[STR_AS_IN_IF_ALT0].id;
+ as_in_interface_alt_1_desc.iInterface = us[STR_AS_IN_IF_ALT1].id;
+ /* Set channel numbers */
+ usb_out_it_desc.bNrChannels = num_channels(audio_opts->c_chmask);
+ usb_out_it_desc.wChannelConfig = cpu_to_le16(audio_opts->c_chmask);
+ as_out_type_i_desc.bNrChannels = num_channels(audio_opts->c_chmask);
+ as_out_type_i_desc.bSubframeSize = audio_opts->c_ssize;
+ as_out_type_i_desc.bBitResolution = audio_opts->c_ssize * 8;
+ io_in_it_desc.bNrChannels = num_channels(audio_opts->p_chmask);
+ io_in_it_desc.wChannelConfig = cpu_to_le16(audio_opts->p_chmask);
+ as_in_type_i_desc.bNrChannels = num_channels(audio_opts->p_chmask);
+ as_in_type_i_desc.bSubframeSize = audio_opts->p_ssize;
+ as_in_type_i_desc.bBitResolution = audio_opts->p_ssize * 8;
- f_audio_build_desc(audio);
+ /* Set sample rates */
+ rate = audio_opts->c_srate;
+ sam_freq = as_out_type_i_desc.tSamFreq[0];
+ memcpy(sam_freq, &rate, 3);
+ rate = audio_opts->p_srate;
+ sam_freq = as_in_type_i_desc.tSamFreq[0];
+ memcpy(sam_freq, &rate, 3);
/* allocate instance-specific interface IDs, and patch descriptors */
status = usb_interface_id(c, f);
if (status < 0)
goto fail;
+ uac_iad.bFirstInterface = status;
ac_interface_desc.bInterfaceNumber = status;
+ uac1->ac_intf = status;
+ uac1->ac_alt = 0;
+
+ status = usb_interface_id(c, f);
+ if (status < 0)
+ goto fail;
+ as_out_interface_alt_0_desc.bInterfaceNumber = status;
+ as_out_interface_alt_1_desc.bInterfaceNumber = status;
+ ac_header_desc.baInterfaceNr[0] = status;
+ uac1->as_out_intf = status;
+ uac1->as_out_alt = 0;
status = usb_interface_id(c, f);
if (status < 0)
goto fail;
- as_interface_alt_0_desc.bInterfaceNumber = status;
- as_interface_alt_1_desc.bInterfaceNumber = status;
+ as_in_interface_alt_0_desc.bInterfaceNumber = status;
+ as_in_interface_alt_1_desc.bInterfaceNumber = status;
+ ac_header_desc.baInterfaceNr[1] = status;
+ uac1->as_in_intf = status;
+ uac1->as_in_alt = 0;
+
+ audio->gadget = gadget;
status = -ENODEV;
@@ -718,51 +645,41 @@
audio->out_ep = ep;
audio->out_ep->desc = &as_out_ep_desc;
- status = -ENOMEM;
+ ep = usb_ep_autoconfig(cdev->gadget, &as_in_ep_desc);
+ if (!ep)
+ goto fail;
+ audio->in_ep = ep;
+ audio->in_ep->desc = &as_in_ep_desc;
/* copy descriptors, and track endpoint copies */
- status = usb_assign_descriptors(f, f_audio_desc, f_audio_desc, NULL,
- NULL);
+ status = usb_assign_descriptors(f, f_audio_desc, f_audio_desc,
+ f_audio_ss_desc, NULL);
if (status)
goto fail;
- return 0;
-
-fail:
- gaudio_cleanup(&audio->card);
- return status;
-}
-/*-------------------------------------------------------------------------*/
+ audio->out_ep_maxpsize = le16_to_cpu(as_out_ep_desc.wMaxPacketSize);
+ audio->in_ep_maxpsize = le16_to_cpu(as_in_ep_desc.wMaxPacketSize);
+ audio->params.c_chmask = audio_opts->c_chmask;
+ audio->params.c_srate = audio_opts->c_srate;
+ audio->params.c_ssize = audio_opts->c_ssize;
+ audio->params.p_chmask = audio_opts->p_chmask;
+ audio->params.p_srate = audio_opts->p_srate;
+ audio->params.p_ssize = audio_opts->p_ssize;
+ audio->params.req_number = audio_opts->req_number;
-static int generic_set_cmd(struct usb_audio_control *con, u8 cmd, int value)
-{
- con->data[cmd] = value;
+ status = g_audio_setup(audio, "UAC1_PCM", "UAC1_Gadget");
+ if (status)
+ goto err_card_register;
return 0;
-}
-static int generic_get_cmd(struct usb_audio_control *con, u8 cmd)
-{
- return con->data[cmd];
+err_card_register:
+ usb_free_all_descriptors(f);
+fail:
+ return status;
}
-/* Todo: add more control selecotor dynamically */
-static int control_selector_init(struct f_audio *audio)
-{
- INIT_LIST_HEAD(&audio->cs);
- list_add(&feature_unit.list, &audio->cs);
-
- INIT_LIST_HEAD(&feature_unit.control);
- list_add(&mute_control.list, &feature_unit.control);
- list_add(&volume_control.list, &feature_unit.control);
-
- volume_control.data[UAC__CUR] = 0xffc0;
- volume_control.data[UAC__MIN] = 0xe3a0;
- volume_control.data[UAC__MAX] = 0xfff0;
- volume_control.data[UAC__RES] = 0x0030;
-
- return 0;
-}
+/*-------------------------------------------------------------------------*/
static inline struct f_uac1_opts *to_f_uac1_opts(struct config_item *item)
{
@@ -781,9 +698,10 @@
.release = f_uac1_attr_release,
};
-#define UAC1_INT_ATTRIBUTE(name) \
-static ssize_t f_uac1_opts_##name##_show(struct config_item *item, \
- char *page) \
+#define UAC1_ATTRIBUTE(name) \
+static ssize_t f_uac1_opts_##name##_show( \
+ struct config_item *item, \
+ char *page) \
{ \
struct f_uac1_opts *opts = to_f_uac1_opts(item); \
int result; \
@@ -795,7 +713,8 @@
return result; \
} \
\
-static ssize_t f_uac1_opts_##name##_store(struct config_item *item, \
+static ssize_t f_uac1_opts_##name##_store( \
+ struct config_item *item, \
const char *page, size_t len) \
{ \
struct f_uac1_opts *opts = to_f_uac1_opts(item); \
@@ -822,64 +741,22 @@
\
CONFIGFS_ATTR(f_uac1_opts_, name)
-UAC1_INT_ATTRIBUTE(req_buf_size);
-UAC1_INT_ATTRIBUTE(req_count);
-UAC1_INT_ATTRIBUTE(audio_buf_size);
-
-#define UAC1_STR_ATTRIBUTE(name) \
-static ssize_t f_uac1_opts_##name##_show(struct config_item *item, \
- char *page) \
-{ \
- struct f_uac1_opts *opts = to_f_uac1_opts(item); \
- int result; \
- \
- mutex_lock(&opts->lock); \
- result = sprintf(page, "%s\n", opts->name); \
- mutex_unlock(&opts->lock); \
- \
- return result; \
-} \
- \
-static ssize_t f_uac1_opts_##name##_store(struct config_item *item, \
- const char *page, size_t len) \
-{ \
- struct f_uac1_opts *opts = to_f_uac1_opts(item); \
- int ret = -EBUSY; \
- char *tmp; \
- \
- mutex_lock(&opts->lock); \
- if (opts->refcnt) \
- goto end; \
- \
- tmp = kstrndup(page, len, GFP_KERNEL); \
- if (tmp) { \
- ret = -ENOMEM; \
- goto end; \
- } \
- if (opts->name##_alloc) \
- kfree(opts->name); \
- opts->name##_alloc = true; \
- opts->name = tmp; \
- ret = len; \
- \
-end: \
- mutex_unlock(&opts->lock); \
- return ret; \
-} \
- \
-CONFIGFS_ATTR(f_uac1_opts_, name)
-
-UAC1_STR_ATTRIBUTE(fn_play);
-UAC1_STR_ATTRIBUTE(fn_cap);
-UAC1_STR_ATTRIBUTE(fn_cntl);
+UAC1_ATTRIBUTE(c_chmask);
+UAC1_ATTRIBUTE(c_srate);
+UAC1_ATTRIBUTE(c_ssize);
+UAC1_ATTRIBUTE(p_chmask);
+UAC1_ATTRIBUTE(p_srate);
+UAC1_ATTRIBUTE(p_ssize);
+UAC1_ATTRIBUTE(req_number);
static struct configfs_attribute *f_uac1_attrs[] = {
- &f_uac1_opts_attr_req_buf_size,
- &f_uac1_opts_attr_req_count,
- &f_uac1_opts_attr_audio_buf_size,
- &f_uac1_opts_attr_fn_play,
- &f_uac1_opts_attr_fn_cap,
- &f_uac1_opts_attr_fn_cntl,
+ &f_uac1_opts_attr_c_chmask,
+ &f_uac1_opts_attr_c_srate,
+ &f_uac1_opts_attr_c_ssize,
+ &f_uac1_opts_attr_p_chmask,
+ &f_uac1_opts_attr_p_srate,
+ &f_uac1_opts_attr_p_ssize,
+ &f_uac1_opts_attr_req_number,
NULL,
};
@@ -894,12 +771,6 @@
struct f_uac1_opts *opts;
opts = container_of(f, struct f_uac1_opts, func_inst);
- if (opts->fn_play_alloc)
- kfree(opts->fn_play);
- if (opts->fn_cap_alloc)
- kfree(opts->fn_cap);
- if (opts->fn_cntl_alloc)
- kfree(opts->fn_cntl);
kfree(opts);
}
@@ -917,21 +788,22 @@
config_group_init_type_name(&opts->func_inst.group, "",
&f_uac1_func_type);
- opts->req_buf_size = UAC1_OUT_EP_MAX_PACKET_SIZE;
- opts->req_count = UAC1_REQ_COUNT;
- opts->audio_buf_size = UAC1_AUDIO_BUF_SIZE;
- opts->fn_play = FILE_PCM_PLAYBACK;
- opts->fn_cap = FILE_PCM_CAPTURE;
- opts->fn_cntl = FILE_CONTROL;
+ opts->c_chmask = UAC1_DEF_CCHMASK;
+ opts->c_srate = UAC1_DEF_CSRATE;
+ opts->c_ssize = UAC1_DEF_CSSIZE;
+ opts->p_chmask = UAC1_DEF_PCHMASK;
+ opts->p_srate = UAC1_DEF_PSRATE;
+ opts->p_ssize = UAC1_DEF_PSSIZE;
+ opts->req_number = UAC1_DEF_REQ_NUM;
return &opts->func_inst;
}
static void f_audio_free(struct usb_function *f)
{
- struct f_audio *audio = func_to_audio(f);
+ struct g_audio *audio;
struct f_uac1_opts *opts;
- gaudio_cleanup(&audio->card);
+ audio = func_to_g_audio(f);
opts = container_of(f->fi, struct f_uac1_opts, func_inst);
kfree(audio);
mutex_lock(&opts->lock);
@@ -941,42 +813,41 @@
static void f_audio_unbind(struct usb_configuration *c, struct usb_function *f)
{
+ struct g_audio *audio = func_to_g_audio(f);
+
+ g_audio_cleanup(audio);
usb_free_all_descriptors(f);
+
+ audio->gadget = NULL;
}
static struct usb_function *f_audio_alloc(struct usb_function_instance *fi)
{
- struct f_audio *audio;
+ struct f_uac1 *uac1;
struct f_uac1_opts *opts;
/* allocate and initialize one new instance */
- audio = kzalloc(sizeof(*audio), GFP_KERNEL);
- if (!audio)
+ uac1 = kzalloc(sizeof(*uac1), GFP_KERNEL);
+ if (!uac1)
return ERR_PTR(-ENOMEM);
- audio->card.func.name = "g_audio";
-
opts = container_of(fi, struct f_uac1_opts, func_inst);
mutex_lock(&opts->lock);
++opts->refcnt;
mutex_unlock(&opts->lock);
- INIT_LIST_HEAD(&audio->play_queue);
- spin_lock_init(&audio->lock);
-
- audio->card.func.bind = f_audio_bind;
- audio->card.func.unbind = f_audio_unbind;
- audio->card.func.set_alt = f_audio_set_alt;
- audio->card.func.setup = f_audio_setup;
- audio->card.func.disable = f_audio_disable;
- audio->card.func.free_func = f_audio_free;
-
- control_selector_init(audio);
- INIT_WORK(&audio->playback_work, f_audio_playback_work);
+ uac1->g_audio.func.name = "uac1_func";
+ uac1->g_audio.func.bind = f_audio_bind;
+ uac1->g_audio.func.unbind = f_audio_unbind;
+ uac1->g_audio.func.set_alt = f_audio_set_alt;
+ uac1->g_audio.func.get_alt = f_audio_get_alt;
+ uac1->g_audio.func.setup = f_audio_setup;
+ uac1->g_audio.func.disable = f_audio_disable;
+ uac1->g_audio.func.free_func = f_audio_free;
- return &audio->card.func;
+ return &uac1->g_audio.func;
}
DECLARE_USB_FUNCTION_INIT(uac1, f_audio_alloc_inst, f_audio_alloc);
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Bryan Wu");
+MODULE_AUTHOR("Ruslan Bilovol");
diff -urN linux-4.9.37/drivers/usb/gadget/function/f_uac1_legacy.c linux-4.9.y/drivers/usb/gadget/function/f_uac1_legacy.c
--- linux-4.9.37/drivers/usb/gadget/function/f_uac1_legacy.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/usb/gadget/function/f_uac1_legacy.c 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,1020 @@
+/*
+ * f_audio.c -- USB Audio class function driver
+ *
+ * Copyright (C) 2008 Bryan Wu <cooloney@kernel.org>
+ * Copyright (C) 2008 Analog Devices, Inc
+ *
+ * Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Licensed under the GPL-2 or later.
+ */
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/atomic.h>
+
+#include "u_uac1_legacy.h"
+
+static int generic_set_cmd(struct usb_audio_control *con, u8 cmd, int value);
+static int generic_get_cmd(struct usb_audio_control *con, u8 cmd);
+
+/*
+ * DESCRIPTORS ... most are static, but strings and full
+ * configuration descriptors are built on demand.
+ */
+
+/*
+ * We have two interfaces- AudioControl and AudioStreaming
+ * TODO: only supcard playback currently
+ */
+#define F_AUDIO_AC_INTERFACE 0
+#define F_AUDIO_AS_INTERFACE 1
+#define F_AUDIO_NUM_INTERFACES 1
+
+/* B.3.1 Standard AC Interface Descriptor */
+static struct usb_interface_descriptor ac_interface_desc = {
+ .bLength = USB_DT_INTERFACE_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bNumEndpoints = 0,
+ .bInterfaceClass = USB_CLASS_AUDIO,
+ .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL,
+};
+
+/*
+ * The number of AudioStreaming and MIDIStreaming interfaces
+ * in the Audio Interface Collection
+ */
+DECLARE_UAC_AC_HEADER_DESCRIPTOR(1);
+
+#define UAC_DT_AC_HEADER_LENGTH UAC_DT_AC_HEADER_SIZE(F_AUDIO_NUM_INTERFACES)
+/* 1 input terminal, 1 output terminal and 1 feature unit */
+#define UAC_DT_TOTAL_LENGTH (UAC_DT_AC_HEADER_LENGTH + UAC_DT_INPUT_TERMINAL_SIZE \
+ + UAC_DT_OUTPUT_TERMINAL_SIZE + UAC_DT_FEATURE_UNIT_SIZE(0))
+/* B.3.2 Class-Specific AC Interface Descriptor */
+static struct uac1_ac_header_descriptor_1 ac_header_desc = {
+ .bLength = UAC_DT_AC_HEADER_LENGTH,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubtype = UAC_HEADER,
+ .bcdADC = __constant_cpu_to_le16(0x0100),
+ .wTotalLength = __constant_cpu_to_le16(UAC_DT_TOTAL_LENGTH),
+ .bInCollection = F_AUDIO_NUM_INTERFACES,
+ .baInterfaceNr = {
+ /* Interface number of the first AudioStream interface */
+ [0] = 1,
+ }
+};
+
+#define INPUT_TERMINAL_ID 1
+static struct uac_input_terminal_descriptor input_terminal_desc = {
+ .bLength = UAC_DT_INPUT_TERMINAL_SIZE,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubtype = UAC_INPUT_TERMINAL,
+ .bTerminalID = INPUT_TERMINAL_ID,
+ .wTerminalType = UAC_TERMINAL_STREAMING,
+ .bAssocTerminal = 0,
+ .wChannelConfig = 0x3,
+};
+
+DECLARE_UAC_FEATURE_UNIT_DESCRIPTOR(0);
+
+#define FEATURE_UNIT_ID 2
+static struct uac_feature_unit_descriptor_0 feature_unit_desc = {
+ .bLength = UAC_DT_FEATURE_UNIT_SIZE(0),
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubtype = UAC_FEATURE_UNIT,
+ .bUnitID = FEATURE_UNIT_ID,
+ .bSourceID = INPUT_TERMINAL_ID,
+ .bControlSize = 2,
+ .bmaControls[0] = (UAC_FU_MUTE | UAC_FU_VOLUME),
+};
+
+static struct usb_audio_control mute_control = {
+ .list = LIST_HEAD_INIT(mute_control.list),
+ .name = "Mute Control",
+ .type = UAC_FU_MUTE,
+ /* Todo: add real Mute control code */
+ .set = generic_set_cmd,
+ .get = generic_get_cmd,
+};
+
+static struct usb_audio_control volume_control = {
+ .list = LIST_HEAD_INIT(volume_control.list),
+ .name = "Volume Control",
+ .type = UAC_FU_VOLUME,
+ /* Todo: add real Volume control code */
+ .set = generic_set_cmd,
+ .get = generic_get_cmd,
+};
+
+static struct usb_audio_control_selector feature_unit = {
+ .list = LIST_HEAD_INIT(feature_unit.list),
+ .id = FEATURE_UNIT_ID,
+ .name = "Mute & Volume Control",
+ .type = UAC_FEATURE_UNIT,
+ .desc = (struct usb_descriptor_header *)&feature_unit_desc,
+};
+
+#define OUTPUT_TERMINAL_ID 3
+static struct uac1_output_terminal_descriptor output_terminal_desc = {
+ .bLength = UAC_DT_OUTPUT_TERMINAL_SIZE,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubtype = UAC_OUTPUT_TERMINAL,
+ .bTerminalID = OUTPUT_TERMINAL_ID,
+ .wTerminalType = UAC_OUTPUT_TERMINAL_SPEAKER,
+ .bAssocTerminal = FEATURE_UNIT_ID,
+ .bSourceID = FEATURE_UNIT_ID,
+};
+
+/* B.4.1 Standard AS Interface Descriptor */
+static struct usb_interface_descriptor as_interface_alt_0_desc = {
+ .bLength = USB_DT_INTERFACE_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 0,
+ .bInterfaceClass = USB_CLASS_AUDIO,
+ .bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING,
+};
+
+static struct usb_interface_descriptor as_interface_alt_1_desc = {
+ .bLength = USB_DT_INTERFACE_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bAlternateSetting = 1,
+ .bNumEndpoints = 1,
+ .bInterfaceClass = USB_CLASS_AUDIO,
+ .bInterfaceSubClass = USB_SUBCLASS_AUDIOSTREAMING,
+};
+
+/* B.4.2 Class-Specific AS Interface Descriptor */
+static struct uac1_as_header_descriptor as_header_desc = {
+ .bLength = UAC_DT_AS_HEADER_SIZE,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubtype = UAC_AS_GENERAL,
+ .bTerminalLink = INPUT_TERMINAL_ID,
+ .bDelay = 1,
+ .wFormatTag = UAC_FORMAT_TYPE_I_PCM,
+};
+
+DECLARE_UAC_FORMAT_TYPE_I_DISCRETE_DESC(1);
+
+static struct uac_format_type_i_discrete_descriptor_1 as_type_i_desc = {
+ .bLength = UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(1),
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubtype = UAC_FORMAT_TYPE,
+ .bFormatType = UAC_FORMAT_TYPE_I,
+ .bSubframeSize = 2,
+ .bBitResolution = 16,
+ .bSamFreqType = 1,
+};
+
+/* Standard ISO OUT Endpoint Descriptor */
+static struct usb_endpoint_descriptor as_out_ep_desc = {
+ .bLength = USB_DT_ENDPOINT_AUDIO_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_SYNC_ADAPTIVE
+ | USB_ENDPOINT_XFER_ISOC,
+ .wMaxPacketSize = cpu_to_le16(UAC1_OUT_EP_MAX_PACKET_SIZE),
+ .bInterval = 4,
+};
+
+/* Class-specific AS ISO OUT Endpoint Descriptor */
+static struct uac_iso_endpoint_descriptor as_iso_out_desc = {
+ .bLength = UAC_ISO_ENDPOINT_DESC_SIZE,
+ .bDescriptorType = USB_DT_CS_ENDPOINT,
+ .bDescriptorSubtype = UAC_EP_GENERAL,
+ .bmAttributes = 1,
+ .bLockDelayUnits = 1,
+ .wLockDelay = __constant_cpu_to_le16(1),
+};
+
+static struct usb_descriptor_header *f_audio_desc[] = {
+ (struct usb_descriptor_header *)&ac_interface_desc,
+ (struct usb_descriptor_header *)&ac_header_desc,
+
+ (struct usb_descriptor_header *)&input_terminal_desc,
+ (struct usb_descriptor_header *)&output_terminal_desc,
+ (struct usb_descriptor_header *)&feature_unit_desc,
+
+ (struct usb_descriptor_header *)&as_interface_alt_0_desc,
+ (struct usb_descriptor_header *)&as_interface_alt_1_desc,
+ (struct usb_descriptor_header *)&as_header_desc,
+
+ (struct usb_descriptor_header *)&as_type_i_desc,
+
+ (struct usb_descriptor_header *)&as_out_ep_desc,
+ (struct usb_descriptor_header *)&as_iso_out_desc,
+ NULL,
+};
+
+enum {
+ STR_AC_IF,
+ STR_INPUT_TERMINAL,
+ STR_INPUT_TERMINAL_CH_NAMES,
+ STR_FEAT_DESC_0,
+ STR_OUTPUT_TERMINAL,
+ STR_AS_IF_ALT0,
+ STR_AS_IF_ALT1,
+};
+
+static struct usb_string strings_uac1[] = {
+ [STR_AC_IF].s = "AC Interface",
+ [STR_INPUT_TERMINAL].s = "Input terminal",
+ [STR_INPUT_TERMINAL_CH_NAMES].s = "Channels",
+ [STR_FEAT_DESC_0].s = "Volume control & mute",
+ [STR_OUTPUT_TERMINAL].s = "Output terminal",
+ [STR_AS_IF_ALT0].s = "AS Interface",
+ [STR_AS_IF_ALT1].s = "AS Interface",
+ { },
+};
+
+static struct usb_gadget_strings str_uac1 = {
+ .language = 0x0409, /* en-us */
+ .strings = strings_uac1,
+};
+
+static struct usb_gadget_strings *uac1_strings[] = {
+ &str_uac1,
+ NULL,
+};
+
+/*
+ * This function is an ALSA sound card following USB Audio Class Spec 1.0.
+ */
+
+/*-------------------------------------------------------------------------*/
+struct f_audio_buf {
+ u8 *buf;
+ int actual;
+ struct list_head list;
+};
+
+static struct f_audio_buf *f_audio_buffer_alloc(int buf_size)
+{
+ struct f_audio_buf *copy_buf;
+
+ copy_buf = kzalloc(sizeof *copy_buf, GFP_ATOMIC);
+ if (!copy_buf)
+ return ERR_PTR(-ENOMEM);
+
+ copy_buf->buf = kzalloc(buf_size, GFP_ATOMIC);
+ if (!copy_buf->buf) {
+ kfree(copy_buf);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ return copy_buf;
+}
+
+static void f_audio_buffer_free(struct f_audio_buf *audio_buf)
+{
+ kfree(audio_buf->buf);
+ kfree(audio_buf);
+}
+/*-------------------------------------------------------------------------*/
+
+struct f_audio {
+ struct gaudio card;
+
+ u8 ac_intf, ac_alt;
+ u8 as_intf, as_alt;
+
+ /* endpoints handle full and/or high speeds */
+ struct usb_ep *out_ep;
+
+ spinlock_t lock;
+ struct f_audio_buf *copy_buf;
+ struct work_struct playback_work;
+ struct list_head play_queue;
+
+ /* Control Set command */
+ struct list_head cs;
+ u8 set_cmd;
+ struct usb_audio_control *set_con;
+};
+
+static inline struct f_audio *func_to_audio(struct usb_function *f)
+{
+ return container_of(f, struct f_audio, card.func);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void f_audio_playback_work(struct work_struct *data)
+{
+ struct f_audio *audio = container_of(data, struct f_audio,
+ playback_work);
+ struct f_audio_buf *play_buf;
+
+ spin_lock_irq(&audio->lock);
+ if (list_empty(&audio->play_queue)) {
+ spin_unlock_irq(&audio->lock);
+ return;
+ }
+ play_buf = list_first_entry(&audio->play_queue,
+ struct f_audio_buf, list);
+ list_del(&play_buf->list);
+ spin_unlock_irq(&audio->lock);
+
+ u_audio_playback(&audio->card, play_buf->buf, play_buf->actual);
+ f_audio_buffer_free(play_buf);
+}
+
+static int f_audio_out_ep_complete(struct usb_ep *ep, struct usb_request *req)
+{
+ struct f_audio *audio = req->context;
+ struct usb_composite_dev *cdev = audio->card.func.config->cdev;
+ struct f_audio_buf *copy_buf = audio->copy_buf;
+ struct f_uac1_legacy_opts *opts;
+ int audio_buf_size;
+ int err;
+
+ opts = container_of(audio->card.func.fi, struct f_uac1_legacy_opts,
+ func_inst);
+ audio_buf_size = opts->audio_buf_size;
+
+ if (!copy_buf)
+ return -EINVAL;
+
+ /* Copy buffer is full, add it to the play_queue */
+ if (audio_buf_size - copy_buf->actual < req->actual) {
+ list_add_tail(&copy_buf->list, &audio->play_queue);
+ schedule_work(&audio->playback_work);
+ copy_buf = f_audio_buffer_alloc(audio_buf_size);
+ if (IS_ERR(copy_buf))
+ return -ENOMEM;
+ }
+
+ memcpy(copy_buf->buf + copy_buf->actual, req->buf, req->actual);
+ copy_buf->actual += req->actual;
+ audio->copy_buf = copy_buf;
+
+ err = usb_ep_queue(ep, req, GFP_ATOMIC);
+ if (err)
+ ERROR(cdev, "%s queue req: %d\n", ep->name, err);
+
+ return 0;
+
+}
+
+static void f_audio_complete(struct usb_ep *ep, struct usb_request *req)
+{
+ struct f_audio *audio = req->context;
+ int status = req->status;
+ u32 data = 0;
+ struct usb_ep *out_ep = audio->out_ep;
+
+ switch (status) {
+
+ case 0: /* normal completion? */
+ if (ep == out_ep)
+ f_audio_out_ep_complete(ep, req);
+ else if (audio->set_con) {
+ memcpy(&data, req->buf, req->length);
+ audio->set_con->set(audio->set_con, audio->set_cmd,
+ le16_to_cpu(data));
+ audio->set_con = NULL;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static int audio_set_intf_req(struct usb_function *f,
+ const struct usb_ctrlrequest *ctrl)
+{
+ struct f_audio *audio = func_to_audio(f);
+ struct usb_composite_dev *cdev = f->config->cdev;
+ struct usb_request *req = cdev->req;
+ u8 id = ((le16_to_cpu(ctrl->wIndex) >> 8) & 0xFF);
+ u16 len = le16_to_cpu(ctrl->wLength);
+ u16 w_value = le16_to_cpu(ctrl->wValue);
+ u8 con_sel = (w_value >> 8) & 0xFF;
+ u8 cmd = (ctrl->bRequest & 0x0F);
+ struct usb_audio_control_selector *cs;
+ struct usb_audio_control *con;
+
+ DBG(cdev, "bRequest 0x%x, w_value 0x%04x, len %d, entity %d\n",
+ ctrl->bRequest, w_value, len, id);
+
+ list_for_each_entry(cs, &audio->cs, list) {
+ if (cs->id == id) {
+ list_for_each_entry(con, &cs->control, list) {
+ if (con->type == con_sel) {
+ audio->set_con = con;
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ audio->set_cmd = cmd;
+ req->context = audio;
+ req->complete = f_audio_complete;
+
+ return len;
+}
+
+static int audio_get_intf_req(struct usb_function *f,
+ const struct usb_ctrlrequest *ctrl)
+{
+ struct f_audio *audio = func_to_audio(f);
+ struct usb_composite_dev *cdev = f->config->cdev;
+ struct usb_request *req = cdev->req;
+ int value = -EOPNOTSUPP;
+ u8 id = ((le16_to_cpu(ctrl->wIndex) >> 8) & 0xFF);
+ u16 len = le16_to_cpu(ctrl->wLength);
+ u16 w_value = le16_to_cpu(ctrl->wValue);
+ u8 con_sel = (w_value >> 8) & 0xFF;
+ u8 cmd = (ctrl->bRequest & 0x0F);
+ struct usb_audio_control_selector *cs;
+ struct usb_audio_control *con;
+
+ DBG(cdev, "bRequest 0x%x, w_value 0x%04x, len %d, entity %d\n",
+ ctrl->bRequest, w_value, len, id);
+
+ list_for_each_entry(cs, &audio->cs, list) {
+ if (cs->id == id) {
+ list_for_each_entry(con, &cs->control, list) {
+ if (con->type == con_sel && con->get) {
+ value = con->get(con, cmd);
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ req->context = audio;
+ req->complete = f_audio_complete;
+ len = min_t(size_t, sizeof(value), len);
+ memcpy(req->buf, &value, len);
+
+ return len;
+}
+
+static int audio_set_endpoint_req(struct usb_function *f,
+ const struct usb_ctrlrequest *ctrl)
+{
+ struct usb_composite_dev *cdev = f->config->cdev;
+ int value = -EOPNOTSUPP;
+ u16 ep = le16_to_cpu(ctrl->wIndex);
+ u16 len = le16_to_cpu(ctrl->wLength);
+ u16 w_value = le16_to_cpu(ctrl->wValue);
+
+ DBG(cdev, "bRequest 0x%x, w_value 0x%04x, len %d, endpoint %d\n",
+ ctrl->bRequest, w_value, len, ep);
+
+ switch (ctrl->bRequest) {
+ case UAC_SET_CUR:
+ value = len;
+ break;
+
+ case UAC_SET_MIN:
+ break;
+
+ case UAC_SET_MAX:
+ break;
+
+ case UAC_SET_RES:
+ break;
+
+ case UAC_SET_MEM:
+ break;
+
+ default:
+ break;
+ }
+
+ return value;
+}
+
+static int audio_get_endpoint_req(struct usb_function *f,
+ const struct usb_ctrlrequest *ctrl)
+{
+ struct usb_composite_dev *cdev = f->config->cdev;
+ int value = -EOPNOTSUPP;
+ u8 ep = ((le16_to_cpu(ctrl->wIndex) >> 8) & 0xFF);
+ u16 len = le16_to_cpu(ctrl->wLength);
+ u16 w_value = le16_to_cpu(ctrl->wValue);
+
+ DBG(cdev, "bRequest 0x%x, w_value 0x%04x, len %d, endpoint %d\n",
+ ctrl->bRequest, w_value, len, ep);
+
+ switch (ctrl->bRequest) {
+ case UAC_GET_CUR:
+ case UAC_GET_MIN:
+ case UAC_GET_MAX:
+ case UAC_GET_RES:
+ value = len;
+ break;
+ case UAC_GET_MEM:
+ break;
+ default:
+ break;
+ }
+
+ return value;
+}
+
+static int
+f_audio_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
+{
+ struct usb_composite_dev *cdev = f->config->cdev;
+ struct usb_request *req = cdev->req;
+ int value = -EOPNOTSUPP;
+ u16 w_index = le16_to_cpu(ctrl->wIndex);
+ u16 w_value = le16_to_cpu(ctrl->wValue);
+ u16 w_length = le16_to_cpu(ctrl->wLength);
+
+ /* composite driver infrastructure handles everything; interface
+ * activation uses set_alt().
+ */
+ switch (ctrl->bRequestType) {
+ case USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE:
+ value = audio_set_intf_req(f, ctrl);
+ break;
+
+ case USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE:
+ value = audio_get_intf_req(f, ctrl);
+ break;
+
+ case USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_ENDPOINT:
+ value = audio_set_endpoint_req(f, ctrl);
+ break;
+
+ case USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT:
+ value = audio_get_endpoint_req(f, ctrl);
+ break;
+
+ default:
+ ERROR(cdev, "invalid control req%02x.%02x v%04x i%04x l%d\n",
+ ctrl->bRequestType, ctrl->bRequest,
+ w_value, w_index, w_length);
+ }
+
+ /* respond with data transfer or status phase? */
+ if (value >= 0) {
+ DBG(cdev, "audio req%02x.%02x v%04x i%04x l%d\n",
+ ctrl->bRequestType, ctrl->bRequest,
+ w_value, w_index, w_length);
+ req->zero = 0;
+ req->length = value;
+ value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
+ if (value < 0)
+ ERROR(cdev, "audio response on err %d\n", value);
+ }
+
+ /* device either stalls (value < 0) or reports success */
+ return value;
+}
+
+static int f_audio_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
+{
+ struct f_audio *audio = func_to_audio(f);
+ struct usb_composite_dev *cdev = f->config->cdev;
+ struct usb_ep *out_ep = audio->out_ep;
+ struct usb_request *req;
+ struct f_uac1_legacy_opts *opts;
+ int req_buf_size, req_count, audio_buf_size;
+ int i = 0, err = 0;
+
+ DBG(cdev, "intf %d, alt %d\n", intf, alt);
+
+ opts = container_of(f->fi, struct f_uac1_legacy_opts, func_inst);
+ req_buf_size = opts->req_buf_size;
+ req_count = opts->req_count;
+ audio_buf_size = opts->audio_buf_size;
+
+ /* No i/f has more than 2 alt settings */
+ if (alt > 1) {
+ ERROR(cdev, "%s:%d Error!\n", __func__, __LINE__);
+ return -EINVAL;
+ }
+
+ if (intf == audio->ac_intf) {
+ /* Control I/f has only 1 AltSetting - 0 */
+ if (alt) {
+ ERROR(cdev, "%s:%d Error!\n", __func__, __LINE__);
+ return -EINVAL;
+ }
+ return 0;
+ } else if (intf == audio->as_intf) {
+ if (alt == 1) {
+ err = config_ep_by_speed(cdev->gadget, f, out_ep);
+ if (err)
+ return err;
+
+ usb_ep_enable(out_ep);
+ audio->copy_buf = f_audio_buffer_alloc(audio_buf_size);
+ if (IS_ERR(audio->copy_buf))
+ return -ENOMEM;
+
+ /*
+ * allocate a bunch of read buffers
+ * and queue them all at once.
+ */
+ for (i = 0; i < req_count && err == 0; i++) {
+ req = usb_ep_alloc_request(out_ep, GFP_ATOMIC);
+ if (req) {
+ req->buf = kzalloc(req_buf_size,
+ GFP_ATOMIC);
+ if (req->buf) {
+ req->length = req_buf_size;
+ req->context = audio;
+ req->complete =
+ f_audio_complete;
+ err = usb_ep_queue(out_ep,
+ req, GFP_ATOMIC);
+ if (err)
+ ERROR(cdev,
+ "%s queue req: %d\n",
+ out_ep->name, err);
+ } else
+ err = -ENOMEM;
+ } else
+ err = -ENOMEM;
+ }
+
+ } else {
+ struct f_audio_buf *copy_buf = audio->copy_buf;
+ if (copy_buf) {
+ list_add_tail(&copy_buf->list,
+ &audio->play_queue);
+ schedule_work(&audio->playback_work);
+ }
+ }
+ audio->as_alt = alt;
+ }
+
+ return err;
+}
+
+static int f_audio_get_alt(struct usb_function *f, unsigned intf)
+{
+ struct f_audio *audio = func_to_audio(f);
+ struct usb_composite_dev *cdev = f->config->cdev;
+
+ if (intf == audio->ac_intf)
+ return audio->ac_alt;
+ else if (intf == audio->as_intf)
+ return audio->as_alt;
+ else
+ ERROR(cdev, "%s:%d Invalid Interface %d!\n",
+ __func__, __LINE__, intf);
+
+ return -EINVAL;
+}
+
+static void f_audio_disable(struct usb_function *f)
+{
+ return;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void f_audio_build_desc(struct f_audio *audio)
+{
+ struct gaudio *card = &audio->card;
+ u8 *sam_freq;
+ int rate;
+
+ /* Set channel numbers */
+ input_terminal_desc.bNrChannels = u_audio_get_playback_channels(card);
+ as_type_i_desc.bNrChannels = u_audio_get_playback_channels(card);
+
+ /* Set sample rates */
+ rate = u_audio_get_playback_rate(card);
+ sam_freq = as_type_i_desc.tSamFreq[0];
+ memcpy(sam_freq, &rate, 3);
+
+ /* Todo: Set Sample bits and other parameters */
+
+ return;
+}
+
+/* audio function driver setup/binding */
+static int
+f_audio_bind(struct usb_configuration *c, struct usb_function *f)
+{
+ struct usb_composite_dev *cdev = c->cdev;
+ struct f_audio *audio = func_to_audio(f);
+ struct usb_string *us;
+ int status;
+ struct usb_ep *ep = NULL;
+ struct f_uac1_legacy_opts *audio_opts;
+
+ audio_opts = container_of(f->fi, struct f_uac1_legacy_opts, func_inst);
+ audio->card.gadget = c->cdev->gadget;
+ /* set up ASLA audio devices */
+ if (!audio_opts->bound) {
+ status = gaudio_setup(&audio->card);
+ if (status < 0)
+ return status;
+ audio_opts->bound = true;
+ }
+ us = usb_gstrings_attach(cdev, uac1_strings, ARRAY_SIZE(strings_uac1));
+ if (IS_ERR(us))
+ return PTR_ERR(us);
+ ac_interface_desc.iInterface = us[STR_AC_IF].id;
+ input_terminal_desc.iTerminal = us[STR_INPUT_TERMINAL].id;
+ input_terminal_desc.iChannelNames = us[STR_INPUT_TERMINAL_CH_NAMES].id;
+ feature_unit_desc.iFeature = us[STR_FEAT_DESC_0].id;
+ output_terminal_desc.iTerminal = us[STR_OUTPUT_TERMINAL].id;
+ as_interface_alt_0_desc.iInterface = us[STR_AS_IF_ALT0].id;
+ as_interface_alt_1_desc.iInterface = us[STR_AS_IF_ALT1].id;
+
+
+ f_audio_build_desc(audio);
+
+ /* allocate instance-specific interface IDs, and patch descriptors */
+ status = usb_interface_id(c, f);
+ if (status < 0)
+ goto fail;
+ ac_interface_desc.bInterfaceNumber = status;
+ audio->ac_intf = status;
+ audio->ac_alt = 0;
+
+ status = usb_interface_id(c, f);
+ if (status < 0)
+ goto fail;
+ as_interface_alt_0_desc.bInterfaceNumber = status;
+ as_interface_alt_1_desc.bInterfaceNumber = status;
+ audio->as_intf = status;
+ audio->as_alt = 0;
+
+ status = -ENODEV;
+
+ /* allocate instance-specific endpoints */
+ ep = usb_ep_autoconfig(cdev->gadget, &as_out_ep_desc);
+ if (!ep)
+ goto fail;
+ audio->out_ep = ep;
+ audio->out_ep->desc = &as_out_ep_desc;
+
+ status = -ENOMEM;
+
+ /* copy descriptors, and track endpoint copies */
+ status = usb_assign_descriptors(f, f_audio_desc, f_audio_desc, NULL,
+ NULL);
+ if (status)
+ goto fail;
+ return 0;
+
+fail:
+ gaudio_cleanup(&audio->card);
+ return status;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int generic_set_cmd(struct usb_audio_control *con, u8 cmd, int value)
+{
+ con->data[cmd] = value;
+
+ return 0;
+}
+
+static int generic_get_cmd(struct usb_audio_control *con, u8 cmd)
+{
+ return con->data[cmd];
+}
+
+/* Todo: add more control selecotor dynamically */
+static int control_selector_init(struct f_audio *audio)
+{
+ INIT_LIST_HEAD(&audio->cs);
+ list_add(&feature_unit.list, &audio->cs);
+
+ INIT_LIST_HEAD(&feature_unit.control);
+ list_add(&mute_control.list, &feature_unit.control);
+ list_add(&volume_control.list, &feature_unit.control);
+
+ volume_control.data[UAC__CUR] = 0xffc0;
+ volume_control.data[UAC__MIN] = 0xe3a0;
+ volume_control.data[UAC__MAX] = 0xfff0;
+ volume_control.data[UAC__RES] = 0x0030;
+
+ return 0;
+}
+
+static inline
+struct f_uac1_legacy_opts *to_f_uac1_opts(struct config_item *item)
+{
+ return container_of(to_config_group(item), struct f_uac1_legacy_opts,
+ func_inst.group);
+}
+
+static void f_uac1_attr_release(struct config_item *item)
+{
+ struct f_uac1_legacy_opts *opts = to_f_uac1_opts(item);
+
+ usb_put_function_instance(&opts->func_inst);
+}
+
+static struct configfs_item_operations f_uac1_item_ops = {
+ .release = f_uac1_attr_release,
+};
+
+#define UAC1_INT_ATTRIBUTE(name) \
+static ssize_t f_uac1_opts_##name##_show(struct config_item *item, \
+ char *page) \
+{ \
+ struct f_uac1_legacy_opts *opts = to_f_uac1_opts(item); \
+ int result; \
+ \
+ mutex_lock(&opts->lock); \
+ result = sprintf(page, "%u\n", opts->name); \
+ mutex_unlock(&opts->lock); \
+ \
+ return result; \
+} \
+ \
+static ssize_t f_uac1_opts_##name##_store(struct config_item *item, \
+ const char *page, size_t len) \
+{ \
+ struct f_uac1_legacy_opts *opts = to_f_uac1_opts(item); \
+ int ret; \
+ u32 num; \
+ \
+ mutex_lock(&opts->lock); \
+ if (opts->refcnt) { \
+ ret = -EBUSY; \
+ goto end; \
+ } \
+ \
+ ret = kstrtou32(page, 0, &num); \
+ if (ret) \
+ goto end; \
+ \
+ opts->name = num; \
+ ret = len; \
+ \
+end: \
+ mutex_unlock(&opts->lock); \
+ return ret; \
+} \
+ \
+CONFIGFS_ATTR(f_uac1_opts_, name)
+
+UAC1_INT_ATTRIBUTE(req_buf_size);
+UAC1_INT_ATTRIBUTE(req_count);
+UAC1_INT_ATTRIBUTE(audio_buf_size);
+
+#define UAC1_STR_ATTRIBUTE(name) \
+static ssize_t f_uac1_opts_##name##_show(struct config_item *item, \
+ char *page) \
+{ \
+ struct f_uac1_legacy_opts *opts = to_f_uac1_opts(item); \
+ int result; \
+ \
+ mutex_lock(&opts->lock); \
+ result = sprintf(page, "%s\n", opts->name); \
+ mutex_unlock(&opts->lock); \
+ \
+ return result; \
+} \
+ \
+static ssize_t f_uac1_opts_##name##_store(struct config_item *item, \
+ const char *page, size_t len) \
+{ \
+ struct f_uac1_legacy_opts *opts = to_f_uac1_opts(item); \
+ int ret = -EBUSY; \
+ char *tmp; \
+ \
+ mutex_lock(&opts->lock); \
+ if (opts->refcnt) \
+ goto end; \
+ \
+ tmp = kstrndup(page, len, GFP_KERNEL); \
+ if (tmp) { \
+ ret = -ENOMEM; \
+ goto end; \
+ } \
+ if (opts->name##_alloc) \
+ kfree(opts->name); \
+ opts->name##_alloc = true; \
+ opts->name = tmp; \
+ ret = len; \
+ \
+end: \
+ mutex_unlock(&opts->lock); \
+ return ret; \
+} \
+ \
+CONFIGFS_ATTR(f_uac1_opts_, name)
+
+UAC1_STR_ATTRIBUTE(fn_play);
+UAC1_STR_ATTRIBUTE(fn_cap);
+UAC1_STR_ATTRIBUTE(fn_cntl);
+
+static struct configfs_attribute *f_uac1_attrs[] = {
+ &f_uac1_opts_attr_req_buf_size,
+ &f_uac1_opts_attr_req_count,
+ &f_uac1_opts_attr_audio_buf_size,
+ &f_uac1_opts_attr_fn_play,
+ &f_uac1_opts_attr_fn_cap,
+ &f_uac1_opts_attr_fn_cntl,
+ NULL,
+};
+
+static const struct config_item_type f_uac1_func_type = {
+ .ct_item_ops = &f_uac1_item_ops,
+ .ct_attrs = f_uac1_attrs,
+ .ct_owner = THIS_MODULE,
+};
+
+static void f_audio_free_inst(struct usb_function_instance *f)
+{
+ struct f_uac1_legacy_opts *opts;
+
+ opts = container_of(f, struct f_uac1_legacy_opts, func_inst);
+ if (opts->fn_play_alloc)
+ kfree(opts->fn_play);
+ if (opts->fn_cap_alloc)
+ kfree(opts->fn_cap);
+ if (opts->fn_cntl_alloc)
+ kfree(opts->fn_cntl);
+ kfree(opts);
+}
+
+static struct usb_function_instance *f_audio_alloc_inst(void)
+{
+ struct f_uac1_legacy_opts *opts;
+
+ opts = kzalloc(sizeof(*opts), GFP_KERNEL);
+ if (!opts)
+ return ERR_PTR(-ENOMEM);
+
+ mutex_init(&opts->lock);
+ opts->func_inst.free_func_inst = f_audio_free_inst;
+
+ config_group_init_type_name(&opts->func_inst.group, "",
+ &f_uac1_func_type);
+
+ opts->req_buf_size = UAC1_OUT_EP_MAX_PACKET_SIZE;
+ opts->req_count = UAC1_REQ_COUNT;
+ opts->audio_buf_size = UAC1_AUDIO_BUF_SIZE;
+ opts->fn_play = FILE_PCM_PLAYBACK;
+ opts->fn_cap = FILE_PCM_CAPTURE;
+ opts->fn_cntl = FILE_CONTROL;
+ return &opts->func_inst;
+}
+
+static void f_audio_free(struct usb_function *f)
+{
+ struct f_audio *audio = func_to_audio(f);
+ struct f_uac1_legacy_opts *opts;
+
+ gaudio_cleanup(&audio->card);
+ opts = container_of(f->fi, struct f_uac1_legacy_opts, func_inst);
+ kfree(audio);
+ mutex_lock(&opts->lock);
+ --opts->refcnt;
+ mutex_unlock(&opts->lock);
+}
+
+static void f_audio_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+ usb_free_all_descriptors(f);
+}
+
+static struct usb_function *f_audio_alloc(struct usb_function_instance *fi)
+{
+ struct f_audio *audio;
+ struct f_uac1_legacy_opts *opts;
+
+ /* allocate and initialize one new instance */
+ audio = kzalloc(sizeof(*audio), GFP_KERNEL);
+ if (!audio)
+ return ERR_PTR(-ENOMEM);
+
+ audio->card.func.name = "g_audio";
+
+ opts = container_of(fi, struct f_uac1_legacy_opts, func_inst);
+ mutex_lock(&opts->lock);
+ ++opts->refcnt;
+ mutex_unlock(&opts->lock);
+ INIT_LIST_HEAD(&audio->play_queue);
+ spin_lock_init(&audio->lock);
+
+ audio->card.func.bind = f_audio_bind;
+ audio->card.func.unbind = f_audio_unbind;
+ audio->card.func.set_alt = f_audio_set_alt;
+ audio->card.func.get_alt = f_audio_get_alt;
+ audio->card.func.setup = f_audio_setup;
+ audio->card.func.disable = f_audio_disable;
+ audio->card.func.free_func = f_audio_free;
+
+ control_selector_init(audio);
+
+ INIT_WORK(&audio->playback_work, f_audio_playback_work);
+
+ return &audio->card.func;
+}
+
+DECLARE_USB_FUNCTION_INIT(uac1_legacy, f_audio_alloc_inst, f_audio_alloc);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Bryan Wu");
diff -urN linux-4.9.37/drivers/usb/gadget/function/f_uac2.c linux-4.9.y/drivers/usb/gadget/function/f_uac2.c
--- linux-4.9.37/drivers/usb/gadget/function/f_uac2.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/gadget/function/f_uac2.c 2021-06-07 13:01:34.000000000 +0300
@@ -1,30 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* f_uac2.c -- USB Audio Class 2.0 Function
*
* Copyright (C) 2011
* Yadwinder Singh (yadi.brar01@gmail.com)
* Jaswinder Singh (jaswinder.singh@linaro.org)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
*/
#include <linux/usb/audio.h>
#include <linux/usb/audio-v2.h>
-#include <linux/platform_device.h>
#include <linux/module.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-
+#include "u_audio.h"
#include "u_uac2.h"
-/* Keep everyone on toes */
-#define USB_XFERS 2
-
/*
* The driver implements a simple UAC_2 topology.
* USB-OUT -> IT_1 -> OT_3 -> ALSA_Capture
@@ -33,12 +22,8 @@
* controlled by two clock sources :
* CLK_5 := c_srate, and CLK_6 := p_srate
*/
-#define USB_OUT_IT_ID 1
-#define IO_IN_IT_ID 2
-#define IO_OUT_OT_ID 3
-#define USB_IN_OT_ID 4
-#define USB_OUT_CLK_ID 5
-#define USB_IN_CLK_ID 6
+#define USB_OUT_CLK_ID (out_clk_src_desc.bClockID)
+#define USB_IN_CLK_ID (in_clk_src_desc.bClockID)
#define CONTROL_ABSENT 0
#define CONTROL_RDONLY 1
@@ -54,504 +39,26 @@
#define UNFLW_CTRL 8
#define OVFLW_CTRL 10
-static const char *uac2_name = "snd_uac2";
-
-struct uac2_req {
- struct uac2_rtd_params *pp; /* parent param */
- struct usb_request *req;
-};
-
-struct uac2_rtd_params {
- struct snd_uac2_chip *uac2; /* parent chip */
- bool ep_enabled; /* if the ep is enabled */
- /* Size of the ring buffer */
- size_t dma_bytes;
- unsigned char *dma_area;
-
- struct snd_pcm_substream *ss;
+#define EPIN_EN(_opts) ((_opts)->p_chmask != 0)
+#define EPOUT_EN(_opts) ((_opts)->c_chmask != 0)
- /* Ring buffer */
- ssize_t hw_ptr;
-
- void *rbuf;
-
- size_t period_size;
-
- unsigned max_psize;
- struct uac2_req ureq[USB_XFERS];
-
- spinlock_t lock;
+struct f_uac2 {
+ struct g_audio g_audio;
+ u8 ac_intf, as_in_intf, as_out_intf;
+ u8 ac_alt, as_in_alt, as_out_alt; /* needed for get_alt() */
};
-struct snd_uac2_chip {
- struct platform_device pdev;
- struct platform_driver pdrv;
-
- struct uac2_rtd_params p_prm;
- struct uac2_rtd_params c_prm;
-
- struct snd_card *card;
- struct snd_pcm *pcm;
-
- /* timekeeping for the playback endpoint */
- unsigned int p_interval;
- unsigned int p_residue;
-
- /* pre-calculated values for playback iso completion */
- unsigned int p_pktsize;
- unsigned int p_pktsize_residue;
- unsigned int p_framesize;
-};
-
-#define BUFF_SIZE_MAX (PAGE_SIZE * 16)
-#define PRD_SIZE_MAX PAGE_SIZE
-#define MIN_PERIODS 4
-
-static struct snd_pcm_hardware uac2_pcm_hardware = {
- .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER
- | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID
- | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
- .rates = SNDRV_PCM_RATE_CONTINUOUS,
- .periods_max = BUFF_SIZE_MAX / PRD_SIZE_MAX,
- .buffer_bytes_max = BUFF_SIZE_MAX,
- .period_bytes_max = PRD_SIZE_MAX,
- .periods_min = MIN_PERIODS,
-};
-
-struct audio_dev {
- u8 ac_intf, ac_alt;
- u8 as_out_intf, as_out_alt;
- u8 as_in_intf, as_in_alt;
-
- struct usb_ep *in_ep, *out_ep;
- struct usb_function func;
-
- /* The ALSA Sound Card it represents on the USB-Client side */
- struct snd_uac2_chip uac2;
-};
-
-static inline
-struct audio_dev *func_to_agdev(struct usb_function *f)
-{
- return container_of(f, struct audio_dev, func);
-}
-
-static inline
-struct audio_dev *uac2_to_agdev(struct snd_uac2_chip *u)
+static inline struct f_uac2 *func_to_uac2(struct usb_function *f)
{
- return container_of(u, struct audio_dev, uac2);
+ return container_of(f, struct f_uac2, g_audio.func);
}
static inline
-struct snd_uac2_chip *pdev_to_uac2(struct platform_device *p)
-{
- return container_of(p, struct snd_uac2_chip, pdev);
-}
-
-static inline
-struct f_uac2_opts *agdev_to_uac2_opts(struct audio_dev *agdev)
+struct f_uac2_opts *g_audio_to_uac2_opts(struct g_audio *agdev)
{
return container_of(agdev->func.fi, struct f_uac2_opts, func_inst);
}
-static inline
-uint num_channels(uint chanmask)
-{
- uint num = 0;
-
- while (chanmask) {
- num += (chanmask & 1);
- chanmask >>= 1;
- }
-
- return num;
-}
-
-static void
-agdev_iso_complete(struct usb_ep *ep, struct usb_request *req)
-{
- unsigned pending;
- unsigned long flags;
- unsigned int hw_ptr;
- bool update_alsa = false;
- int status = req->status;
- struct uac2_req *ur = req->context;
- struct snd_pcm_substream *substream;
- struct uac2_rtd_params *prm = ur->pp;
- struct snd_uac2_chip *uac2 = prm->uac2;
-
- /* i/f shutting down */
- if (!prm->ep_enabled || req->status == -ESHUTDOWN)
- return;
-
- /*
- * We can't really do much about bad xfers.
- * Afterall, the ISOCH xfers could fail legitimately.
- */
- if (status)
- pr_debug("%s: iso_complete status(%d) %d/%d\n",
- __func__, status, req->actual, req->length);
-
- substream = prm->ss;
-
- /* Do nothing if ALSA isn't active */
- if (!substream)
- goto exit;
-
- spin_lock_irqsave(&prm->lock, flags);
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- /*
- * For each IN packet, take the quotient of the current data
- * rate and the endpoint's interval as the base packet size.
- * If there is a residue from this division, add it to the
- * residue accumulator.
- */
- req->length = uac2->p_pktsize;
- uac2->p_residue += uac2->p_pktsize_residue;
-
- /*
- * Whenever there are more bytes in the accumulator than we
- * need to add one more sample frame, increase this packet's
- * size and decrease the accumulator.
- */
- if (uac2->p_residue / uac2->p_interval >= uac2->p_framesize) {
- req->length += uac2->p_framesize;
- uac2->p_residue -= uac2->p_framesize *
- uac2->p_interval;
- }
-
- req->actual = req->length;
- }
-
- pending = prm->hw_ptr % prm->period_size;
- pending += req->actual;
- if (pending >= prm->period_size)
- update_alsa = true;
-
- hw_ptr = prm->hw_ptr;
- prm->hw_ptr = (prm->hw_ptr + req->actual) % prm->dma_bytes;
-
- spin_unlock_irqrestore(&prm->lock, flags);
-
- /* Pack USB load in ALSA ring buffer */
- pending = prm->dma_bytes - hw_ptr;
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- if (unlikely(pending < req->actual)) {
- memcpy(req->buf, prm->dma_area + hw_ptr, pending);
- memcpy(req->buf + pending, prm->dma_area,
- req->actual - pending);
- } else {
- memcpy(req->buf, prm->dma_area + hw_ptr, req->actual);
- }
- } else {
- if (unlikely(pending < req->actual)) {
- memcpy(prm->dma_area + hw_ptr, req->buf, pending);
- memcpy(prm->dma_area, req->buf + pending,
- req->actual - pending);
- } else {
- memcpy(prm->dma_area + hw_ptr, req->buf, req->actual);
- }
- }
-
-exit:
- if (usb_ep_queue(ep, req, GFP_ATOMIC))
- dev_err(&uac2->pdev.dev, "%d Error!\n", __LINE__);
-
- if (update_alsa)
- snd_pcm_period_elapsed(substream);
-
- return;
-}
-
-static int
-uac2_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
-{
- struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream);
- struct uac2_rtd_params *prm;
- unsigned long flags;
- int err = 0;
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- prm = &uac2->p_prm;
- else
- prm = &uac2->c_prm;
-
- spin_lock_irqsave(&prm->lock, flags);
-
- /* Reset */
- prm->hw_ptr = 0;
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- case SNDRV_PCM_TRIGGER_RESUME:
- prm->ss = substream;
- break;
- case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- prm->ss = NULL;
- break;
- default:
- err = -EINVAL;
- }
-
- spin_unlock_irqrestore(&prm->lock, flags);
-
- /* Clear buffer after Play stops */
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && !prm->ss)
- memset(prm->rbuf, 0, prm->max_psize * USB_XFERS);
-
- return err;
-}
-
-static snd_pcm_uframes_t uac2_pcm_pointer(struct snd_pcm_substream *substream)
-{
- struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream);
- struct uac2_rtd_params *prm;
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- prm = &uac2->p_prm;
- else
- prm = &uac2->c_prm;
-
- return bytes_to_frames(substream->runtime, prm->hw_ptr);
-}
-
-static int uac2_pcm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *hw_params)
-{
- struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream);
- struct uac2_rtd_params *prm;
- int err;
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- prm = &uac2->p_prm;
- else
- prm = &uac2->c_prm;
-
- err = snd_pcm_lib_malloc_pages(substream,
- params_buffer_bytes(hw_params));
- if (err >= 0) {
- prm->dma_bytes = substream->runtime->dma_bytes;
- prm->dma_area = substream->runtime->dma_area;
- prm->period_size = params_period_bytes(hw_params);
- }
-
- return err;
-}
-
-static int uac2_pcm_hw_free(struct snd_pcm_substream *substream)
-{
- struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream);
- struct uac2_rtd_params *prm;
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- prm = &uac2->p_prm;
- else
- prm = &uac2->c_prm;
-
- prm->dma_area = NULL;
- prm->dma_bytes = 0;
- prm->period_size = 0;
-
- return snd_pcm_lib_free_pages(substream);
-}
-
-static int uac2_pcm_open(struct snd_pcm_substream *substream)
-{
- struct snd_uac2_chip *uac2 = snd_pcm_substream_chip(substream);
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct audio_dev *audio_dev;
- struct f_uac2_opts *opts;
- int p_ssize, c_ssize;
- int p_srate, c_srate;
- int p_chmask, c_chmask;
-
- audio_dev = uac2_to_agdev(uac2);
- opts = container_of(audio_dev->func.fi, struct f_uac2_opts, func_inst);
- p_ssize = opts->p_ssize;
- c_ssize = opts->c_ssize;
- p_srate = opts->p_srate;
- c_srate = opts->c_srate;
- p_chmask = opts->p_chmask;
- c_chmask = opts->c_chmask;
- uac2->p_residue = 0;
-
- runtime->hw = uac2_pcm_hardware;
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- spin_lock_init(&uac2->p_prm.lock);
- runtime->hw.rate_min = p_srate;
- switch (p_ssize) {
- case 3:
- runtime->hw.formats = SNDRV_PCM_FMTBIT_S24_3LE;
- break;
- case 4:
- runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE;
- break;
- default:
- runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
- break;
- }
- runtime->hw.channels_min = num_channels(p_chmask);
- runtime->hw.period_bytes_min = 2 * uac2->p_prm.max_psize
- / runtime->hw.periods_min;
- } else {
- spin_lock_init(&uac2->c_prm.lock);
- runtime->hw.rate_min = c_srate;
- switch (c_ssize) {
- case 3:
- runtime->hw.formats = SNDRV_PCM_FMTBIT_S24_3LE;
- break;
- case 4:
- runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE;
- break;
- default:
- runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
- break;
- }
- runtime->hw.channels_min = num_channels(c_chmask);
- runtime->hw.period_bytes_min = 2 * uac2->c_prm.max_psize
- / runtime->hw.periods_min;
- }
-
- runtime->hw.rate_max = runtime->hw.rate_min;
- runtime->hw.channels_max = runtime->hw.channels_min;
-
- snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
-
- return 0;
-}
-
-/* ALSA cries without these function pointers */
-static int uac2_pcm_null(struct snd_pcm_substream *substream)
-{
- return 0;
-}
-
-static struct snd_pcm_ops uac2_pcm_ops = {
- .open = uac2_pcm_open,
- .close = uac2_pcm_null,
- .ioctl = snd_pcm_lib_ioctl,
- .hw_params = uac2_pcm_hw_params,
- .hw_free = uac2_pcm_hw_free,
- .trigger = uac2_pcm_trigger,
- .pointer = uac2_pcm_pointer,
- .prepare = uac2_pcm_null,
-};
-
-static int snd_uac2_probe(struct platform_device *pdev)
-{
- struct snd_uac2_chip *uac2 = pdev_to_uac2(pdev);
- struct snd_card *card;
- struct snd_pcm *pcm;
- struct audio_dev *audio_dev;
- struct f_uac2_opts *opts;
- int err;
- int p_chmask, c_chmask;
-
- audio_dev = uac2_to_agdev(uac2);
- opts = container_of(audio_dev->func.fi, struct f_uac2_opts, func_inst);
- p_chmask = opts->p_chmask;
- c_chmask = opts->c_chmask;
-
- /* Choose any slot, with no id */
- err = snd_card_new(&pdev->dev, -1, NULL, THIS_MODULE, 0, &card);
- if (err < 0)
- return err;
-
- uac2->card = card;
-
- /*
- * Create first PCM device
- * Create a substream only for non-zero channel streams
- */
- err = snd_pcm_new(uac2->card, "UAC2 PCM", 0,
- p_chmask ? 1 : 0, c_chmask ? 1 : 0, &pcm);
- if (err < 0)
- goto snd_fail;
-
- strcpy(pcm->name, "UAC2 PCM");
- pcm->private_data = uac2;
-
- uac2->pcm = pcm;
-
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &uac2_pcm_ops);
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &uac2_pcm_ops);
-
- strcpy(card->driver, "UAC2_Gadget");
- strcpy(card->shortname, "UAC2_Gadget");
- sprintf(card->longname, "UAC2_Gadget %i", pdev->id);
-
- snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
- snd_dma_continuous_data(GFP_KERNEL), 0, BUFF_SIZE_MAX);
-
- err = snd_card_register(card);
- if (!err) {
- platform_set_drvdata(pdev, card);
- return 0;
- }
-
-snd_fail:
- snd_card_free(card);
-
- uac2->pcm = NULL;
- uac2->card = NULL;
-
- return err;
-}
-
-static int snd_uac2_remove(struct platform_device *pdev)
-{
- struct snd_card *card = platform_get_drvdata(pdev);
-
- if (card)
- return snd_card_free(card);
-
- return 0;
-}
-
-static void snd_uac2_release(struct device *dev)
-{
- dev_dbg(dev, "releasing '%s'\n", dev_name(dev));
-}
-
-static int alsa_uac2_init(struct audio_dev *agdev)
-{
- struct snd_uac2_chip *uac2 = &agdev->uac2;
- int err;
-
- uac2->pdrv.probe = snd_uac2_probe;
- uac2->pdrv.remove = snd_uac2_remove;
- uac2->pdrv.driver.name = uac2_name;
-
- uac2->pdev.id = 0;
- uac2->pdev.name = uac2_name;
- uac2->pdev.dev.release = snd_uac2_release;
-
- /* Register snd_uac2 driver */
- err = platform_driver_register(&uac2->pdrv);
- if (err)
- return err;
-
- /* Register snd_uac2 device */
- err = platform_device_register(&uac2->pdev);
- if (err)
- platform_driver_unregister(&uac2->pdrv);
-
- return err;
-}
-
-static void alsa_uac2_exit(struct audio_dev *agdev)
-{
- struct snd_uac2_chip *uac2 = &agdev->uac2;
-
- platform_driver_unregister(&uac2->pdrv);
- platform_device_unregister(&uac2->pdev);
-}
-
-
/* --------- USB Function Interface ------------- */
enum {
@@ -627,7 +134,7 @@
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubtype = UAC2_CLOCK_SOURCE,
- .bClockID = USB_IN_CLK_ID,
+ /* .bClockID = DYNAMIC */
.bmAttributes = UAC_CLOCK_SOURCE_TYPE_INT_FIXED,
.bmControls = (CONTROL_RDONLY << CLK_FREQ_CTRL),
.bAssocTerminal = 0,
@@ -639,7 +146,7 @@
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubtype = UAC2_CLOCK_SOURCE,
- .bClockID = USB_OUT_CLK_ID,
+ /* .bClockID = DYNAMIC */
.bmAttributes = UAC_CLOCK_SOURCE_TYPE_INT_FIXED,
.bmControls = (CONTROL_RDONLY << CLK_FREQ_CTRL),
.bAssocTerminal = 0,
@@ -651,12 +158,12 @@
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubtype = UAC_INPUT_TERMINAL,
- .bTerminalID = USB_OUT_IT_ID,
+ /* .bTerminalID = DYNAMIC */
.wTerminalType = cpu_to_le16(UAC_TERMINAL_STREAMING),
.bAssocTerminal = 0,
- .bCSourceID = USB_OUT_CLK_ID,
+ /* .bCSourceID = DYNAMIC */
.iChannelNames = 0,
- .bmControls = (CONTROL_RDWR << COPY_CTRL),
+ .bmControls = cpu_to_le16(CONTROL_RDWR << COPY_CTRL),
};
/* Input Terminal for I/O-In */
@@ -665,12 +172,12 @@
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubtype = UAC_INPUT_TERMINAL,
- .bTerminalID = IO_IN_IT_ID,
+ /* .bTerminalID = DYNAMIC */
.wTerminalType = cpu_to_le16(UAC_INPUT_TERMINAL_UNDEFINED),
.bAssocTerminal = 0,
- .bCSourceID = USB_IN_CLK_ID,
+ /* .bCSourceID = DYNAMIC */
.iChannelNames = 0,
- .bmControls = (CONTROL_RDWR << COPY_CTRL),
+ .bmControls = cpu_to_le16(CONTROL_RDWR << COPY_CTRL),
};
/* Ouput Terminal for USB_IN */
@@ -679,12 +186,12 @@
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubtype = UAC_OUTPUT_TERMINAL,
- .bTerminalID = USB_IN_OT_ID,
+ /* .bTerminalID = DYNAMIC */
.wTerminalType = cpu_to_le16(UAC_TERMINAL_STREAMING),
.bAssocTerminal = 0,
- .bSourceID = IO_IN_IT_ID,
- .bCSourceID = USB_IN_CLK_ID,
- .bmControls = (CONTROL_RDWR << COPY_CTRL),
+ /* .bSourceID = DYNAMIC */
+ /* .bCSourceID = DYNAMIC */
+ .bmControls = cpu_to_le16(CONTROL_RDWR << COPY_CTRL),
};
/* Ouput Terminal for I/O-Out */
@@ -693,12 +200,12 @@
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubtype = UAC_OUTPUT_TERMINAL,
- .bTerminalID = IO_OUT_OT_ID,
+ /* .bTerminalID = DYNAMIC */
.wTerminalType = cpu_to_le16(UAC_OUTPUT_TERMINAL_UNDEFINED),
.bAssocTerminal = 0,
- .bSourceID = USB_OUT_IT_ID,
- .bCSourceID = USB_OUT_CLK_ID,
- .bmControls = (CONTROL_RDWR << COPY_CTRL),
+ /* .bSourceID = DYNAMIC */
+ /* .bCSourceID = DYNAMIC */
+ .bmControls = cpu_to_le16(CONTROL_RDWR << COPY_CTRL),
};
static struct uac2_ac_header_descriptor ac_hdr_desc = {
@@ -708,9 +215,10 @@
.bDescriptorSubtype = UAC_MS_HEADER,
.bcdADC = cpu_to_le16(0x200),
.bCategory = UAC2_FUNCTION_IO_BOX,
- .wTotalLength = sizeof in_clk_src_desc + sizeof out_clk_src_desc
- + sizeof usb_out_it_desc + sizeof io_in_it_desc
- + sizeof usb_in_ot_desc + sizeof io_out_ot_desc,
+ .wTotalLength = cpu_to_le16(sizeof in_clk_src_desc
+ + sizeof out_clk_src_desc + sizeof usb_out_it_desc
+ + sizeof io_in_it_desc + sizeof usb_in_ot_desc
+ + sizeof io_out_ot_desc),
.bmControls = 0,
};
@@ -744,7 +252,7 @@
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubtype = UAC_AS_GENERAL,
- .bTerminalLink = USB_OUT_IT_ID,
+ /* .bTerminalLink = DYNAMIC */
.bmControls = 0,
.bFormatType = UAC_FORMAT_TYPE_I,
.bmFormats = cpu_to_le32(UAC_FORMAT_TYPE_I_PCM),
@@ -821,7 +329,7 @@
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubtype = UAC_AS_GENERAL,
- .bTerminalLink = USB_IN_OT_ID,
+ /* .bTerminalLink = DYNAMIC */
.bmControls = 0,
.bFormatType = UAC_FORMAT_TYPE_I,
.bmFormats = cpu_to_le32(UAC_FORMAT_TYPE_I_PCM),
@@ -929,40 +437,16 @@
};
struct cntrl_cur_lay3 {
- __u32 dCUR;
+ __le32 dCUR;
};
struct cntrl_range_lay3 {
- __u16 wNumSubRanges;
- __u32 dMIN;
- __u32 dMAX;
- __u32 dRES;
+ __le16 wNumSubRanges;
+ __le32 dMIN;
+ __le32 dMAX;
+ __le32 dRES;
} __packed;
-static inline void
-free_ep(struct uac2_rtd_params *prm, struct usb_ep *ep)
-{
- struct snd_uac2_chip *uac2 = prm->uac2;
- int i;
-
- if (!prm->ep_enabled)
- return;
-
- prm->ep_enabled = false;
-
- for (i = 0; i < USB_XFERS; i++) {
- if (prm->ureq[i].req) {
- usb_ep_dequeue(ep, prm->ureq[i].req);
- usb_ep_free_request(ep, prm->ureq[i].req);
- prm->ureq[i].req = NULL;
- }
- }
-
- if (usb_ep_disable(ep))
- dev_err(&uac2->pdev.dev,
- "%s:%d Error!\n", __func__, __LINE__);
-}
-
static void set_ep_max_packet_size(const struct f_uac2_opts *uac2_opts,
struct usb_endpoint_descriptor *ep_desc,
unsigned int factor, bool is_playback)
@@ -986,15 +470,133 @@
le16_to_cpu(ep_desc->wMaxPacketSize)));
}
+/* Use macro to overcome line length limitation */
+#define USBDHDR(p) (struct usb_descriptor_header *)(p)
+
+static void setup_descriptor(struct f_uac2_opts *opts)
+{
+ /* patch descriptors */
+ int i = 1; /* ID's start with 1 */
+
+ if (EPOUT_EN(opts))
+ usb_out_it_desc.bTerminalID = i++;
+ if (EPIN_EN(opts))
+ io_in_it_desc.bTerminalID = i++;
+ if (EPOUT_EN(opts))
+ io_out_ot_desc.bTerminalID = i++;
+ if (EPIN_EN(opts))
+ usb_in_ot_desc.bTerminalID = i++;
+ if (EPOUT_EN(opts))
+ out_clk_src_desc.bClockID = i++;
+ if (EPIN_EN(opts))
+ in_clk_src_desc.bClockID = i++;
+
+ usb_out_it_desc.bCSourceID = out_clk_src_desc.bClockID;
+ usb_in_ot_desc.bSourceID = io_in_it_desc.bTerminalID;
+ usb_in_ot_desc.bCSourceID = in_clk_src_desc.bClockID;
+ io_in_it_desc.bCSourceID = in_clk_src_desc.bClockID;
+ io_out_ot_desc.bCSourceID = out_clk_src_desc.bClockID;
+ io_out_ot_desc.bSourceID = usb_out_it_desc.bTerminalID;
+ as_out_hdr_desc.bTerminalLink = usb_out_it_desc.bTerminalID;
+ as_in_hdr_desc.bTerminalLink = usb_in_ot_desc.bTerminalID;
+
+ iad_desc.bInterfaceCount = 1;
+ ac_hdr_desc.wTotalLength = 0;
+
+ if (EPIN_EN(opts)) {
+ u16 len = le16_to_cpu(ac_hdr_desc.wTotalLength);
+
+ len += sizeof(in_clk_src_desc);
+ len += sizeof(usb_in_ot_desc);
+ len += sizeof(io_in_it_desc);
+ ac_hdr_desc.wTotalLength = cpu_to_le16(len);
+ iad_desc.bInterfaceCount++;
+ }
+ if (EPOUT_EN(opts)) {
+ u16 len = le16_to_cpu(ac_hdr_desc.wTotalLength);
+
+ len += sizeof(out_clk_src_desc);
+ len += sizeof(usb_out_it_desc);
+ len += sizeof(io_out_ot_desc);
+ ac_hdr_desc.wTotalLength = cpu_to_le16(len);
+ iad_desc.bInterfaceCount++;
+ }
+
+ i = 0;
+ fs_audio_desc[i++] = USBDHDR(&iad_desc);
+ fs_audio_desc[i++] = USBDHDR(&std_ac_if_desc);
+ fs_audio_desc[i++] = USBDHDR(&ac_hdr_desc);
+ if (EPIN_EN(opts))
+ fs_audio_desc[i++] = USBDHDR(&in_clk_src_desc);
+ if (EPOUT_EN(opts)) {
+ fs_audio_desc[i++] = USBDHDR(&out_clk_src_desc);
+ fs_audio_desc[i++] = USBDHDR(&usb_out_it_desc);
+ }
+ if (EPIN_EN(opts)) {
+ fs_audio_desc[i++] = USBDHDR(&io_in_it_desc);
+ fs_audio_desc[i++] = USBDHDR(&usb_in_ot_desc);
+ }
+ if (EPOUT_EN(opts)) {
+ fs_audio_desc[i++] = USBDHDR(&io_out_ot_desc);
+ fs_audio_desc[i++] = USBDHDR(&std_as_out_if0_desc);
+ fs_audio_desc[i++] = USBDHDR(&std_as_out_if1_desc);
+ fs_audio_desc[i++] = USBDHDR(&as_out_hdr_desc);
+ fs_audio_desc[i++] = USBDHDR(&as_out_fmt1_desc);
+ fs_audio_desc[i++] = USBDHDR(&fs_epout_desc);
+ fs_audio_desc[i++] = USBDHDR(&as_iso_out_desc);
+ }
+ if (EPIN_EN(opts)) {
+ fs_audio_desc[i++] = USBDHDR(&std_as_in_if0_desc);
+ fs_audio_desc[i++] = USBDHDR(&std_as_in_if1_desc);
+ fs_audio_desc[i++] = USBDHDR(&as_in_hdr_desc);
+ fs_audio_desc[i++] = USBDHDR(&as_in_fmt1_desc);
+ fs_audio_desc[i++] = USBDHDR(&fs_epin_desc);
+ fs_audio_desc[i++] = USBDHDR(&as_iso_in_desc);
+ }
+ fs_audio_desc[i] = NULL;
+
+ i = 0;
+ hs_audio_desc[i++] = USBDHDR(&iad_desc);
+ hs_audio_desc[i++] = USBDHDR(&std_ac_if_desc);
+ hs_audio_desc[i++] = USBDHDR(&ac_hdr_desc);
+ if (EPIN_EN(opts))
+ hs_audio_desc[i++] = USBDHDR(&in_clk_src_desc);
+ if (EPOUT_EN(opts)) {
+ hs_audio_desc[i++] = USBDHDR(&out_clk_src_desc);
+ hs_audio_desc[i++] = USBDHDR(&usb_out_it_desc);
+ }
+ if (EPIN_EN(opts)) {
+ hs_audio_desc[i++] = USBDHDR(&io_in_it_desc);
+ hs_audio_desc[i++] = USBDHDR(&usb_in_ot_desc);
+ }
+ if (EPOUT_EN(opts)) {
+ hs_audio_desc[i++] = USBDHDR(&io_out_ot_desc);
+ hs_audio_desc[i++] = USBDHDR(&std_as_out_if0_desc);
+ hs_audio_desc[i++] = USBDHDR(&std_as_out_if1_desc);
+ hs_audio_desc[i++] = USBDHDR(&as_out_hdr_desc);
+ hs_audio_desc[i++] = USBDHDR(&as_out_fmt1_desc);
+ hs_audio_desc[i++] = USBDHDR(&hs_epout_desc);
+ hs_audio_desc[i++] = USBDHDR(&as_iso_out_desc);
+ }
+ if (EPIN_EN(opts)) {
+ hs_audio_desc[i++] = USBDHDR(&std_as_in_if0_desc);
+ hs_audio_desc[i++] = USBDHDR(&std_as_in_if1_desc);
+ hs_audio_desc[i++] = USBDHDR(&as_in_hdr_desc);
+ hs_audio_desc[i++] = USBDHDR(&as_in_fmt1_desc);
+ hs_audio_desc[i++] = USBDHDR(&hs_epin_desc);
+ hs_audio_desc[i++] = USBDHDR(&as_iso_in_desc);
+ }
+ hs_audio_desc[i] = NULL;
+}
+
static int
afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
{
- struct audio_dev *agdev = func_to_agdev(fn);
- struct snd_uac2_chip *uac2 = &agdev->uac2;
+ struct f_uac2 *uac2 = func_to_uac2(fn);
+ struct g_audio *agdev = func_to_g_audio(fn);
struct usb_composite_dev *cdev = cfg->cdev;
struct usb_gadget *gadget = cdev->gadget;
- struct device *dev = &uac2->pdev.dev;
- struct uac2_rtd_params *prm;
+ struct device *dev = &gadget->dev;
struct f_uac2_opts *uac2_opts;
struct usb_string *us;
int ret;
@@ -1040,100 +642,103 @@
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
return ret;
}
- std_ac_if_desc.bInterfaceNumber = ret;
- agdev->ac_intf = ret;
- agdev->ac_alt = 0;
+ iad_desc.bFirstInterface = ret;
- ret = usb_interface_id(cfg, fn);
- if (ret < 0) {
- dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
- return ret;
- }
- std_as_out_if0_desc.bInterfaceNumber = ret;
- std_as_out_if1_desc.bInterfaceNumber = ret;
- agdev->as_out_intf = ret;
- agdev->as_out_alt = 0;
-
- ret = usb_interface_id(cfg, fn);
- if (ret < 0) {
- dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
- return ret;
- }
- std_as_in_if0_desc.bInterfaceNumber = ret;
- std_as_in_if1_desc.bInterfaceNumber = ret;
- agdev->as_in_intf = ret;
- agdev->as_in_alt = 0;
+ std_ac_if_desc.bInterfaceNumber = ret;
+ uac2->ac_intf = ret;
+ uac2->ac_alt = 0;
- agdev->out_ep = usb_ep_autoconfig(gadget, &fs_epout_desc);
- if (!agdev->out_ep) {
- dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
- return ret;
+ if (EPOUT_EN(uac2_opts)) {
+ ret = usb_interface_id(cfg, fn);
+ if (ret < 0) {
+ dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
+ return ret;
+ }
+ std_as_out_if0_desc.bInterfaceNumber = ret;
+ std_as_out_if1_desc.bInterfaceNumber = ret;
+ uac2->as_out_intf = ret;
+ uac2->as_out_alt = 0;
}
- agdev->in_ep = usb_ep_autoconfig(gadget, &fs_epin_desc);
- if (!agdev->in_ep) {
- dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
- return ret;
+ if (EPIN_EN(uac2_opts)) {
+ ret = usb_interface_id(cfg, fn);
+ if (ret < 0) {
+ dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
+ return ret;
+ }
+ std_as_in_if0_desc.bInterfaceNumber = ret;
+ std_as_in_if1_desc.bInterfaceNumber = ret;
+ uac2->as_in_intf = ret;
+ uac2->as_in_alt = 0;
}
- uac2->p_prm.uac2 = uac2;
- uac2->c_prm.uac2 = uac2;
-
/* Calculate wMaxPacketSize according to audio bandwidth */
set_ep_max_packet_size(uac2_opts, &fs_epin_desc, 1000, true);
set_ep_max_packet_size(uac2_opts, &fs_epout_desc, 1000, false);
set_ep_max_packet_size(uac2_opts, &hs_epin_desc, 8000, true);
set_ep_max_packet_size(uac2_opts, &hs_epout_desc, 8000, false);
+ if (EPOUT_EN(uac2_opts)) {
+ agdev->out_ep = usb_ep_autoconfig(gadget, &fs_epout_desc);
+ if (!agdev->out_ep) {
+ dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
+ return -ENODEV;
+ }
+ }
+
+ if (EPIN_EN(uac2_opts)) {
+ agdev->in_ep = usb_ep_autoconfig(gadget, &fs_epin_desc);
+ if (!agdev->in_ep) {
+ dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
+ return -ENODEV;
+ }
+ }
+
+ agdev->in_ep_maxpsize = max_t(u16,
+ le16_to_cpu(fs_epin_desc.wMaxPacketSize),
+ le16_to_cpu(hs_epin_desc.wMaxPacketSize));
+ agdev->out_ep_maxpsize = max_t(u16,
+ le16_to_cpu(fs_epout_desc.wMaxPacketSize),
+ le16_to_cpu(hs_epout_desc.wMaxPacketSize));
+
hs_epout_desc.bEndpointAddress = fs_epout_desc.bEndpointAddress;
hs_epin_desc.bEndpointAddress = fs_epin_desc.bEndpointAddress;
+ setup_descriptor(uac2_opts);
+
ret = usb_assign_descriptors(fn, fs_audio_desc, hs_audio_desc, NULL,
NULL);
if (ret)
return ret;
- prm = &agdev->uac2.c_prm;
- prm->max_psize = hs_epout_desc.wMaxPacketSize;
- prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL);
- if (!prm->rbuf) {
- prm->max_psize = 0;
- goto err_free_descs;
- }
-
- prm = &agdev->uac2.p_prm;
- prm->max_psize = hs_epin_desc.wMaxPacketSize;
- prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL);
- if (!prm->rbuf) {
- prm->max_psize = 0;
- goto err;
- }
+ agdev->gadget = gadget;
- ret = alsa_uac2_init(agdev);
+ agdev->params.p_chmask = uac2_opts->p_chmask;
+ agdev->params.p_srate = uac2_opts->p_srate;
+ agdev->params.p_ssize = uac2_opts->p_ssize;
+ agdev->params.c_chmask = uac2_opts->c_chmask;
+ agdev->params.c_srate = uac2_opts->c_srate;
+ agdev->params.c_ssize = uac2_opts->c_ssize;
+ agdev->params.req_number = uac2_opts->req_number;
+ ret = g_audio_setup(agdev, "UAC2 PCM", "UAC2_Gadget");
if (ret)
- goto err;
+ goto err_free_descs;
return 0;
-err:
- kfree(agdev->uac2.p_prm.rbuf);
- kfree(agdev->uac2.c_prm.rbuf);
err_free_descs:
usb_free_all_descriptors(fn);
- return -EINVAL;
+ agdev->gadget = NULL;
+ return ret;
}
static int
afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt)
{
struct usb_composite_dev *cdev = fn->config->cdev;
- struct audio_dev *agdev = func_to_agdev(fn);
- struct snd_uac2_chip *uac2 = &agdev->uac2;
+ struct f_uac2 *uac2 = func_to_uac2(fn);
struct usb_gadget *gadget = cdev->gadget;
- struct device *dev = &uac2->pdev.dev;
- struct usb_request *req;
- struct usb_ep *ep;
- struct uac2_rtd_params *prm;
- int req_len, i;
+ struct device *dev = &gadget->dev;
+ int ret = 0;
/* No i/f has more than 2 alt settings */
if (alt > 1) {
@@ -1141,7 +746,7 @@
return -EINVAL;
}
- if (intf == agdev->ac_intf) {
+ if (intf == uac2->ac_intf) {
/* Control I/f has only 1 AltSetting - 0 */
if (alt) {
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
@@ -1150,96 +755,42 @@
return 0;
}
- if (intf == agdev->as_out_intf) {
- ep = agdev->out_ep;
- prm = &uac2->c_prm;
- config_ep_by_speed(gadget, fn, ep);
- agdev->as_out_alt = alt;
- req_len = prm->max_psize;
- } else if (intf == agdev->as_in_intf) {
- struct f_uac2_opts *opts = agdev_to_uac2_opts(agdev);
- unsigned int factor, rate;
- struct usb_endpoint_descriptor *ep_desc;
-
- ep = agdev->in_ep;
- prm = &uac2->p_prm;
- config_ep_by_speed(gadget, fn, ep);
- agdev->as_in_alt = alt;
-
- /* pre-calculate the playback endpoint's interval */
- if (gadget->speed == USB_SPEED_FULL) {
- ep_desc = &fs_epin_desc;
- factor = 1000;
- } else {
- ep_desc = &hs_epin_desc;
- factor = 8000;
- }
-
- /* pre-compute some values for iso_complete() */
- uac2->p_framesize = opts->p_ssize *
- num_channels(opts->p_chmask);
- rate = opts->p_srate * uac2->p_framesize;
- uac2->p_interval = factor / (1 << (ep_desc->bInterval - 1));
- uac2->p_pktsize = min_t(unsigned int, rate / uac2->p_interval,
- prm->max_psize);
+ if (intf == uac2->as_out_intf) {
+ uac2->as_out_alt = alt;
- if (uac2->p_pktsize < prm->max_psize)
- uac2->p_pktsize_residue = rate % uac2->p_interval;
+ if (alt)
+ ret = u_audio_start_capture(&uac2->g_audio);
else
- uac2->p_pktsize_residue = 0;
+ u_audio_stop_capture(&uac2->g_audio);
+ } else if (intf == uac2->as_in_intf) {
+ uac2->as_in_alt = alt;
- req_len = uac2->p_pktsize;
- uac2->p_residue = 0;
+ if (alt)
+ ret = u_audio_start_playback(&uac2->g_audio);
+ else
+ u_audio_stop_playback(&uac2->g_audio);
} else {
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
return -EINVAL;
}
- if (alt == 0) {
- free_ep(prm, ep);
- return 0;
- }
-
- prm->ep_enabled = true;
- usb_ep_enable(ep);
-
- for (i = 0; i < USB_XFERS; i++) {
- if (!prm->ureq[i].req) {
- req = usb_ep_alloc_request(ep, GFP_ATOMIC);
- if (req == NULL)
- return -ENOMEM;
-
- prm->ureq[i].req = req;
- prm->ureq[i].pp = prm;
-
- req->zero = 0;
- req->context = &prm->ureq[i];
- req->length = req_len;
- req->complete = agdev_iso_complete;
- req->buf = prm->rbuf + i * prm->max_psize;
- }
-
- if (usb_ep_queue(ep, prm->ureq[i].req, GFP_ATOMIC))
- dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
- }
-
- return 0;
+ return ret;
}
static int
afunc_get_alt(struct usb_function *fn, unsigned intf)
{
- struct audio_dev *agdev = func_to_agdev(fn);
- struct snd_uac2_chip *uac2 = &agdev->uac2;
+ struct f_uac2 *uac2 = func_to_uac2(fn);
+ struct g_audio *agdev = func_to_g_audio(fn);
- if (intf == agdev->ac_intf)
- return agdev->ac_alt;
- else if (intf == agdev->as_out_intf)
- return agdev->as_out_alt;
- else if (intf == agdev->as_in_intf)
- return agdev->as_in_alt;
+ if (intf == uac2->ac_intf)
+ return uac2->ac_alt;
+ else if (intf == uac2->as_out_intf)
+ return uac2->as_out_alt;
+ else if (intf == uac2->as_in_intf)
+ return uac2->as_in_alt;
else
- dev_err(&uac2->pdev.dev,
+ dev_err(&agdev->gadget->dev,
"%s:%d Invalid Interface %d!\n",
__func__, __LINE__, intf);
@@ -1249,22 +800,19 @@
static void
afunc_disable(struct usb_function *fn)
{
- struct audio_dev *agdev = func_to_agdev(fn);
- struct snd_uac2_chip *uac2 = &agdev->uac2;
-
- free_ep(&uac2->p_prm, agdev->in_ep);
- agdev->as_in_alt = 0;
+ struct f_uac2 *uac2 = func_to_uac2(fn);
- free_ep(&uac2->c_prm, agdev->out_ep);
- agdev->as_out_alt = 0;
+ uac2->as_in_alt = 0;
+ uac2->as_out_alt = 0;
+ u_audio_stop_capture(&uac2->g_audio);
+ u_audio_stop_playback(&uac2->g_audio);
}
static int
in_rq_cur(struct usb_function *fn, const struct usb_ctrlrequest *cr)
{
struct usb_request *req = fn->config->cdev->req;
- struct audio_dev *agdev = func_to_agdev(fn);
- struct snd_uac2_chip *uac2 = &agdev->uac2;
+ struct g_audio *agdev = func_to_g_audio(fn);
struct f_uac2_opts *opts;
u16 w_length = le16_to_cpu(cr->wLength);
u16 w_index = le16_to_cpu(cr->wIndex);
@@ -1274,7 +822,7 @@
int value = -EOPNOTSUPP;
int p_srate, c_srate;
- opts = agdev_to_uac2_opts(agdev);
+ opts = g_audio_to_uac2_opts(agdev);
p_srate = opts->p_srate;
c_srate = opts->c_srate;
@@ -1283,9 +831,9 @@
memset(&c, 0, sizeof(struct cntrl_cur_lay3));
if (entity_id == USB_IN_CLK_ID)
- c.dCUR = p_srate;
+ c.dCUR = cpu_to_le32(p_srate);
else if (entity_id == USB_OUT_CLK_ID)
- c.dCUR = c_srate;
+ c.dCUR = cpu_to_le32(c_srate);
value = min_t(unsigned, w_length, sizeof c);
memcpy(req->buf, &c, value);
@@ -1293,7 +841,7 @@
*(u8 *)req->buf = 1;
value = min_t(unsigned, w_length, 1);
} else {
- dev_err(&uac2->pdev.dev,
+ dev_err(&agdev->gadget->dev,
"%s:%d control_selector=%d TODO!\n",
__func__, __LINE__, control_selector);
}
@@ -1305,8 +853,7 @@
in_rq_range(struct usb_function *fn, const struct usb_ctrlrequest *cr)
{
struct usb_request *req = fn->config->cdev->req;
- struct audio_dev *agdev = func_to_agdev(fn);
- struct snd_uac2_chip *uac2 = &agdev->uac2;
+ struct g_audio *agdev = func_to_g_audio(fn);
struct f_uac2_opts *opts;
u16 w_length = le16_to_cpu(cr->wLength);
u16 w_index = le16_to_cpu(cr->wIndex);
@@ -1317,26 +864,26 @@
int value = -EOPNOTSUPP;
int p_srate, c_srate;
- opts = agdev_to_uac2_opts(agdev);
+ opts = g_audio_to_uac2_opts(agdev);
p_srate = opts->p_srate;
c_srate = opts->c_srate;
if (control_selector == UAC2_CS_CONTROL_SAM_FREQ) {
if (entity_id == USB_IN_CLK_ID)
- r.dMIN = p_srate;
+ r.dMIN = cpu_to_le32(p_srate);
else if (entity_id == USB_OUT_CLK_ID)
- r.dMIN = c_srate;
+ r.dMIN = cpu_to_le32(c_srate);
else
return -EOPNOTSUPP;
r.dMAX = r.dMIN;
r.dRES = 0;
- r.wNumSubRanges = 1;
+ r.wNumSubRanges = cpu_to_le16(1);
value = min_t(unsigned, w_length, sizeof r);
memcpy(req->buf, &r, value);
} else {
- dev_err(&uac2->pdev.dev,
+ dev_err(&agdev->gadget->dev,
"%s:%d control_selector=%d TODO!\n",
__func__, __LINE__, control_selector);
}
@@ -1371,13 +918,13 @@
static int
setup_rq_inf(struct usb_function *fn, const struct usb_ctrlrequest *cr)
{
- struct audio_dev *agdev = func_to_agdev(fn);
- struct snd_uac2_chip *uac2 = &agdev->uac2;
+ struct f_uac2 *uac2 = func_to_uac2(fn);
+ struct g_audio *agdev = func_to_g_audio(fn);
u16 w_index = le16_to_cpu(cr->wIndex);
u8 intf = w_index & 0xff;
- if (intf != agdev->ac_intf) {
- dev_err(&uac2->pdev.dev,
+ if (intf != uac2->ac_intf) {
+ dev_err(&agdev->gadget->dev,
"%s:%d Error!\n", __func__, __LINE__);
return -EOPNOTSUPP;
}
@@ -1394,8 +941,7 @@
afunc_setup(struct usb_function *fn, const struct usb_ctrlrequest *cr)
{
struct usb_composite_dev *cdev = fn->config->cdev;
- struct audio_dev *agdev = func_to_agdev(fn);
- struct snd_uac2_chip *uac2 = &agdev->uac2;
+ struct g_audio *agdev = func_to_g_audio(fn);
struct usb_request *req = cdev->req;
u16 w_length = le16_to_cpu(cr->wLength);
int value = -EOPNOTSUPP;
@@ -1407,14 +953,15 @@
if ((cr->bRequestType & USB_RECIP_MASK) == USB_RECIP_INTERFACE)
value = setup_rq_inf(fn, cr);
else
- dev_err(&uac2->pdev.dev, "%s:%d Error!\n", __func__, __LINE__);
+ dev_err(&agdev->gadget->dev, "%s:%d Error!\n",
+ __func__, __LINE__);
if (value >= 0) {
req->length = value;
req->zero = value < w_length;
value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
if (value < 0) {
- dev_err(&uac2->pdev.dev,
+ dev_err(&agdev->gadget->dev,
"%s:%d Error!\n", __func__, __LINE__);
req->status = 0;
}
@@ -1487,6 +1034,7 @@
UAC2_ATTRIBUTE(c_chmask);
UAC2_ATTRIBUTE(c_srate);
UAC2_ATTRIBUTE(c_ssize);
+UAC2_ATTRIBUTE(req_number);
static struct configfs_attribute *f_uac2_attrs[] = {
&f_uac2_opts_attr_p_chmask,
@@ -1495,6 +1043,7 @@
&f_uac2_opts_attr_c_chmask,
&f_uac2_opts_attr_c_srate,
&f_uac2_opts_attr_c_ssize,
+ &f_uac2_opts_attr_req_number,
NULL,
};
@@ -1532,15 +1081,16 @@
opts->c_chmask = UAC2_DEF_CCHMASK;
opts->c_srate = UAC2_DEF_CSRATE;
opts->c_ssize = UAC2_DEF_CSSIZE;
+ opts->req_number = UAC2_DEF_REQ_NUM;
return &opts->func_inst;
}
static void afunc_free(struct usb_function *f)
{
- struct audio_dev *agdev;
+ struct g_audio *agdev;
struct f_uac2_opts *opts;
- agdev = func_to_agdev(f);
+ agdev = func_to_g_audio(f);
opts = container_of(f->fi, struct f_uac2_opts, func_inst);
kfree(agdev);
mutex_lock(&opts->lock);
@@ -1550,26 +1100,21 @@
static void afunc_unbind(struct usb_configuration *c, struct usb_function *f)
{
- struct audio_dev *agdev = func_to_agdev(f);
- struct uac2_rtd_params *prm;
+ struct g_audio *agdev = func_to_g_audio(f);
- alsa_uac2_exit(agdev);
-
- prm = &agdev->uac2.p_prm;
- kfree(prm->rbuf);
-
- prm = &agdev->uac2.c_prm;
- kfree(prm->rbuf);
+ g_audio_cleanup(agdev);
usb_free_all_descriptors(f);
+
+ agdev->gadget = NULL;
}
static struct usb_function *afunc_alloc(struct usb_function_instance *fi)
{
- struct audio_dev *agdev;
+ struct f_uac2 *uac2;
struct f_uac2_opts *opts;
- agdev = kzalloc(sizeof(*agdev), GFP_KERNEL);
- if (agdev == NULL)
+ uac2 = kzalloc(sizeof(*uac2), GFP_KERNEL);
+ if (uac2 == NULL)
return ERR_PTR(-ENOMEM);
opts = container_of(fi, struct f_uac2_opts, func_inst);
@@ -1577,16 +1122,16 @@
++opts->refcnt;
mutex_unlock(&opts->lock);
- agdev->func.name = "uac2_func";
- agdev->func.bind = afunc_bind;
- agdev->func.unbind = afunc_unbind;
- agdev->func.set_alt = afunc_set_alt;
- agdev->func.get_alt = afunc_get_alt;
- agdev->func.disable = afunc_disable;
- agdev->func.setup = afunc_setup;
- agdev->func.free_func = afunc_free;
+ uac2->g_audio.func.name = "uac2_func";
+ uac2->g_audio.func.bind = afunc_bind;
+ uac2->g_audio.func.unbind = afunc_unbind;
+ uac2->g_audio.func.set_alt = afunc_set_alt;
+ uac2->g_audio.func.get_alt = afunc_get_alt;
+ uac2->g_audio.func.disable = afunc_disable;
+ uac2->g_audio.func.setup = afunc_setup;
+ uac2->g_audio.func.free_func = afunc_free;
- return &agdev->func;
+ return &uac2->g_audio.func;
}
DECLARE_USB_FUNCTION_INIT(uac2, afunc_alloc_inst, afunc_alloc);
diff -urN linux-4.9.37/drivers/usb/gadget/function/f_uvc.c linux-4.9.y/drivers/usb/gadget/function/f_uvc.c
--- linux-4.9.37/drivers/usb/gadget/function/f_uvc.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/gadget/function/f_uvc.c 2021-06-07 13:01:34.000000000 +0300
@@ -594,6 +594,14 @@
opts->streaming_maxpacket = clamp(opts->streaming_maxpacket, 1U, 3072U);
opts->streaming_maxburst = min(opts->streaming_maxburst, 15U);
+ /* For SS, wMaxPacketSize has to be 1024 if bMaxBurst is not 0 */
+ if (opts->streaming_maxburst &&
+ (opts->streaming_maxpacket % 1024) != 0) {
+ opts->streaming_maxpacket = roundup(opts->streaming_maxpacket, 1024);
+ INFO(cdev, "overriding streaming_maxpacket to %d\n",
+ opts->streaming_maxpacket);
+ }
+
/* Fill in the FS/HS/SS Video Streaming specific descriptors from the
* module parameters.
*
@@ -621,7 +629,7 @@
uvc_ss_streaming_ep.wMaxPacketSize = cpu_to_le16(max_packet_size);
uvc_ss_streaming_ep.bInterval = opts->streaming_interval;
- uvc_ss_streaming_comp.bmAttributes = max_packet_mult - 1;
+ uvc_ss_streaming_comp.bmAttributes = 1;
uvc_ss_streaming_comp.bMaxBurst = opts->streaming_maxburst;
uvc_ss_streaming_comp.wBytesPerInterval =
cpu_to_le16(max_packet_size * max_packet_mult *
@@ -720,7 +728,7 @@
}
/* Initialise video. */
- ret = uvcg_video_init(&uvc->video);
+ ret = uvcg_video_init(&uvc->video, uvc);
if (ret < 0)
goto error;
@@ -765,6 +773,11 @@
struct uvc_color_matching_descriptor *md;
struct uvc_descriptor_header **ctl_cls;
+ struct UVC_EXTENSION_UNIT_DESCRIPTOR(1, 2) *ed;
+ /* GUID of the UVC H.264 extension unit */
+ static char extension_guid[] = {0x41, 0x76, 0x9E, 0xA2, 0x04, 0xDE, 0xE3, 0x47,
+ 0x8B, 0x2B, 0xF4, 0x34, 0x1A, 0xFF, 0x00, 0x3B};
+
opts = kzalloc(sizeof(*opts), GFP_KERNEL);
if (!opts)
return ERR_PTR(-ENOMEM);
@@ -799,6 +812,20 @@
pd->bmControls[1] = 0;
pd->iProcessing = 0;
+ ed = &opts->uvc_extension;
+ ed->bLength = UVC_DT_EXTENSION_UNIT_SIZE(1, 2);
+ ed->bDescriptorType = USB_DT_CS_INTERFACE;
+ ed->bDescriptorSubType = UVC_VC_EXTENSION_UNIT;
+ ed->bUnitID = 10;
+ memcpy(ed->guidExtensionCode, extension_guid, sizeof(extension_guid));
+ ed->bNrInPins = 1;
+ ed->baSourceID[0] = 2;
+ ed->bNumControls = 15;
+ ed->bControlSize = 2;
+ ed->bmControls[0] = 1;
+ ed->bmControls[1] = 0;
+ ed->iExtension = 0;
+
od = &opts->uvc_output_terminal;
od->bLength = UVC_DT_OUTPUT_TERMINAL_SIZE;
od->bDescriptorType = USB_DT_CS_INTERFACE;
@@ -822,8 +849,9 @@
ctl_cls[0] = NULL; /* assigned elsewhere by configfs */
ctl_cls[1] = (struct uvc_descriptor_header *)cd;
ctl_cls[2] = (struct uvc_descriptor_header *)pd;
- ctl_cls[3] = (struct uvc_descriptor_header *)od;
- ctl_cls[4] = NULL; /* NULL-terminate */
+ ctl_cls[3] = (struct uvc_descriptor_header *)ed;
+ ctl_cls[4] = (struct uvc_descriptor_header *)od;
+ ctl_cls[5] = NULL; /* NULL-terminate */
opts->fs_control =
(const struct uvc_descriptor_header * const *)ctl_cls;
@@ -832,13 +860,15 @@
ctl_cls[0] = NULL; /* assigned elsewhere by configfs */
ctl_cls[1] = (struct uvc_descriptor_header *)cd;
ctl_cls[2] = (struct uvc_descriptor_header *)pd;
- ctl_cls[3] = (struct uvc_descriptor_header *)od;
- ctl_cls[4] = NULL; /* NULL-terminate */
+ ctl_cls[3] = (struct uvc_descriptor_header *)ed;
+ ctl_cls[4] = (struct uvc_descriptor_header *)od;
+ ctl_cls[5] = NULL; /* NULL-terminate */
opts->ss_control =
(const struct uvc_descriptor_header * const *)ctl_cls;
opts->streaming_interval = 1;
- opts->streaming_maxpacket = 1024;
+ opts->streaming_maxpacket = 3072;
+ opts->streaming_maxburst = 15;
uvcg_attach_configfs(opts);
return &opts->func_inst;
diff -urN linux-4.9.37/drivers/usb/gadget/function/Makefile linux-4.9.y/drivers/usb/gadget/function/Makefile
--- linux-4.9.37/drivers/usb/gadget/function/Makefile 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/gadget/function/Makefile 2021-06-07 13:01:34.000000000 +0300
@@ -32,8 +32,11 @@
obj-$(CONFIG_USB_F_MASS_STORAGE)+= usb_f_mass_storage.o
usb_f_fs-y := f_fs.o
obj-$(CONFIG_USB_F_FS) += usb_f_fs.o
-usb_f_uac1-y := f_uac1.o u_uac1.o
+obj-$(CONFIG_USB_U_AUDIO) += u_audio.o
+usb_f_uac1-y := f_uac1.o
obj-$(CONFIG_USB_F_UAC1) += usb_f_uac1.o
+usb_f_uac1_legacy-y := f_uac1_legacy.o u_uac1_legacy.o
+obj-$(CONFIG_USB_F_UAC1_LEGACY) += usb_f_uac1_legacy.o
usb_f_uac2-y := f_uac2.o
obj-$(CONFIG_USB_F_UAC2) += usb_f_uac2.o
usb_f_uvc-y := f_uvc.o uvc_queue.o uvc_v4l2.o uvc_video.o uvc_configfs.o
diff -urN linux-4.9.37/drivers/usb/gadget/function/u_audio.c linux-4.9.y/drivers/usb/gadget/function/u_audio.c
--- linux-4.9.37/drivers/usb/gadget/function/u_audio.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/usb/gadget/function/u_audio.c 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,628 @@
+/*
+ * ALSA audio utilities for Gadget stack
+ *
+ * Copyright (C) 2008 Bryan Wu <cooloney@kernel.org>
+ * Copyright (C) 2008 Analog Devices, Inc
+ *
+ * Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/module.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+
+#include "u_audio.h"
+
+#define BUFF_SIZE_MAX (PAGE_SIZE * 16)
+#define PRD_SIZE_MAX PAGE_SIZE
+#define MIN_PERIODS 4
+
+struct uac_req {
+ struct uac_rtd_params *pp; /* parent param */
+ struct usb_request *req;
+};
+
+/* Runtime data params for one stream */
+struct uac_rtd_params {
+ struct snd_uac_chip *uac; /* parent chip */
+ bool ep_enabled; /* if the ep is enabled */
+
+ struct snd_pcm_substream *ss;
+
+ /* Ring buffer */
+ ssize_t hw_ptr;
+
+ void *rbuf;
+
+ unsigned max_psize; /* MaxPacketSize of endpoint */
+ struct uac_req *ureq;
+
+ spinlock_t lock;
+};
+
+struct snd_uac_chip {
+ struct g_audio *audio_dev;
+
+ struct uac_rtd_params p_prm;
+ struct uac_rtd_params c_prm;
+
+ struct snd_card *card;
+ struct snd_pcm *pcm;
+
+ /* timekeeping for the playback endpoint */
+ unsigned int p_interval;
+ unsigned int p_residue;
+
+ /* pre-calculated values for playback iso completion */
+ unsigned int p_pktsize;
+ unsigned int p_pktsize_residue;
+ unsigned int p_framesize;
+};
+
+static const struct snd_pcm_hardware uac_pcm_hardware = {
+ .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER
+ | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID
+ | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
+ .rates = SNDRV_PCM_RATE_CONTINUOUS,
+ .periods_max = BUFF_SIZE_MAX / PRD_SIZE_MAX,
+ .buffer_bytes_max = BUFF_SIZE_MAX,
+ .period_bytes_max = PRD_SIZE_MAX,
+ .periods_min = MIN_PERIODS,
+};
+
+static void u_audio_iso_complete(struct usb_ep *ep, struct usb_request *req)
+{
+ unsigned pending;
+ unsigned long flags, flags2;
+ unsigned int hw_ptr;
+ int status = req->status;
+ struct uac_req *ur = req->context;
+ struct snd_pcm_substream *substream;
+ struct snd_pcm_runtime *runtime;
+ struct uac_rtd_params *prm = ur->pp;
+ struct snd_uac_chip *uac = prm->uac;
+
+ /* i/f shutting down */
+ if (!prm->ep_enabled || req->status == -ESHUTDOWN)
+ return;
+
+ /*
+ * We can't really do much about bad xfers.
+ * Afterall, the ISOCH xfers could fail legitimately.
+ */
+ if (status)
+ pr_debug("%s: iso_complete status(%d) %d/%d\n",
+ __func__, status, req->actual, req->length);
+
+ substream = prm->ss;
+
+ /* Do nothing if ALSA isn't active */
+ if (!substream)
+ goto exit;
+
+ snd_pcm_stream_lock_irqsave(substream, flags2);
+
+ runtime = substream->runtime;
+ if (!runtime || !snd_pcm_running(substream)) {
+ snd_pcm_stream_unlock_irqrestore(substream, flags2);
+ goto exit;
+ }
+
+ spin_lock_irqsave(&prm->lock, flags);
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ /*
+ * For each IN packet, take the quotient of the current data
+ * rate and the endpoint's interval as the base packet size.
+ * If there is a residue from this division, add it to the
+ * residue accumulator.
+ */
+ req->length = uac->p_pktsize;
+ uac->p_residue += uac->p_pktsize_residue;
+
+ /*
+ * Whenever there are more bytes in the accumulator than we
+ * need to add one more sample frame, increase this packet's
+ * size and decrease the accumulator.
+ */
+ if (uac->p_residue / uac->p_interval >= uac->p_framesize) {
+ req->length += uac->p_framesize;
+ uac->p_residue -= uac->p_framesize *
+ uac->p_interval;
+ }
+
+ req->actual = req->length;
+ }
+
+ hw_ptr = prm->hw_ptr;
+
+ spin_unlock_irqrestore(&prm->lock, flags);
+
+ /* Pack USB load in ALSA ring buffer */
+ pending = runtime->dma_bytes - hw_ptr;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ if (unlikely(pending < req->actual)) {
+ memcpy(req->buf, runtime->dma_area + hw_ptr, pending);
+ memcpy(req->buf + pending, runtime->dma_area,
+ req->actual - pending);
+ } else {
+ memcpy(req->buf, runtime->dma_area + hw_ptr,
+ req->actual);
+ }
+ } else {
+ if (unlikely(pending < req->actual)) {
+ memcpy(runtime->dma_area + hw_ptr, req->buf, pending);
+ memcpy(runtime->dma_area, req->buf + pending,
+ req->actual - pending);
+ } else {
+ memcpy(runtime->dma_area + hw_ptr, req->buf,
+ req->actual);
+ }
+ }
+
+ spin_lock_irqsave(&prm->lock, flags);
+ /* update hw_ptr after data is copied to memory */
+ prm->hw_ptr = (hw_ptr + req->actual) % runtime->dma_bytes;
+ hw_ptr = prm->hw_ptr;
+ spin_unlock_irqrestore(&prm->lock, flags);
+ snd_pcm_stream_unlock_irqrestore(substream, flags2);
+
+ if ((hw_ptr % snd_pcm_lib_period_bytes(substream)) < req->actual)
+ snd_pcm_period_elapsed(substream);
+
+exit:
+ if (usb_ep_queue(ep, req, GFP_ATOMIC))
+ dev_err(uac->card->dev, "%d Error!\n", __LINE__);
+}
+
+static int uac_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ struct snd_uac_chip *uac = snd_pcm_substream_chip(substream);
+ struct uac_rtd_params *prm;
+ struct g_audio *audio_dev;
+ struct uac_params *params;
+ unsigned long flags;
+ int err = 0;
+
+ audio_dev = uac->audio_dev;
+ params = &audio_dev->params;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ prm = &uac->p_prm;
+ else
+ prm = &uac->c_prm;
+
+ spin_lock_irqsave(&prm->lock, flags);
+
+ /* Reset */
+ prm->hw_ptr = 0;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ prm->ss = substream;
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ prm->ss = NULL;
+ break;
+ default:
+ err = -EINVAL;
+ }
+
+ spin_unlock_irqrestore(&prm->lock, flags);
+
+ /* Clear buffer after Play stops */
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && !prm->ss)
+ memset(prm->rbuf, 0, prm->max_psize * params->req_number);
+
+ return err;
+}
+
+static snd_pcm_uframes_t uac_pcm_pointer(struct snd_pcm_substream *substream)
+{
+ struct snd_uac_chip *uac = snd_pcm_substream_chip(substream);
+ struct uac_rtd_params *prm;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ prm = &uac->p_prm;
+ else
+ prm = &uac->c_prm;
+
+ return bytes_to_frames(substream->runtime, prm->hw_ptr);
+}
+
+static int uac_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
+{
+ return snd_pcm_lib_malloc_pages(substream,
+ params_buffer_bytes(hw_params));
+}
+
+static int uac_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+ return snd_pcm_lib_free_pages(substream);
+}
+
+static int uac_pcm_open(struct snd_pcm_substream *substream)
+{
+ struct snd_uac_chip *uac = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct g_audio *audio_dev;
+ struct uac_params *params;
+ int p_ssize, c_ssize;
+ int p_srate, c_srate;
+ int p_chmask, c_chmask;
+
+ audio_dev = uac->audio_dev;
+ params = &audio_dev->params;
+ p_ssize = params->p_ssize;
+ c_ssize = params->c_ssize;
+ p_srate = params->p_srate;
+ c_srate = params->c_srate;
+ p_chmask = params->p_chmask;
+ c_chmask = params->c_chmask;
+ uac->p_residue = 0;
+
+ runtime->hw = uac_pcm_hardware;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ spin_lock_init(&uac->p_prm.lock);
+ runtime->hw.rate_min = p_srate;
+ switch (p_ssize) {
+ case 3:
+ runtime->hw.formats = SNDRV_PCM_FMTBIT_S24_3LE;
+ break;
+ case 4:
+ runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE;
+ break;
+ default:
+ runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
+ break;
+ }
+ runtime->hw.channels_min = num_channels(p_chmask);
+ runtime->hw.period_bytes_min = 2 * uac->p_prm.max_psize
+ / runtime->hw.periods_min;
+ } else {
+ spin_lock_init(&uac->c_prm.lock);
+ runtime->hw.rate_min = c_srate;
+ switch (c_ssize) {
+ case 3:
+ runtime->hw.formats = SNDRV_PCM_FMTBIT_S24_3LE;
+ break;
+ case 4:
+ runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE;
+ break;
+ default:
+ runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE;
+ break;
+ }
+ runtime->hw.channels_min = num_channels(c_chmask);
+ runtime->hw.period_bytes_min = 2 * uac->c_prm.max_psize
+ / runtime->hw.periods_min;
+ }
+
+ runtime->hw.rate_max = runtime->hw.rate_min;
+ runtime->hw.channels_max = runtime->hw.channels_min;
+
+ snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+
+ return 0;
+}
+
+/* ALSA cries without these function pointers */
+static int uac_pcm_null(struct snd_pcm_substream *substream)
+{
+ return 0;
+}
+
+static const struct snd_pcm_ops uac_pcm_ops = {
+ .open = uac_pcm_open,
+ .close = uac_pcm_null,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = uac_pcm_hw_params,
+ .hw_free = uac_pcm_hw_free,
+ .trigger = uac_pcm_trigger,
+ .pointer = uac_pcm_pointer,
+ .prepare = uac_pcm_null,
+};
+
+static inline void free_ep(struct uac_rtd_params *prm, struct usb_ep *ep)
+{
+ struct snd_uac_chip *uac = prm->uac;
+ struct g_audio *audio_dev;
+ struct uac_params *params;
+ int i;
+
+ if (!prm->ep_enabled)
+ return;
+
+ prm->ep_enabled = false;
+
+ audio_dev = uac->audio_dev;
+ params = &audio_dev->params;
+
+ for (i = 0; i < params->req_number; i++) {
+ if (prm->ureq[i].req) {
+ usb_ep_dequeue(ep, prm->ureq[i].req);
+ usb_ep_free_request(ep, prm->ureq[i].req);
+ prm->ureq[i].req = NULL;
+ }
+ }
+
+ if (usb_ep_disable(ep))
+ dev_err(uac->card->dev, "%s:%d Error!\n", __func__, __LINE__);
+}
+
+
+int u_audio_start_capture(struct g_audio *audio_dev)
+{
+ struct snd_uac_chip *uac = audio_dev->uac;
+ struct usb_gadget *gadget = audio_dev->gadget;
+ struct device *dev = &gadget->dev;
+ struct usb_request *req;
+ struct usb_ep *ep;
+ struct uac_rtd_params *prm;
+ struct uac_params *params = &audio_dev->params;
+ int req_len, i;
+
+ ep = audio_dev->out_ep;
+ prm = &uac->c_prm;
+ config_ep_by_speed(gadget, &audio_dev->func, ep);
+ req_len = prm->max_psize;
+
+ prm->ep_enabled = true;
+ usb_ep_enable(ep);
+
+ for (i = 0; i < params->req_number; i++) {
+ if (!prm->ureq[i].req) {
+ req = usb_ep_alloc_request(ep, GFP_ATOMIC);
+ if (req == NULL)
+ return -ENOMEM;
+
+ prm->ureq[i].req = req;
+ prm->ureq[i].pp = prm;
+
+ req->zero = 0;
+ req->context = &prm->ureq[i];
+ req->length = req_len;
+ req->complete = u_audio_iso_complete;
+ req->buf = prm->rbuf + i * prm->max_psize;
+ }
+
+ if (usb_ep_queue(ep, prm->ureq[i].req, GFP_ATOMIC))
+ dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(u_audio_start_capture);
+
+void u_audio_stop_capture(struct g_audio *audio_dev)
+{
+ struct snd_uac_chip *uac = audio_dev->uac;
+
+ free_ep(&uac->c_prm, audio_dev->out_ep);
+}
+EXPORT_SYMBOL_GPL(u_audio_stop_capture);
+
+int u_audio_start_playback(struct g_audio *audio_dev)
+{
+ struct snd_uac_chip *uac = audio_dev->uac;
+ struct usb_gadget *gadget = audio_dev->gadget;
+ struct device *dev = &gadget->dev;
+ struct usb_request *req;
+ struct usb_ep *ep;
+ struct uac_rtd_params *prm;
+ struct uac_params *params = &audio_dev->params;
+ unsigned int factor, rate;
+ const struct usb_endpoint_descriptor *ep_desc;
+ int req_len, i;
+
+ ep = audio_dev->in_ep;
+ prm = &uac->p_prm;
+ config_ep_by_speed(gadget, &audio_dev->func, ep);
+
+ ep_desc = ep->desc;
+
+ /* pre-calculate the playback endpoint's interval */
+ if (gadget->speed == USB_SPEED_FULL)
+ factor = 1000;
+ else
+ factor = 8000;
+
+ /* pre-compute some values for iso_complete() */
+ uac->p_framesize = params->p_ssize *
+ num_channels(params->p_chmask);
+ rate = params->p_srate * uac->p_framesize;
+ uac->p_interval = factor / (1 << (ep_desc->bInterval - 1));
+ uac->p_pktsize = min_t(unsigned int, rate / uac->p_interval,
+ prm->max_psize);
+
+ if (uac->p_pktsize < prm->max_psize)
+ uac->p_pktsize_residue = rate % uac->p_interval;
+ else
+ uac->p_pktsize_residue = 0;
+
+ req_len = uac->p_pktsize;
+ uac->p_residue = 0;
+
+ prm->ep_enabled = true;
+ usb_ep_enable(ep);
+
+ for (i = 0; i < params->req_number; i++) {
+ if (!prm->ureq[i].req) {
+ req = usb_ep_alloc_request(ep, GFP_ATOMIC);
+ if (req == NULL)
+ return -ENOMEM;
+
+ prm->ureq[i].req = req;
+ prm->ureq[i].pp = prm;
+
+ req->zero = 0;
+ req->context = &prm->ureq[i];
+ req->length = req_len;
+ req->complete = u_audio_iso_complete;
+ req->buf = prm->rbuf + i * prm->max_psize;
+ }
+
+ if (usb_ep_queue(ep, prm->ureq[i].req, GFP_ATOMIC))
+ dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(u_audio_start_playback);
+
+void u_audio_stop_playback(struct g_audio *audio_dev)
+{
+ struct snd_uac_chip *uac = audio_dev->uac;
+
+ free_ep(&uac->p_prm, audio_dev->in_ep);
+}
+EXPORT_SYMBOL_GPL(u_audio_stop_playback);
+
+int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
+ const char *card_name)
+{
+ struct snd_uac_chip *uac;
+ struct snd_card *card;
+ struct snd_pcm *pcm;
+ struct uac_params *params;
+ int p_chmask, c_chmask;
+ int err;
+
+ if (!g_audio)
+ return -EINVAL;
+
+ uac = kzalloc(sizeof(*uac), GFP_KERNEL);
+ if (!uac)
+ return -ENOMEM;
+ g_audio->uac = uac;
+ uac->audio_dev = g_audio;
+
+ params = &g_audio->params;
+ p_chmask = params->p_chmask;
+ c_chmask = params->c_chmask;
+
+ if (c_chmask) {
+ struct uac_rtd_params *prm = &uac->c_prm;
+
+ uac->c_prm.uac = uac;
+ prm->max_psize = g_audio->out_ep_maxpsize;
+
+ prm->ureq = kcalloc(params->req_number, sizeof(struct uac_req),
+ GFP_KERNEL);
+ if (!prm->ureq) {
+ err = -ENOMEM;
+ goto fail;
+ }
+
+ prm->rbuf = kcalloc(params->req_number, prm->max_psize,
+ GFP_KERNEL);
+ if (!prm->rbuf) {
+ prm->max_psize = 0;
+ err = -ENOMEM;
+ goto fail;
+ }
+ }
+
+ if (p_chmask) {
+ struct uac_rtd_params *prm = &uac->p_prm;
+
+ uac->p_prm.uac = uac;
+ prm->max_psize = g_audio->in_ep_maxpsize;
+
+ prm->ureq = kcalloc(params->req_number, sizeof(struct uac_req),
+ GFP_KERNEL);
+ if (!prm->ureq) {
+ err = -ENOMEM;
+ goto fail;
+ }
+
+ prm->rbuf = kcalloc(params->req_number, prm->max_psize,
+ GFP_KERNEL);
+ if (!prm->rbuf) {
+ prm->max_psize = 0;
+ err = -ENOMEM;
+ goto fail;
+ }
+ }
+
+ /* Choose any slot, with no id */
+ err = snd_card_new(&g_audio->gadget->dev,
+ -1, NULL, THIS_MODULE, 0, &card);
+ if (err < 0)
+ goto fail;
+
+ uac->card = card;
+
+ /*
+ * Create first PCM device
+ * Create a substream only for non-zero channel streams
+ */
+ err = snd_pcm_new(uac->card, pcm_name, 0,
+ p_chmask ? 1 : 0, c_chmask ? 1 : 0, &pcm);
+ if (err < 0)
+ goto snd_fail;
+
+ strlcpy(pcm->name, pcm_name, sizeof(pcm->name));
+ pcm->private_data = uac;
+ uac->pcm = pcm;
+
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &uac_pcm_ops);
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &uac_pcm_ops);
+
+ strlcpy(card->driver, card_name, sizeof(card->driver));
+ strlcpy(card->shortname, card_name, sizeof(card->shortname));
+ sprintf(card->longname, "%s %i", card_name, card->dev->id);
+
+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
+ snd_dma_continuous_data(GFP_KERNEL), 0, BUFF_SIZE_MAX);
+
+ err = snd_card_register(card);
+
+ if (!err)
+ return 0;
+
+snd_fail:
+ snd_card_free(card);
+fail:
+ kfree(uac->p_prm.ureq);
+ kfree(uac->c_prm.ureq);
+ kfree(uac->p_prm.rbuf);
+ kfree(uac->c_prm.rbuf);
+ kfree(uac);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(g_audio_setup);
+
+void g_audio_cleanup(struct g_audio *g_audio)
+{
+ struct snd_uac_chip *uac;
+ struct snd_card *card;
+
+ if (!g_audio || !g_audio->uac)
+ return;
+
+ uac = g_audio->uac;
+ card = uac->card;
+ if (card)
+ snd_card_free(card);
+
+ kfree(uac->p_prm.ureq);
+ kfree(uac->c_prm.ureq);
+ kfree(uac->p_prm.rbuf);
+ kfree(uac->c_prm.rbuf);
+ kfree(uac);
+}
+EXPORT_SYMBOL_GPL(g_audio_cleanup);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("USB gadget \"ALSA sound card\" utilities");
+MODULE_AUTHOR("Ruslan Bilovol");
diff -urN linux-4.9.37/drivers/usb/gadget/function/u_audio.h linux-4.9.y/drivers/usb/gadget/function/u_audio.h
--- linux-4.9.37/drivers/usb/gadget/function/u_audio.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/usb/gadget/function/u_audio.h 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,88 @@
+/*
+ * ALSA audio utilities for Gadget stack
+ *
+ * Copyright (C) 2008 Bryan Wu <cooloney@kernel.org>
+ * Copyright (C) 2008 Analog Devices, Inc
+ *
+ * Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __U_AUDIO_H
+#define __U_AUDIO_H
+
+#include <linux/usb/composite.h>
+
+struct uac_params {
+ /* playback */
+ int p_chmask; /* channel mask */
+ int p_srate; /* rate in Hz */
+ int p_ssize; /* sample size */
+
+ /* capture */
+ int c_chmask; /* channel mask */
+ int c_srate; /* rate in Hz */
+ int c_ssize; /* sample size */
+
+ int req_number; /* number of preallocated requests */
+};
+
+struct g_audio {
+ struct usb_function func;
+ struct usb_gadget *gadget;
+
+ struct usb_ep *in_ep;
+ struct usb_ep *out_ep;
+
+ /* Max packet size for all in_ep possible speeds */
+ unsigned int in_ep_maxpsize;
+ /* Max packet size for all out_ep possible speeds */
+ unsigned int out_ep_maxpsize;
+
+ /* The ALSA Sound Card it represents on the USB-Client side */
+ struct snd_uac_chip *uac;
+
+ struct uac_params params;
+};
+
+static inline struct g_audio *func_to_g_audio(struct usb_function *f)
+{
+ return container_of(f, struct g_audio, func);
+}
+
+static inline uint num_channels(uint chanmask)
+{
+ uint num = 0;
+
+ while (chanmask) {
+ num += (chanmask & 1);
+ chanmask >>= 1;
+ }
+
+ return num;
+}
+
+/*
+ * g_audio_setup - initialize one virtual ALSA sound card
+ * @g_audio: struct with filled params, in_ep_maxpsize, out_ep_maxpsize
+ * @pcm_name: the id string for a PCM instance of this sound card
+ * @card_name: name of this soundcard
+ *
+ * This sets up the single virtual ALSA sound card that may be exported by a
+ * gadget driver using this framework.
+ *
+ * Context: may sleep
+ *
+ * Returns zero on success, or a negative error on failure.
+ */
+int g_audio_setup(struct g_audio *g_audio, const char *pcm_name,
+ const char *card_name);
+void g_audio_cleanup(struct g_audio *g_audio);
+
+int u_audio_start_capture(struct g_audio *g_audio);
+void u_audio_stop_capture(struct g_audio *g_audio);
+int u_audio_start_playback(struct g_audio *g_audio);
+void u_audio_stop_playback(struct g_audio *g_audio);
+
+#endif /* __U_AUDIO_H */
diff -urN linux-4.9.37/drivers/usb/gadget/function/u_uac1.c linux-4.9.y/drivers/usb/gadget/function/u_uac1.c
--- linux-4.9.37/drivers/usb/gadget/function/u_uac1.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/gadget/function/u_uac1.c 2021-06-07 13:01:34.000000000 +0300
@@ -157,7 +157,6 @@
struct gaudio_snd_dev *snd = &card->playback;
struct snd_pcm_substream *substream = snd->substream;
struct snd_pcm_runtime *runtime = substream->runtime;
- mm_segment_t old_fs;
ssize_t result;
snd_pcm_sframes_t frames;
@@ -174,15 +173,11 @@
}
frames = bytes_to_frames(runtime, count);
- old_fs = get_fs();
- set_fs(KERNEL_DS);
- result = snd_pcm_lib_write(snd->substream, (void __user *)buf, frames);
+ result = snd_pcm_kernel_write(snd->substream, buf, frames);
if (result != frames) {
ERROR(card, "Playback error: %d\n", (int)result);
- set_fs(old_fs);
goto try_again;
}
- set_fs(old_fs);
return 0;
}
diff -urN linux-4.9.37/drivers/usb/gadget/function/u_uac1.h linux-4.9.y/drivers/usb/gadget/function/u_uac1.h
--- linux-4.9.37/drivers/usb/gadget/function/u_uac1.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/gadget/function/u_uac1.h 2021-06-07 13:01:34.000000000 +0300
@@ -1,82 +1,38 @@
+// SPDX-License-Identifier: GPL-2.0
/*
- * u_uac1.h -- interface to USB gadget "ALSA AUDIO" utilities
+ * u_uac1.h - Utility definitions for UAC1 function
*
- * Copyright (C) 2008 Bryan Wu <cooloney@kernel.org>
- * Copyright (C) 2008 Analog Devices, Inc
- *
- * Enter bugs at http://blackfin.uclinux.org/
- *
- * Licensed under the GPL-2 or later.
+ * Copyright (C) 2016 Ruslan Bilovol <ruslan.bilovol@gmail.com>
*/
-#ifndef __U_AUDIO_H
-#define __U_AUDIO_H
+#ifndef __U_UAC1_H
+#define __U_UAC1_H
-#include <linux/device.h>
-#include <linux/err.h>
-#include <linux/usb/audio.h>
#include <linux/usb/composite.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-
-#define FILE_PCM_PLAYBACK "/dev/snd/pcmC0D0p"
-#define FILE_PCM_CAPTURE "/dev/snd/pcmC0D0c"
-#define FILE_CONTROL "/dev/snd/controlC0"
-
#define UAC1_OUT_EP_MAX_PACKET_SIZE 200
-#define UAC1_REQ_COUNT 256
-#define UAC1_AUDIO_BUF_SIZE 48000
+#define UAC1_DEF_CCHMASK 0x3
+#define UAC1_DEF_CSRATE 48000
+#define UAC1_DEF_CSSIZE 2
+#define UAC1_DEF_PCHMASK 0x3
+#define UAC1_DEF_PSRATE 48000
+#define UAC1_DEF_PSSIZE 2
+#define UAC1_DEF_REQ_NUM 2
-/*
- * This represents the USB side of an audio card device, managed by a USB
- * function which provides control and stream interfaces.
- */
-
-struct gaudio_snd_dev {
- struct gaudio *card;
- struct file *filp;
- struct snd_pcm_substream *substream;
- int access;
- int format;
- int channels;
- int rate;
-};
-
-struct gaudio {
- struct usb_function func;
- struct usb_gadget *gadget;
-
- /* ALSA sound device interfaces */
- struct gaudio_snd_dev control;
- struct gaudio_snd_dev playback;
- struct gaudio_snd_dev capture;
-
- /* TODO */
-};
struct f_uac1_opts {
struct usb_function_instance func_inst;
- int req_buf_size;
- int req_count;
- int audio_buf_size;
- char *fn_play;
- char *fn_cap;
- char *fn_cntl;
+ int c_chmask;
+ int c_srate;
+ int c_ssize;
+ int p_chmask;
+ int p_srate;
+ int p_ssize;
+ int req_number;
unsigned bound:1;
- unsigned fn_play_alloc:1;
- unsigned fn_cap_alloc:1;
- unsigned fn_cntl_alloc:1;
+
struct mutex lock;
int refcnt;
};
-int gaudio_setup(struct gaudio *card);
-void gaudio_cleanup(struct gaudio *the_card);
-
-size_t u_audio_playback(struct gaudio *card, void *buf, size_t count);
-int u_audio_get_playback_channels(struct gaudio *card);
-int u_audio_get_playback_rate(struct gaudio *card);
-
-#endif /* __U_AUDIO_H */
+#endif /* __U_UAC1_H */
diff -urN linux-4.9.37/drivers/usb/gadget/function/u_uac1_legacy.c linux-4.9.y/drivers/usb/gadget/function/u_uac1_legacy.c
--- linux-4.9.37/drivers/usb/gadget/function/u_uac1_legacy.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/usb/gadget/function/u_uac1_legacy.c 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,315 @@
+/*
+ * u_uac1.c -- ALSA audio utilities for Gadget stack
+ *
+ * Copyright (C) 2008 Bryan Wu <cooloney@kernel.org>
+ * Copyright (C) 2008 Analog Devices, Inc
+ *
+ * Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/ctype.h>
+#include <linux/random.h>
+#include <linux/syscalls.h>
+
+#include "u_uac1_legacy.h"
+
+/*
+ * This component encapsulates the ALSA devices for USB audio gadget
+ */
+
+/*-------------------------------------------------------------------------*/
+
+/**
+ * Some ALSA internal helper functions
+ */
+static int snd_interval_refine_set(struct snd_interval *i, unsigned int val)
+{
+ struct snd_interval t;
+ t.empty = 0;
+ t.min = t.max = val;
+ t.openmin = t.openmax = 0;
+ t.integer = 1;
+ return snd_interval_refine(i, &t);
+}
+
+static int _snd_pcm_hw_param_set(struct snd_pcm_hw_params *params,
+ snd_pcm_hw_param_t var, unsigned int val,
+ int dir)
+{
+ int changed;
+ if (hw_is_mask(var)) {
+ struct snd_mask *m = hw_param_mask(params, var);
+ if (val == 0 && dir < 0) {
+ changed = -EINVAL;
+ snd_mask_none(m);
+ } else {
+ if (dir > 0)
+ val++;
+ else if (dir < 0)
+ val--;
+ changed = snd_mask_refine_set(
+ hw_param_mask(params, var), val);
+ }
+ } else if (hw_is_interval(var)) {
+ struct snd_interval *i = hw_param_interval(params, var);
+ if (val == 0 && dir < 0) {
+ changed = -EINVAL;
+ snd_interval_none(i);
+ } else if (dir == 0)
+ changed = snd_interval_refine_set(i, val);
+ else {
+ struct snd_interval t;
+ t.openmin = 1;
+ t.openmax = 1;
+ t.empty = 0;
+ t.integer = 0;
+ if (dir < 0) {
+ t.min = val - 1;
+ t.max = val;
+ } else {
+ t.min = val;
+ t.max = val+1;
+ }
+ changed = snd_interval_refine(i, &t);
+ }
+ } else
+ return -EINVAL;
+ if (changed) {
+ params->cmask |= 1 << var;
+ params->rmask |= 1 << var;
+ }
+ return changed;
+}
+/*-------------------------------------------------------------------------*/
+
+/**
+ * Set default hardware params
+ */
+static int playback_default_hw_params(struct gaudio_snd_dev *snd)
+{
+ struct snd_pcm_substream *substream = snd->substream;
+ struct snd_pcm_hw_params *params;
+ snd_pcm_sframes_t result;
+
+ /*
+ * SNDRV_PCM_ACCESS_RW_INTERLEAVED,
+ * SNDRV_PCM_FORMAT_S16_LE
+ * CHANNELS: 2
+ * RATE: 48000
+ */
+ snd->access = SNDRV_PCM_ACCESS_RW_INTERLEAVED;
+ snd->format = SNDRV_PCM_FORMAT_S16_LE;
+ snd->channels = 2;
+ snd->rate = 48000;
+
+ params = kzalloc(sizeof(*params), GFP_KERNEL);
+ if (!params)
+ return -ENOMEM;
+
+ _snd_pcm_hw_params_any(params);
+ _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_ACCESS,
+ snd->access, 0);
+ _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_FORMAT,
+ snd->format, 0);
+ _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_CHANNELS,
+ snd->channels, 0);
+ _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_RATE,
+ snd->rate, 0);
+
+ snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
+ snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_HW_PARAMS, params);
+
+ result = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_PREPARE, NULL);
+ if (result < 0) {
+ ERROR(snd->card,
+ "Preparing sound card failed: %d\n", (int)result);
+ kfree(params);
+ return result;
+ }
+
+ /* Store the hardware parameters */
+ snd->access = params_access(params);
+ snd->format = params_format(params);
+ snd->channels = params_channels(params);
+ snd->rate = params_rate(params);
+
+ kfree(params);
+
+ INFO(snd->card,
+ "Hardware params: access %x, format %x, channels %d, rate %d\n",
+ snd->access, snd->format, snd->channels, snd->rate);
+
+ return 0;
+}
+
+/**
+ * Playback audio buffer data by ALSA PCM device
+ */
+size_t u_audio_playback(struct gaudio *card, void *buf, size_t count)
+{
+ struct gaudio_snd_dev *snd = &card->playback;
+ struct snd_pcm_substream *substream = snd->substream;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ mm_segment_t old_fs;
+ ssize_t result;
+ snd_pcm_sframes_t frames;
+
+try_again:
+ if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
+ runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
+ result = snd_pcm_kernel_ioctl(substream,
+ SNDRV_PCM_IOCTL_PREPARE, NULL);
+ if (result < 0) {
+ ERROR(card, "Preparing sound card failed: %d\n",
+ (int)result);
+ return result;
+ }
+ }
+
+ frames = bytes_to_frames(runtime, count);
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ result = snd_pcm_lib_write(snd->substream, (void __user *)buf, frames);
+ if (result != frames) {
+ ERROR(card, "Playback error: %d\n", (int)result);
+ set_fs(old_fs);
+ goto try_again;
+ }
+ set_fs(old_fs);
+
+ return 0;
+}
+
+int u_audio_get_playback_channels(struct gaudio *card)
+{
+ return card->playback.channels;
+}
+
+int u_audio_get_playback_rate(struct gaudio *card)
+{
+ return card->playback.rate;
+}
+
+/**
+ * Open ALSA PCM and control device files
+ * Initial the PCM or control device
+ */
+static int gaudio_open_snd_dev(struct gaudio *card)
+{
+ struct snd_pcm_file *pcm_file;
+ struct gaudio_snd_dev *snd;
+ struct f_uac1_legacy_opts *opts;
+ char *fn_play, *fn_cap, *fn_cntl;
+
+ opts = container_of(card->func.fi, struct f_uac1_legacy_opts,
+ func_inst);
+ fn_play = opts->fn_play;
+ fn_cap = opts->fn_cap;
+ fn_cntl = opts->fn_cntl;
+
+ /* Open control device */
+ snd = &card->control;
+ snd->filp = filp_open(fn_cntl, O_RDWR, 0);
+ if (IS_ERR(snd->filp)) {
+ int ret = PTR_ERR(snd->filp);
+ ERROR(card, "unable to open sound control device file: %s\n",
+ fn_cntl);
+ snd->filp = NULL;
+ return ret;
+ }
+ snd->card = card;
+
+ /* Open PCM playback device and setup substream */
+ snd = &card->playback;
+ snd->filp = filp_open(fn_play, O_WRONLY, 0);
+ if (IS_ERR(snd->filp)) {
+ int ret = PTR_ERR(snd->filp);
+
+ ERROR(card, "No such PCM playback device: %s\n", fn_play);
+ snd->filp = NULL;
+ return ret;
+ }
+ pcm_file = snd->filp->private_data;
+ snd->substream = pcm_file->substream;
+ snd->card = card;
+ playback_default_hw_params(snd);
+
+ /* Open PCM capture device and setup substream */
+ snd = &card->capture;
+ snd->filp = filp_open(fn_cap, O_RDONLY, 0);
+ if (IS_ERR(snd->filp)) {
+ ERROR(card, "No such PCM capture device: %s\n", fn_cap);
+ snd->substream = NULL;
+ snd->card = NULL;
+ snd->filp = NULL;
+ } else {
+ pcm_file = snd->filp->private_data;
+ snd->substream = pcm_file->substream;
+ snd->card = card;
+ }
+
+ return 0;
+}
+
+/**
+ * Close ALSA PCM and control device files
+ */
+static int gaudio_close_snd_dev(struct gaudio *gau)
+{
+ struct gaudio_snd_dev *snd;
+
+ /* Close control device */
+ snd = &gau->control;
+ if (snd->filp)
+ filp_close(snd->filp, NULL);
+
+ /* Close PCM playback device and setup substream */
+ snd = &gau->playback;
+ if (snd->filp)
+ filp_close(snd->filp, NULL);
+
+ /* Close PCM capture device and setup substream */
+ snd = &gau->capture;
+ if (snd->filp)
+ filp_close(snd->filp, NULL);
+
+ return 0;
+}
+
+/**
+ * gaudio_setup - setup ALSA interface and preparing for USB transfer
+ *
+ * This sets up PCM, mixer or MIDI ALSA devices fore USB gadget using.
+ *
+ * Returns negative errno, or zero on success
+ */
+int gaudio_setup(struct gaudio *card)
+{
+ int ret;
+
+ ret = gaudio_open_snd_dev(card);
+ if (ret)
+ ERROR(card, "we need at least one control device\n");
+
+ return ret;
+
+}
+
+/**
+ * gaudio_cleanup - remove ALSA device interface
+ *
+ * This is called to free all resources allocated by @gaudio_setup().
+ */
+void gaudio_cleanup(struct gaudio *the_card)
+{
+ if (the_card)
+ gaudio_close_snd_dev(the_card);
+}
+
diff -urN linux-4.9.37/drivers/usb/gadget/function/u_uac1_legacy.h linux-4.9.y/drivers/usb/gadget/function/u_uac1_legacy.h
--- linux-4.9.37/drivers/usb/gadget/function/u_uac1_legacy.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/usb/gadget/function/u_uac1_legacy.h 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,82 @@
+/*
+ * u_uac1.c -- ALSA audio utilities for Gadget stack
+ *
+ * Copyright (C) 2008 Bryan Wu <cooloney@kernel.org>
+ * Copyright (C) 2008 Analog Devices, Inc
+ *
+ * Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __U_UAC1_LEGACY_H
+#define __U_UAC1_LEGACY_H
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/usb/audio.h>
+#include <linux/usb/composite.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+
+#define FILE_PCM_PLAYBACK "/dev/snd/pcmC0D0p"
+#define FILE_PCM_CAPTURE "/dev/snd/pcmC0D0c"
+#define FILE_CONTROL "/dev/snd/controlC0"
+
+#define UAC1_OUT_EP_MAX_PACKET_SIZE 200
+#define UAC1_REQ_COUNT 256
+#define UAC1_AUDIO_BUF_SIZE 48000
+
+/*
+ * This represents the USB side of an audio card device, managed by a USB
+ * function which provides control and stream interfaces.
+ */
+
+struct gaudio_snd_dev {
+ struct gaudio *card;
+ struct file *filp;
+ struct snd_pcm_substream *substream;
+ int access;
+ int format;
+ int channels;
+ int rate;
+};
+
+struct gaudio {
+ struct usb_function func;
+ struct usb_gadget *gadget;
+
+ /* ALSA sound device interfaces */
+ struct gaudio_snd_dev control;
+ struct gaudio_snd_dev playback;
+ struct gaudio_snd_dev capture;
+
+ /* TODO */
+};
+
+struct f_uac1_legacy_opts {
+ struct usb_function_instance func_inst;
+ int req_buf_size;
+ int req_count;
+ int audio_buf_size;
+ char *fn_play;
+ char *fn_cap;
+ char *fn_cntl;
+ unsigned bound:1;
+ unsigned fn_play_alloc:1;
+ unsigned fn_cap_alloc:1;
+ unsigned fn_cntl_alloc:1;
+ struct mutex lock;
+ int refcnt;
+};
+
+int gaudio_setup(struct gaudio *card);
+void gaudio_cleanup(struct gaudio *the_card);
+
+size_t u_audio_playback(struct gaudio *card, void *buf, size_t count);
+int u_audio_get_playback_channels(struct gaudio *card);
+int u_audio_get_playback_rate(struct gaudio *card);
+
+#endif /* __U_UAC1_LEGACY_H */
diff -urN linux-4.9.37/drivers/usb/gadget/function/u_uac2.h linux-4.9.y/drivers/usb/gadget/function/u_uac2.h
--- linux-4.9.37/drivers/usb/gadget/function/u_uac2.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/gadget/function/u_uac2.h 2021-06-07 13:01:34.000000000 +0300
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* u_uac2.h
*
@@ -7,10 +8,6 @@
* http://www.samsung.com
*
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
- *
- * 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.
*/
#ifndef U_UAC2_H
@@ -24,6 +21,7 @@
#define UAC2_DEF_CCHMASK 0x3
#define UAC2_DEF_CSRATE 64000
#define UAC2_DEF_CSSIZE 2
+#define UAC2_DEF_REQ_NUM 2
struct f_uac2_opts {
struct usb_function_instance func_inst;
@@ -33,6 +31,7 @@
int c_chmask;
int c_srate;
int c_ssize;
+ int req_number;
bool bound;
struct mutex lock;
diff -urN linux-4.9.37/drivers/usb/gadget/function/u_uvc.h linux-4.9.y/drivers/usb/gadget/function/u_uvc.h
--- linux-4.9.37/drivers/usb/gadget/function/u_uvc.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/gadget/function/u_uvc.h 2021-06-07 13:01:34.000000000 +0300
@@ -52,6 +52,7 @@
struct uvc_processing_unit_descriptor uvc_processing;
struct uvc_output_terminal_descriptor uvc_output_terminal;
struct uvc_color_matching_descriptor uvc_color_matching;
+ struct UVC_EXTENSION_UNIT_DESCRIPTOR(1, 2) uvc_extension;
/*
* Control descriptors pointers arrays for full-/high-speed and
@@ -60,8 +61,8 @@
* descriptors. Used by configfs only, must not be touched by legacy
* gadgets.
*/
- struct uvc_descriptor_header *uvc_fs_control_cls[5];
- struct uvc_descriptor_header *uvc_ss_control_cls[5];
+ struct uvc_descriptor_header *uvc_fs_control_cls[6];
+ struct uvc_descriptor_header *uvc_ss_control_cls[6];
/*
* Streaming descriptors for full-speed, high-speed and super-speed.
diff -urN linux-4.9.37/drivers/usb/gadget/function/uvc_configfs.c linux-4.9.y/drivers/usb/gadget/function/uvc_configfs.c
--- linux-4.9.37/drivers/usb/gadget/function/uvc_configfs.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/gadget/function/uvc_configfs.c 2021-06-07 13:01:34.000000000 +0300
@@ -254,7 +254,49 @@
return result;
}
-UVC_ATTR_RO(uvcg_default_processing_, bm_controls, bmControls);
+static ssize_t uvcg_default_processing_bm_controls_store(
+ struct config_item *item, const char *page, size_t len)
+{
+ struct uvcg_default_processing *dp = to_uvcg_default_processing(item);
+ struct f_uvc_opts *opts;
+ struct config_item *opts_item;
+ struct mutex *su_mutex = &dp->group.cg_subsys->su_mutex;
+ struct uvc_processing_unit_descriptor *pd;
+ int ret, i;
+ const char *pg = page;
+ /* sign, base 2 representation, newline, terminator */
+ char buf[1 + sizeof(u8) * 8 + 1 + 1];
+ int idx;
+
+ mutex_lock(su_mutex); /* for navigating configfs hierarchy */
+
+ opts_item = dp->group.cg_item.ci_parent->ci_parent->ci_parent;
+ opts = to_f_uvc_opts(opts_item);
+ pd = &opts->uvc_processing;
+
+ idx = 0;
+ while (pg - page < len) {
+ i = 0;
+ while (i < sizeof(buf) && (pg - page < len) &&
+ *pg != '\0' && *pg != '\n')
+ buf[i++] = *pg++;
+ while ((pg - page < len) && (*pg == '\0' || *pg == '\n'))
+ ++pg;
+ buf[i] = '\0';
+ ret = kstrtou8(buf, 0, &pd->bmControls[idx++]);
+ if (ret < 0)
+ goto end;
+ if (idx >= pd->bControlSize)
+ break;
+ }
+ ret = len;
+end:
+ mutex_unlock(&opts->lock);
+ mutex_unlock(su_mutex);
+ return ret;
+}
+
+UVC_ATTR(uvcg_default_processing_, bm_controls, bmControls);
static struct configfs_attribute *uvcg_default_processing_attrs[] = {
&uvcg_default_processing_attr_b_unit_id,
@@ -281,6 +323,110 @@
.ct_owner = THIS_MODULE,
};
+/* control/extension/default */
+static struct uvcg_default_extension {
+ struct config_group group;
+} uvcg_default_extension;
+
+static inline struct uvcg_default_extension
+*to_uvcg_default_extension(struct config_item *item)
+{
+ return container_of(to_config_group(item),
+ struct uvcg_default_extension, group);
+}
+
+#define UVCG_DEFAULT_EXTENSION_ATTR(cname, aname, conv) \
+static ssize_t uvcg_default_extension_##cname##_show( \
+ struct config_item *item, char *page) \
+{ \
+ struct uvcg_default_extension *dp = to_uvcg_default_extension(item); \
+ struct f_uvc_opts *opts; \
+ struct config_item *opts_item; \
+ struct mutex *su_mutex = &dp->group.cg_subsys->su_mutex; \
+ struct UVC_EXTENSION_UNIT_DESCRIPTOR(1, 2) *ed; \
+ int result; \
+ \
+ mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
+ \
+ opts_item = dp->group.cg_item.ci_parent->ci_parent->ci_parent; \
+ opts = to_f_uvc_opts(opts_item); \
+ ed = &opts->uvc_extension; \
+ \
+ mutex_lock(&opts->lock); \
+ result = sprintf(page, "%d\n", conv(ed->aname)); \
+ mutex_unlock(&opts->lock); \
+ \
+ mutex_unlock(su_mutex); \
+ return result; \
+} \
+ \
+UVC_ATTR_RO(uvcg_default_extension_, cname, aname)
+
+#define identity_conv(x) (x)
+
+UVCG_DEFAULT_EXTENSION_ATTR(b_unit_id, bUnitID, identity_conv);
+UVCG_DEFAULT_EXTENSION_ATTR(b_num_input_pins, bNrInPins, identity_conv);
+UVCG_DEFAULT_EXTENSION_ATTR(i_extension, iExtension, identity_conv);
+
+#undef identity_conv
+
+#undef UVCG_DEFAULT_EXTENSION_ATTR
+
+static ssize_t uvcg_default_extension_bm_controls_show(
+ struct config_item *item, char *page)
+{
+ struct uvcg_default_extension *dp = to_uvcg_default_extension(item);
+ struct f_uvc_opts *opts;
+ struct config_item *opts_item;
+ struct mutex *su_mutex = &dp->group.cg_subsys->su_mutex;
+ struct UVC_EXTENSION_UNIT_DESCRIPTOR(1, 2) *ed;
+ int result, i;
+ char *pg = page;
+
+ mutex_lock(su_mutex); /* for navigating configfs hierarchy */
+
+ opts_item = dp->group.cg_item.ci_parent->ci_parent->ci_parent;
+ opts = to_f_uvc_opts(opts_item);
+ ed = &opts->uvc_extension;
+
+ mutex_lock(&opts->lock);
+ for (result = 0, i = 0; i < ed->bControlSize; ++i) {
+ result += sprintf(pg, "%d\n", ed->bmControls[i]);
+ pg = page + result;
+ }
+ mutex_unlock(&opts->lock);
+
+ mutex_unlock(su_mutex);
+
+ return result;
+}
+
+UVC_ATTR_RO(uvcg_default_extension_, bm_controls, bmControls);
+
+static struct configfs_attribute *uvcg_default_extension_attrs[] = {
+ &uvcg_default_extension_attr_b_unit_id,
+ &uvcg_default_extension_attr_b_num_input_pins,
+ &uvcg_default_extension_attr_bm_controls,
+ &uvcg_default_extension_attr_i_extension,
+ NULL,
+};
+
+static struct config_item_type uvcg_default_extension_type = {
+ .ct_attrs = uvcg_default_extension_attrs,
+ .ct_owner = THIS_MODULE,
+};
+
+/* struct uvcg_extension {}; */
+
+/* control/extension */
+static struct uvcg_extension_grp {
+ struct config_group group;
+} uvcg_extension_grp;
+
+static struct config_item_type uvcg_extension_grp_type = {
+ .ct_owner = THIS_MODULE,
+};
+
/* control/terminal/camera/default */
static struct uvcg_default_camera {
struct config_group group;
@@ -368,7 +514,50 @@
return result;
}
-UVC_ATTR_RO(uvcg_default_camera_, bm_controls, bmControls);
+static ssize_t uvcg_default_camera_bm_controls_store(
+ struct config_item *item, const char *page, size_t len)
+{
+ struct uvcg_default_camera *dc = to_uvcg_default_camera(item);
+ struct f_uvc_opts *opts;
+ struct config_item *opts_item;
+ struct mutex *su_mutex = &dc->group.cg_subsys->su_mutex;
+ struct uvc_camera_terminal_descriptor *cd;
+ int ret, i;
+ const char *pg = page;
+ /* sign, base 2 representation, newline, terminator */
+ char buf[1 + sizeof(u8) * 8 + 1 + 1];
+ int idx;
+
+ mutex_lock(su_mutex); /* for navigating configfs hierarchy */
+
+ opts_item = dc->group.cg_item.ci_parent->ci_parent->ci_parent->
+ ci_parent;
+ opts = to_f_uvc_opts(opts_item);
+ cd = &opts->uvc_camera_terminal;
+
+ idx = 0;
+ while (pg - page < len) {
+ i = 0;
+ while (i < sizeof(buf) && (pg - page < len) &&
+ *pg != '\0' && *pg != '\n')
+ buf[i++] = *pg++;
+ while ((pg - page < len) && (*pg == '\0' || *pg == '\n'))
+ ++pg;
+ buf[i] = '\0';
+ ret = kstrtou8(buf, 0, &cd->bmControls[idx++]);
+ if (ret < 0)
+ goto end;
+ if (idx >= cd->bControlSize)
+ break;
+ }
+ ret = len;
+end:
+ mutex_unlock(&opts->lock);
+ mutex_unlock(su_mutex);
+ return ret;
+}
+
+UVC_ATTR(uvcg_default_camera_, bm_controls, bmControls);
static struct configfs_attribute *uvcg_default_camera_attrs[] = {
&uvcg_default_camera_attr_b_terminal_id,
@@ -626,14 +815,21 @@
struct config_group group;
} uvcg_mjpeg_grp;
+/* streaming/frame_based */
+static struct uvcg_frame_based_format_grp {
+ struct config_group group;
+} uvcg_frame_based_format_grp;
+
static struct config_item *fmt_parent[] = {
&uvcg_uncompressed_grp.group.cg_item,
&uvcg_mjpeg_grp.group.cg_item,
+ &uvcg_frame_based_format_grp.group.cg_item,
};
enum uvcg_format_type {
UVCG_UNCOMPRESSED = 0,
UVCG_MJPEG,
+ UVCG_FRAME_FRAME_BASED,
};
struct uvcg_format {
@@ -1203,6 +1399,7 @@
return ERR_PTR(-EINVAL);
}
++fmt->num_frames;
+ h->frame.b_frame_index = fmt->num_frames;
mutex_unlock(&opts->lock);
config_item_init_type_name(&h->item, name, &uvcg_frame_type);
@@ -1227,6 +1424,263 @@
mutex_unlock(&opts->lock);
}
+struct uvcg_frame_based_frame {
+ struct {
+ u8 b_length;
+ u8 b_descriptor_type;
+ u8 b_descriptor_subtype;
+ u8 b_frame_index;
+ u8 bm_capabilities;
+ u16 w_width;
+ u16 w_height;
+ u32 dw_min_bit_rate;
+ u32 dw_max_bit_rate;
+ u32 dw_default_frame_interval;
+ u8 b_frame_interval_type;
+ u32 dw_bytes_per_line;
+ } __attribute__((packed)) frame;
+ u32 *dw_frame_interval;
+ enum uvcg_format_type fmt_type;
+ struct config_item item;
+};
+
+static struct uvcg_frame_based_frame *to_uvcg_frame_based_frame(struct config_item *item)
+{
+ return container_of(item, struct uvcg_frame_based_frame, item);
+}
+
+#define UVCG_FRAME_BASED_FRAME_ATTR(cname, aname, to_cpu_endian, to_little_endian, bits) \
+static ssize_t uvcg_frame_based_frame_##cname##_show(struct config_item *item, char *page)\
+{ \
+ struct uvcg_frame_based_frame *f = to_uvcg_frame_based_frame(item); \
+ struct f_uvc_opts *opts; \
+ struct config_item *opts_item; \
+ struct mutex *su_mutex = &f->item.ci_group->cg_subsys->su_mutex;\
+ int result; \
+ \
+ mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
+ \
+ opts_item = f->item.ci_parent->ci_parent->ci_parent->ci_parent; \
+ opts = to_f_uvc_opts(opts_item); \
+ \
+ mutex_lock(&opts->lock); \
+ result = sprintf(page, "%d\n", to_cpu_endian(f->frame.cname)); \
+ mutex_unlock(&opts->lock); \
+ \
+ mutex_unlock(su_mutex); \
+ return result; \
+} \
+ \
+static ssize_t uvcg_frame_based_frame_##cname##_store(struct config_item *item, \
+ const char *page, size_t len)\
+{ \
+ struct uvcg_frame_based_frame *f = to_uvcg_frame_based_frame(item); \
+ struct f_uvc_opts *opts; \
+ struct config_item *opts_item; \
+ struct uvcg_format *fmt; \
+ struct mutex *su_mutex = &f->item.ci_group->cg_subsys->su_mutex;\
+ int ret; \
+ u##bits num; \
+ \
+ ret = kstrtou##bits(page, 0, &num); \
+ if (ret) \
+ return ret; \
+ \
+ mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
+ \
+ opts_item = f->item.ci_parent->ci_parent->ci_parent->ci_parent; \
+ opts = to_f_uvc_opts(opts_item); \
+ fmt = to_uvcg_format(f->item.ci_parent); \
+ \
+ mutex_lock(&opts->lock); \
+ if (fmt->linked || opts->refcnt) { \
+ ret = -EBUSY; \
+ goto end; \
+ } \
+ \
+ f->frame.cname = to_little_endian(num); \
+ ret = len; \
+end: \
+ mutex_unlock(&opts->lock); \
+ mutex_unlock(su_mutex); \
+ return ret; \
+} \
+ \
+UVC_ATTR(uvcg_frame_based_frame_, cname, aname);
+
+#define noop_conversion(x) (x)
+
+UVCG_FRAME_BASED_FRAME_ATTR(bm_capabilities, bmCapabilities, noop_conversion,
+ noop_conversion, 8);
+UVCG_FRAME_BASED_FRAME_ATTR(w_width, wWidth, le16_to_cpu, cpu_to_le16, 16);
+UVCG_FRAME_BASED_FRAME_ATTR(w_height, wHeight, le16_to_cpu, cpu_to_le16, 16);
+UVCG_FRAME_BASED_FRAME_ATTR(dw_min_bit_rate, dwMinBitRate, le32_to_cpu, cpu_to_le32, 32);
+UVCG_FRAME_BASED_FRAME_ATTR(dw_max_bit_rate, dwMaxBitRate, le32_to_cpu, cpu_to_le32, 32);
+UVCG_FRAME_BASED_FRAME_ATTR(dw_default_frame_interval, dwDefaultFrameInterval,
+ le32_to_cpu, cpu_to_le32, 32);
+UVCG_FRAME_BASED_FRAME_ATTR(dw_bytes_per_line, dwBytesPerLine,
+ le32_to_cpu, cpu_to_le32, 32);
+
+#undef noop_conversion
+
+#undef UVCG_FRAME_BASED_FRAME_ATTR
+
+static ssize_t uvcg_frame_based_frame_dw_frame_interval_show(struct config_item *item,
+ char *page)
+{
+ struct uvcg_frame_based_frame *frm = to_uvcg_frame_based_frame(item);
+ struct f_uvc_opts *opts;
+ struct config_item *opts_item;
+ struct mutex *su_mutex = &frm->item.ci_group->cg_subsys->su_mutex;
+ int result, i;
+ char *pg = page;
+
+ mutex_lock(su_mutex); /* for navigating configfs hierarchy */
+
+ opts_item = frm->item.ci_parent->ci_parent->ci_parent->ci_parent;
+ opts = to_f_uvc_opts(opts_item);
+
+ mutex_lock(&opts->lock);
+ for (result = 0, i = 0; i < frm->frame.b_frame_interval_type; ++i) {
+ result += sprintf(pg, "%d\n",
+ le32_to_cpu(frm->dw_frame_interval[i]));
+ pg = page + result;
+ }
+ mutex_unlock(&opts->lock);
+
+ mutex_unlock(su_mutex);
+ return result;
+}
+
+static ssize_t uvcg_frame_based_frame_dw_frame_interval_store(struct config_item *item,
+ const char *page, size_t len)
+{
+ struct uvcg_frame_based_frame *ch = to_uvcg_frame_based_frame(item);
+ struct f_uvc_opts *opts;
+ struct config_item *opts_item;
+ struct uvcg_format *fmt;
+ struct mutex *su_mutex = &ch->item.ci_group->cg_subsys->su_mutex;
+ int ret = 0, n = 0;
+ u32 *frm_intrv, *tmp;
+
+ mutex_lock(su_mutex); /* for navigating configfs hierarchy */
+
+ opts_item = ch->item.ci_parent->ci_parent->ci_parent->ci_parent;
+ opts = to_f_uvc_opts(opts_item);
+ fmt = to_uvcg_format(ch->item.ci_parent);
+
+ mutex_lock(&opts->lock);
+ if (fmt->linked || opts->refcnt) {
+ ret = -EBUSY;
+ goto end;
+ }
+
+ ret = __uvcg_iter_frm_intrv(page, len, __uvcg_count_frm_intrv, &n);
+ if (ret)
+ goto end;
+
+ tmp = frm_intrv = kcalloc(n, sizeof(u32), GFP_KERNEL);
+ if (!frm_intrv) {
+ ret = -ENOMEM;
+ goto end;
+ }
+
+ ret = __uvcg_iter_frm_intrv(page, len, __uvcg_fill_frm_intrv, &tmp);
+ if (ret) {
+ kfree(frm_intrv);
+ goto end;
+ }
+
+ kfree(ch->dw_frame_interval);
+ ch->dw_frame_interval = frm_intrv;
+ ch->frame.b_frame_interval_type = n;
+ ret = len;
+
+end:
+ mutex_unlock(&opts->lock);
+ mutex_unlock(su_mutex);
+ return ret;
+}
+
+UVC_ATTR(uvcg_frame_based_frame_, dw_frame_interval, dwFrameInterval);
+
+static struct configfs_attribute *uvcg_frame_based_frame_attrs[] = {
+ &uvcg_frame_based_frame_attr_bm_capabilities,
+ &uvcg_frame_based_frame_attr_w_width,
+ &uvcg_frame_based_frame_attr_w_height,
+ &uvcg_frame_based_frame_attr_dw_min_bit_rate,
+ &uvcg_frame_based_frame_attr_dw_max_bit_rate,
+ &uvcg_frame_based_frame_attr_dw_default_frame_interval,
+ &uvcg_frame_based_frame_attr_dw_frame_interval,
+ &uvcg_frame_based_frame_attr_dw_bytes_per_line,
+ NULL,
+};
+
+static struct config_item_type uvcg_frame_based_frame_type = {
+ .ct_attrs = uvcg_frame_based_frame_attrs,
+ .ct_owner = THIS_MODULE,
+};
+
+static struct config_item *uvcg_frame_based_frame_make(struct config_group *group,
+ const char *name)
+{
+ struct uvcg_frame_based_frame *h;
+ struct uvcg_format *fmt;
+ struct f_uvc_opts *opts;
+ struct config_item *opts_item;
+
+ h = kzalloc(sizeof(*h), GFP_KERNEL);
+ if (!h)
+ return ERR_PTR(-ENOMEM);
+
+ h->frame.b_descriptor_type = USB_DT_CS_INTERFACE;
+ h->frame.b_frame_index = 1;
+ h->frame.w_width = cpu_to_le16(640);
+ h->frame.w_height = cpu_to_le16(360);
+ h->frame.dw_min_bit_rate = cpu_to_le32(18432000);
+ h->frame.dw_max_bit_rate = cpu_to_le32(55296000);
+ h->frame.dw_default_frame_interval = cpu_to_le32(333333);
+ h->frame.dw_bytes_per_line = cpu_to_le32(0);
+
+ opts_item = group->cg_item.ci_parent->ci_parent->ci_parent;
+ opts = to_f_uvc_opts(opts_item);
+
+ mutex_lock(&opts->lock);
+ fmt = to_uvcg_format(&group->cg_item);
+ if (fmt->type == UVCG_FRAME_FRAME_BASED) {
+ h->frame.b_descriptor_subtype = UVC_VS_FRAME_FRAME_BASED;
+ h->fmt_type = UVCG_FRAME_FRAME_BASED;
+ } else {
+ mutex_unlock(&opts->lock);
+ kfree(h);
+ return ERR_PTR(-EINVAL);
+ }
+ ++fmt->num_frames;
+ h->frame.b_frame_index = fmt->num_frames;
+ mutex_unlock(&opts->lock);
+
+ config_item_init_type_name(&h->item, name, &uvcg_frame_based_frame_type);
+
+ return &h->item;
+}
+
+static void uvcg_frame_based_frame_drop(struct config_group *group, struct config_item *item)
+{
+ struct uvcg_frame_based_frame *h = to_uvcg_frame_based_frame(item);
+ struct uvcg_format *fmt;
+ struct f_uvc_opts *opts;
+ struct config_item *opts_item;
+
+ opts_item = group->cg_item.ci_parent->ci_parent->ci_parent;
+ opts = to_f_uvc_opts(opts_item);
+
+ mutex_lock(&opts->lock);
+ fmt = to_uvcg_format(&group->cg_item);
+ --fmt->num_frames;
+ kfree(h);
+ mutex_unlock(&opts->lock);
+}
+
/* streaming/uncompressed/<NAME> */
struct uvcg_uncompressed {
struct uvcg_format fmt;
@@ -1438,10 +1892,17 @@
static struct config_group *uvcg_uncompressed_make(struct config_group *group,
const char *name)
{
+#ifndef CONFIG_GOKE_MC
static char guid[] = {
'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00,
0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71
};
+#else
+ static char guid[] = {
+ 'N', 'V', '2', '1', 0x00, 0x00, 0x10, 0x00,
+ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71
+ };
+#endif
struct uvcg_uncompressed *h;
h = kzalloc(sizeof(*h), GFP_KERNEL);
@@ -1452,7 +1913,11 @@
h->desc.bDescriptorType = USB_DT_CS_INTERFACE;
h->desc.bDescriptorSubType = UVC_VS_FORMAT_UNCOMPRESSED;
memcpy(h->desc.guidFormat, guid, sizeof(guid));
+#ifndef CONFIG_GOKE_MC
h->desc.bBitsPerPixel = 16;
+#else
+ h->desc.bBitsPerPixel = 12;
+#endif
h->desc.bDefaultFrameIndex = 1;
h->desc.bAspectRatioX = 0;
h->desc.bAspectRatioY = 0;
@@ -1678,6 +2143,205 @@
.ct_owner = THIS_MODULE,
};
+/* streaming/frame_based<NAME> */
+struct uvcg_frame_based_format {
+ struct uvcg_format fmt;
+ struct uvc_frame_based_format_desc desc;
+};
+
+static struct uvcg_frame_based_format *to_uvcg_frame_based_format(struct config_item *item)
+{
+ return container_of(
+ container_of(to_config_group(item), struct uvcg_format, group),
+ struct uvcg_frame_based_format, fmt);
+}
+
+static struct configfs_group_operations uvcg_frame_based_format_group_ops = {
+ .make_item = uvcg_frame_based_frame_make,
+ .drop_item = uvcg_frame_based_frame_drop,
+};
+
+#define UVCG_FRAME_BASED_FORMAT_ATTR_RO(cname, aname, conv) \
+static ssize_t uvcg_frame_based_format_##cname##_show(struct config_item *item, char *page)\
+{ \
+ struct uvcg_frame_based_format *u = to_uvcg_frame_based_format(item); \
+ struct f_uvc_opts *opts; \
+ struct config_item *opts_item; \
+ struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
+ int result; \
+ \
+ mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
+ \
+ opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
+ opts = to_f_uvc_opts(opts_item); \
+ \
+ mutex_lock(&opts->lock); \
+ result = sprintf(page, "%d\n", conv(u->desc.aname)); \
+ mutex_unlock(&opts->lock); \
+ \
+ mutex_unlock(su_mutex); \
+ return result; \
+} \
+ \
+UVC_ATTR_RO(uvcg_frame_based_format_, cname, aname)
+
+#define UVCG_FRAME_BASED_FORMAT_ATTR(cname, aname, conv) \
+static ssize_t uvcg_frame_based_format_##cname##_show(struct config_item *item, char *page)\
+{ \
+ struct uvcg_frame_based_format *u = to_uvcg_frame_based_format(item); \
+ struct f_uvc_opts *opts; \
+ struct config_item *opts_item; \
+ struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
+ int result; \
+ \
+ mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
+ \
+ opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
+ opts = to_f_uvc_opts(opts_item); \
+ \
+ mutex_lock(&opts->lock); \
+ result = sprintf(page, "%d\n", conv(u->desc.aname)); \
+ mutex_unlock(&opts->lock); \
+ \
+ mutex_unlock(su_mutex); \
+ return result; \
+} \
+ \
+static ssize_t \
+uvcg_frame_based_format_##cname##_store(struct config_item *item, \
+ const char *page, size_t len) \
+{ \
+ struct uvcg_frame_based_format *u = to_uvcg_frame_based_format(item); \
+ struct f_uvc_opts *opts; \
+ struct config_item *opts_item; \
+ struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
+ int ret; \
+ u8 num; \
+ \
+ mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
+ \
+ opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
+ opts = to_f_uvc_opts(opts_item); \
+ \
+ mutex_lock(&opts->lock); \
+ if (u->fmt.linked || opts->refcnt) { \
+ ret = -EBUSY; \
+ goto end; \
+ } \
+ \
+ ret = kstrtou8(page, 0, &num); \
+ if (ret) \
+ goto end; \
+ \
+ if (num > 255) { \
+ ret = -EINVAL; \
+ goto end; \
+ } \
+ u->desc.aname = num; \
+ ret = len; \
+end: \
+ mutex_unlock(&opts->lock); \
+ mutex_unlock(su_mutex); \
+ return ret; \
+} \
+ \
+UVC_ATTR(uvcg_frame_based_format_, cname, aname)
+
+#define identity_conv(x) (x)
+
+UVCG_FRAME_BASED_FORMAT_ATTR(b_default_frame_index, bDefaultFrameIndex,
+ identity_conv);
+UVCG_FRAME_BASED_FORMAT_ATTR_RO(b_aspect_ratio_x, bAspectRatioX, identity_conv);
+UVCG_FRAME_BASED_FORMAT_ATTR_RO(b_aspect_ratio_y, bAspectRatioY, identity_conv);
+UVCG_FRAME_BASED_FORMAT_ATTR_RO(bm_interface_flags, bmInterfaceFlags, identity_conv);
+
+#undef identity_conv
+
+#undef UVCG_FRAME_BASED_FORMAT_ATTR
+#undef UVCG_FRAME_BASED_FORMAT_ATTR_RO
+
+static inline ssize_t
+uvcg_frame_based_format_bma_controls_show(struct config_item *item, char *page)
+{
+ struct uvcg_frame_based_format *u = to_uvcg_frame_based_format(item);
+ return uvcg_format_bma_controls_show(&u->fmt, page);
+}
+
+static inline ssize_t
+uvcg_frame_based_format_bma_controls_store(struct config_item *item,
+ const char *page, size_t len)
+{
+ struct uvcg_frame_based_format *u = to_uvcg_frame_based_format(item);
+ return uvcg_format_bma_controls_store(&u->fmt, page, len);
+}
+
+UVC_ATTR(uvcg_frame_based_format_, bma_controls, bmaControls);
+
+static struct configfs_attribute *uvcg_frame_based_format_attrs[] = {
+ &uvcg_frame_based_format_attr_b_default_frame_index,
+ &uvcg_frame_based_format_attr_b_aspect_ratio_x,
+ &uvcg_frame_based_format_attr_b_aspect_ratio_y,
+ &uvcg_frame_based_format_attr_bm_interface_flags,
+ &uvcg_frame_based_format_attr_bma_controls,
+ NULL,
+};
+
+static struct config_item_type uvcg_frame_based_format_type = {
+ .ct_group_ops = &uvcg_frame_based_format_group_ops,
+ .ct_attrs = uvcg_frame_based_format_attrs,
+ .ct_owner = THIS_MODULE,
+};
+
+static struct config_group *uvcg_frame_based_format_make(struct config_group *group,
+ const char *name)
+{
+ static char guid[] = { /*Declear frame frame based as H264*/
+ 'H', '2', '6', '4', 0x00, 0x00, 0x10, 0x00,
+ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71
+ };
+ struct uvcg_frame_based_format *h;
+
+ h = kzalloc(sizeof(*h), GFP_KERNEL);
+ if (!h)
+ return ERR_PTR(-ENOMEM);
+
+ h->desc.bLength = UVC_DT_FRAME_BASED_FORMAT_SIZE;
+ h->desc.bDescriptorType = USB_DT_CS_INTERFACE;
+ h->desc.bDescriptorSubType = UVC_VS_FORMAT_FRAME_BASED;
+ memcpy(h->desc.guidFormat, guid, sizeof(guid));
+ h->desc.bBitsPerPixel = 16;
+ h->desc.bDefaultFrameIndex = 1;
+ h->desc.bAspectRatioX = 0;
+ h->desc.bAspectRatioY = 0;
+ h->desc.bmInterfaceFlags = 0;
+ h->desc.bCopyProtect = 0;
+ h->desc.bVariableSize = 1;
+
+ h->fmt.type = UVCG_FRAME_FRAME_BASED;
+ config_group_init_type_name(&h->fmt.group, name,
+ &uvcg_frame_based_format_type);
+
+ return &h->fmt.group;
+}
+
+static void uvcg_frame_based_format_drop(struct config_group *group,
+ struct config_item *item)
+{
+ struct uvcg_frame_based_format *h = to_uvcg_frame_based_format(item);
+
+ kfree(h);
+}
+
+static struct configfs_group_operations uvcg_frame_based_format_grp_ops = {
+ .make_group = uvcg_frame_based_format_make,
+ .drop_item = uvcg_frame_based_format_drop,
+};
+
+static struct config_item_type uvcg_frame_based_format_grp_type = {
+ .ct_group_ops = &uvcg_frame_based_format_grp_ops,
+ .ct_owner = THIS_MODULE,
+};
+
/* streaming/color_matching/default */
static struct uvcg_default_color_matching {
struct config_group group;
@@ -1873,6 +2537,11 @@
container_of(fmt, struct uvcg_mjpeg, fmt);
*size += sizeof(m->desc);
+ } else if (fmt->type == UVCG_FRAME_FRAME_BASED) {
+ struct uvcg_frame_based_format *h =
+ container_of(fmt, struct uvcg_frame_based_format, fmt);
+
+ *size += sizeof(h->desc);
} else {
return -EINVAL;
}
@@ -1881,7 +2550,14 @@
case UVCG_FRAME: {
struct uvcg_frame *frm = priv1;
int sz = sizeof(frm->dw_frame_interval);
+ if (frm->frame.b_descriptor_subtype == UVC_VS_FRAME_FRAME_BASED) {
+ struct uvcg_frame_based_frame *fb_frm = priv1;
+ *size += sizeof(fb_frm->frame);
+ *size += fb_frm->frame.b_frame_interval_type * sizeof(fb_frm->dw_frame_interval);
+ ++*count;
+ return 0;
+ }
*size += sizeof(frm->frame);
*size += frm->frame.b_frame_interval_type * sz;
}
@@ -1949,6 +2625,15 @@
*dest += sizeof(m->desc);
mjp->bNumFrameDescriptors = fmt->num_frames;
mjp->bFormatIndex = n + 1;
+ } else if (fmt->type == UVCG_FRAME_FRAME_BASED) {
+ struct uvc_frame_based_format_desc *ffb = *dest;
+ struct uvcg_frame_based_format *h =
+ container_of(fmt, struct uvcg_frame_based_format, fmt);
+
+ memcpy(*dest, &h->desc, sizeof(h->desc));
+ *dest += sizeof(h->desc);
+ ffb->bNumFrameDescriptors = fmt->num_frames;
+ ffb->bFormatIndex = n + 1;
} else {
return -EINVAL;
}
@@ -1958,6 +2643,19 @@
struct uvcg_frame *frm = priv1;
struct uvc_descriptor_header *h = *dest;
+ if (frm->frame.b_descriptor_subtype == UVC_VS_FRAME_FRAME_BASED) {
+ struct uvcg_frame_based_frame *fb_frm = priv1;
+ sz = sizeof(fb_frm->frame);
+ memcpy(*dest, &fb_frm->frame, sz);
+ *dest += sz;
+ sz = fb_frm->frame.b_frame_interval_type *
+ sizeof(*fb_frm->dw_frame_interval);
+ memcpy(*dest, fb_frm->dw_frame_interval, sz);
+ *dest += sz;
+ h->bLength = UVC_DT_FRAME_BASED_FRAME_SIZE(
+ fb_frm->frame.b_frame_interval_type);
+ return 0;
+ }
sz = sizeof(frm->frame);
memcpy(*dest, &frm->frame, sz);
*dest += sz;
@@ -2224,6 +2922,13 @@
configfs_add_default_group(&uvcg_default_processing.group,
&uvcg_processing_grp.group);
+ config_group_init_type_name(&uvcg_default_extension.group,
+ "default", &uvcg_default_extension_type);
+ config_group_init_type_name(&uvcg_extension_grp.group,
+ "extension", &uvcg_extension_grp_type);
+ configfs_add_default_group(&uvcg_default_extension.group,
+ &uvcg_extension_grp.group);
+
config_group_init_type_name(&uvcg_default_camera.group,
"default", &uvcg_default_camera_type);
config_group_init_type_name(&uvcg_camera_grp.group,
@@ -2278,6 +2983,9 @@
config_group_init_type_name(&uvcg_mjpeg_grp.group,
"mjpeg",
&uvcg_mjpeg_grp_type);
+ config_group_init_type_name(&uvcg_frame_based_format_grp.group,
+ "framebased",
+ &uvcg_frame_based_format_grp_type);
config_group_init_type_name(&uvcg_default_color_matching.group,
"default",
&uvcg_default_color_matching_type);
@@ -2310,6 +3018,8 @@
&uvcg_streaming_grp.group);
configfs_add_default_group(&uvcg_mjpeg_grp.group,
&uvcg_streaming_grp.group);
+ configfs_add_default_group(&uvcg_frame_based_format_grp.group,
+ &uvcg_streaming_grp.group);
configfs_add_default_group(&uvcg_color_matching_grp.group,
&uvcg_streaming_grp.group);
configfs_add_default_group(&uvcg_streaming_class_grp.group,
diff -urN linux-4.9.37/drivers/usb/gadget/function/uvc.h linux-4.9.y/drivers/usb/gadget/function/uvc.h
--- linux-4.9.37/drivers/usb/gadget/function/uvc.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/gadget/function/uvc.h 2021-06-07 13:01:34.000000000 +0300
@@ -17,6 +17,7 @@
#include <linux/types.h>
#include <linux/usb/ch9.h>
+#define UVC_SG_REQ
#define UVC_EVENT_FIRST (V4L2_EVENT_PRIVATE_START + 0)
#define UVC_EVENT_CONNECT (V4L2_EVENT_PRIVATE_START + 0)
#define UVC_EVENT_DISCONNECT (V4L2_EVENT_PRIVATE_START + 1)
@@ -95,8 +96,11 @@
/* ------------------------------------------------------------------------
* Driver specific constants
*/
-
-#define UVC_NUM_REQUESTS 4
+#ifdef UVC_SG_REQ
+#define UVC_NUM_REQUESTS 1
+#else
+#define UVC_NUM_REQUESTS 32
+#endif
#define UVC_MAX_REQUEST_SIZE 64
#define UVC_MAX_EVENTS 4
@@ -106,6 +110,7 @@
struct uvc_video
{
+ struct uvc_device *uvc;
struct usb_ep *ep;
/* Frame parameters */
@@ -116,6 +121,9 @@
unsigned int imagesize;
struct mutex mutex; /* protects frame parameters */
+ unsigned int num_sgs; /* record base */
+ __u8 *sg_buf;
+
/* Requests */
unsigned int req_size;
struct usb_request *req[UVC_NUM_REQUESTS];
diff -urN linux-4.9.37/drivers/usb/gadget/function/uvc_v4l2.c linux-4.9.y/drivers/usb/gadget/function/uvc_v4l2.c
--- linux-4.9.37/drivers/usb/gadget/function/uvc_v4l2.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/gadget/function/uvc_v4l2.c 2021-06-07 13:01:34.000000000 +0300
@@ -60,8 +60,13 @@
};
static struct uvc_format uvc_formats[] = {
+#ifndef CONFIG_GOKE_MC
{ 16, V4L2_PIX_FMT_YUYV },
+#else
+ { 12, V4L2_PIX_FMT_NV21 },
+#endif
{ 0, V4L2_PIX_FMT_MJPEG },
+ { 0, V4L2_PIX_FMT_H264 },
};
static int
diff -urN linux-4.9.37/drivers/usb/gadget/function/uvc_video.c linux-4.9.y/drivers/usb/gadget/function/uvc_video.c
--- linux-4.9.37/drivers/usb/gadget/function/uvc_video.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/gadget/function/uvc_video.c 2021-06-07 13:01:34.000000000 +0300
@@ -23,6 +23,8 @@
#include "uvc_queue.h"
#include "uvc_video.h"
+#include <linux/scatterlist.h>
+#include <linux/io.h>
/* --------------------------------------------------------------------------
* Video codecs
*/
@@ -102,9 +104,45 @@
uvc_video_encode_isoc(struct usb_request *req, struct uvc_video *video,
struct uvc_buffer *buf)
{
+ int ret;
+#ifdef UVC_SG_REQ
+ int len;
+ int ttllen = 0;
+ unsigned int sg_idx;
+ u8 *mem = NULL;
+
+ for (sg_idx = 0; sg_idx < video->num_sgs; sg_idx++) {
+ mem = sg_virt(&req->sg[sg_idx]);
+ len = video->req_size;
+
+ /* Add the header. */
+ ret = uvc_video_encode_header(video, buf, mem, len);
+ mem += ret;
+ len -= ret;
+
+ /* Process video data. */
+ ret = uvc_video_encode_data(video, buf, mem, len);
+ len -= ret;
+
+ /* Sync sg buffer len , default is 1024 or 3072 */
+ sg_set_buf(&req->sg[sg_idx], sg_virt(&req->sg[sg_idx]),
+ video->req_size - len);
+ ttllen += video->req_size - len;
+
+ if (buf->bytesused == video->queue.buf_used) {
+ video->queue.buf_used = 0;
+ buf->state = UVC_BUF_STATE_DONE;
+ uvcg_queue_next_buffer(&video->queue, buf);
+ video->fid ^= UVC_STREAM_FID;
+ break;
+ }
+ }
+ req->num_sgs = sg_idx + 1;
+ sg_mark_end(&req->sg[sg_idx]);
+ req->length = ttllen;
+#else
void *mem = req->buf;
int len = video->req_size;
- int ret;
/* Add the header. */
ret = uvc_video_encode_header(video, buf, mem, len);
@@ -123,12 +161,33 @@
uvcg_queue_next_buffer(&video->queue, buf);
video->fid ^= UVC_STREAM_FID;
}
+#endif
}
/* --------------------------------------------------------------------------
* Request handling
*/
+static int uvcg_video_ep_queue(struct uvc_video *video, struct usb_request *req)
+{
+ int ret;
+
+ /*
+ * Fixme, this is just to workaround the warning by udc core when the ep
+ * is disabled, this may happens when the uvc application is still
+ * streaming new data while the uvc gadget driver has already recieved
+ * the streamoff but the streamoff event is not yet received by the app
+ */
+ if (!video->ep->enabled)
+ return -EINVAL;
+
+ ret = usb_ep_queue(video->ep, req, GFP_ATOMIC);
+ if (ret < 0)
+ printk(KERN_INFO "Failed to queue request (%d).\n", ret);
+
+ return ret;
+}
+
/*
* I somehow feel that synchronisation won't be easy to achieve here. We have
* three events that control USB requests submission:
@@ -190,22 +249,26 @@
spin_unlock_irqrestore(&video->queue.irqlock, flags);
goto requeue;
}
-
+#ifdef UVC_SG_REQ
+ sg_unmark_end(&req->sg[req->num_sgs - 1]);
+#endif
video->encode(req, video, buf);
- if ((ret = usb_ep_queue(ep, req, GFP_ATOMIC)) < 0) {
- printk(KERN_INFO "Failed to queue request (%d).\n", ret);
- usb_ep_set_halt(ep);
- spin_unlock_irqrestore(&video->queue.irqlock, flags);
+ ret = uvcg_video_ep_queue(video, req);
+ spin_unlock_irqrestore(&video->queue.irqlock, flags);
+
+ if (ret < 0) {
uvcg_queue_cancel(queue, 0);
goto requeue;
}
- spin_unlock_irqrestore(&video->queue.irqlock, flags);
return;
requeue:
spin_lock_irqsave(&video->req_lock, flags);
+#ifdef UVC_SG_REQ
+ sg_unmark_end(&req->sg[req->num_sgs - 1]);
+#endif
list_add_tail(&req->list, &video->req_free);
spin_unlock_irqrestore(&video->req_lock, flags);
}
@@ -214,9 +277,22 @@
uvc_video_free_requests(struct uvc_video *video)
{
unsigned int i;
+#ifdef UVC_SG_REQ
+ unsigned int sg_idx;
+#endif
for (i = 0; i < UVC_NUM_REQUESTS; ++i) {
if (video->req[i]) {
+#ifdef UVC_SG_REQ
+ for (sg_idx = 0; sg_idx < video->num_sgs; sg_idx++)
+ if (sg_page(&video->req[i]->sg[sg_idx]))
+ kfree(sg_virt(&video->req[i]->sg[sg_idx]));
+
+ if (video->req[i]->sg) {
+ kfree(video->req[i]->sg);
+ video->req[i]->sg = NULL;
+ }
+#endif
usb_ep_free_request(video->ep, video->req[i]);
video->req[i] = NULL;
}
@@ -238,6 +314,11 @@
unsigned int req_size;
unsigned int i;
int ret = -ENOMEM;
+#ifdef UVC_SG_REQ
+ struct scatterlist *sg;
+ unsigned int num_sgs;
+ unsigned int sg_idx;
+#endif
BUG_ON(video->req_size);
@@ -245,6 +326,35 @@
* max_t(unsigned int, video->ep->maxburst, 1)
* (video->ep->mult);
+#ifdef UVC_SG_REQ
+ num_sgs = ((video->imagesize / (req_size - 2)) + 1);
+ video->num_sgs = num_sgs;
+
+ for (i = 0; i < UVC_NUM_REQUESTS; ++i) {
+ sg = kmalloc(num_sgs * sizeof(struct scatterlist), GFP_ATOMIC);
+ if (sg == NULL)
+ goto error;
+ sg_init_table(sg, num_sgs);
+
+ video->req[i] = usb_ep_alloc_request(video->ep, GFP_KERNEL);
+ if (video->req[i] == NULL)
+ goto error;
+
+ for (sg_idx = 0 ; sg_idx < num_sgs ; sg_idx++) {
+ video->sg_buf = kmalloc(req_size, GFP_KERNEL);
+ if (video->sg_buf == NULL)
+ goto error;
+ sg_set_buf(&sg[sg_idx], video->sg_buf, req_size);
+ }
+ video->req[i]->sg = sg;
+ video->req[i]->num_sgs = num_sgs;
+ video->req[i]->length = 0;
+ video->req[i]->complete = uvc_video_complete;
+ video->req[i]->context = video;
+
+ list_add_tail(&video->req[i]->list, &video->req_free);
+ }
+#else
for (i = 0; i < UVC_NUM_REQUESTS; ++i) {
video->req_buffer[i] = kmalloc(req_size, GFP_KERNEL);
if (video->req_buffer[i] == NULL)
@@ -261,7 +371,7 @@
list_add_tail(&video->req[i]->list, &video->req_free);
}
-
+#endif
video->req_size = req_size;
return 0;
@@ -320,15 +430,13 @@
video->encode(req, video, buf);
/* Queue the USB request */
- ret = usb_ep_queue(video->ep, req, GFP_ATOMIC);
+ ret = uvcg_video_ep_queue(video, req);
+ spin_unlock_irqrestore(&queue->irqlock, flags);
+
if (ret < 0) {
- printk(KERN_INFO "Failed to queue request (%d)\n", ret);
- usb_ep_set_halt(video->ep);
- spin_unlock_irqrestore(&queue->irqlock, flags);
uvcg_queue_cancel(queue, 0);
break;
}
- spin_unlock_irqrestore(&queue->irqlock, flags);
}
spin_lock_irqsave(&video->req_lock, flags);
@@ -379,16 +487,22 @@
/*
* Initialize the UVC video stream.
*/
-int uvcg_video_init(struct uvc_video *video)
+int uvcg_video_init(struct uvc_video *video, struct uvc_device *uvc)
{
INIT_LIST_HEAD(&video->req_free);
spin_lock_init(&video->req_lock);
-
+#ifndef CONFIG_GOKE_MC
video->fcc = V4L2_PIX_FMT_YUYV;
+ video->imagesize = 320 * 240 * 2;
video->bpp = 16;
+#else
+ video->fcc = V4L2_PIX_FMT_NV21;
+ video->imagesize = 320 * 240 * 3 / 2; /* YUV420: w*h*1.5 */
+ video->bpp = 12;
+#endif
video->width = 320;
video->height = 240;
- video->imagesize = 320 * 240 * 2;
+ video->uvc = uvc;
/* Initialize the video buffers queue. */
uvcg_queue_init(&video->queue, V4L2_BUF_TYPE_VIDEO_OUTPUT,
diff -urN linux-4.9.37/drivers/usb/gadget/function/uvc_video.h linux-4.9.y/drivers/usb/gadget/function/uvc_video.h
--- linux-4.9.37/drivers/usb/gadget/function/uvc_video.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/gadget/function/uvc_video.h 2021-06-07 13:01:34.000000000 +0300
@@ -19,6 +19,6 @@
int uvcg_video_enable(struct uvc_video *video, int enable);
-int uvcg_video_init(struct uvc_video *video);
+int uvcg_video_init(struct uvc_video *video, struct uvc_device *uvc);
#endif /* __UVC_VIDEO_H__ */
diff -urN linux-4.9.37/drivers/usb/gadget/Kconfig linux-4.9.y/drivers/usb/gadget/Kconfig
--- linux-4.9.37/drivers/usb/gadget/Kconfig 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/gadget/Kconfig 2021-06-07 13:01:34.000000000 +0300
@@ -158,6 +158,9 @@
config USB_U_ETHER
tristate
+config USB_U_AUDIO
+ tristate
+
config USB_F_SERIAL
tristate
@@ -381,6 +384,7 @@
depends on SND
select USB_LIBCOMPOSITE
select SND_PCM
+ select USB_U_AUDIO
select USB_F_UAC2
help
This Audio function is compatible with USB Audio Class
diff -urN linux-4.9.37/drivers/usb/gadget/legacy/audio.c linux-4.9.y/drivers/usb/gadget/legacy/audio.c
--- linux-4.9.37/drivers/usb/gadget/legacy/audio.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/gadget/legacy/audio.c 2021-06-07 13:01:34.000000000 +0300
@@ -229,6 +229,7 @@
uac2_opts->c_chmask = c_chmask;
uac2_opts->c_srate = c_srate;
uac2_opts->c_ssize = c_ssize;
+ uac2_opts->req_number = UAC2_DEF_REQ_NUM;
#else
uac1_opts = container_of(fi_uac1, struct f_uac1_opts, func_inst);
uac1_opts->fn_play = fn_play;
diff -urN linux-4.9.37/drivers/usb/gadget/legacy/Kconfig linux-4.9.y/drivers/usb/gadget/legacy/Kconfig
--- linux-4.9.37/drivers/usb/gadget/legacy/Kconfig 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/gadget/legacy/Kconfig 2021-06-07 13:01:34.000000000 +0300
@@ -56,6 +56,7 @@
select SND_PCM
select USB_F_UAC1 if GADGET_UAC1
select USB_F_UAC2 if !GADGET_UAC1
+ select USB_U_AUDIO if USB_F_UAC2
help
This Gadget Audio driver is compatible with USB Audio Class
specification 2.0. It implements 1 AudioControl interface,
diff -urN linux-4.9.37/drivers/usb/gadget/legacy/multi.c linux-4.9.y/drivers/usb/gadget/legacy/multi.c
--- linux-4.9.37/drivers/usb/gadget/legacy/multi.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/gadget/legacy/multi.c 2021-06-07 13:01:34.000000000 +0300
@@ -162,21 +162,8 @@
if (ret)
goto err_conf;
- f_msg_rndis = usb_get_function(fi_msg);
- if (IS_ERR(f_msg_rndis)) {
- ret = PTR_ERR(f_msg_rndis);
- goto err_fsg;
- }
-
- ret = usb_add_function(c, f_msg_rndis);
- if (ret)
- goto err_run;
-
return 0;
-err_run:
- usb_put_function(f_msg_rndis);
-err_fsg:
- usb_remove_function(c, f_acm_rndis);
+
err_conf:
usb_put_function(f_acm_rndis);
err_func_acm:
@@ -245,16 +232,6 @@
if (ret)
goto err_conf;
- f_msg_multi = usb_get_function(fi_msg);
- if (IS_ERR(f_msg_multi)) {
- ret = PTR_ERR(f_msg_multi);
- goto err_fsg;
- }
-
- ret = usb_add_function(c, f_msg_multi);
- if (ret)
- goto err_run;
-
return 0;
err_run:
usb_put_function(f_msg_multi);
@@ -304,8 +281,7 @@
#ifdef USB_ETH_RNDIS
struct f_rndis_opts *rndis_opts;
#endif
- struct fsg_opts *fsg_opts;
- struct fsg_config config;
+
int status;
if (!can_support_ecm(cdev->gadget)) {
@@ -367,32 +343,6 @@
goto fail0;
}
- /* set up mass storage function */
- fi_msg = usb_get_function_instance("mass_storage");
- if (IS_ERR(fi_msg)) {
- status = PTR_ERR(fi_msg);
- goto fail1;
- }
- fsg_config_from_params(&config, &fsg_mod_data, fsg_num_buffers);
- fsg_opts = fsg_opts_from_func_inst(fi_msg);
-
- fsg_opts->no_configfs = true;
- status = fsg_common_set_num_buffers(fsg_opts->common, fsg_num_buffers);
- if (status)
- goto fail2;
-
- status = fsg_common_set_cdev(fsg_opts->common, cdev, config.can_stall);
- if (status)
- goto fail_set_cdev;
-
- fsg_common_set_sysfs(fsg_opts->common, true);
- status = fsg_common_create_luns(fsg_opts->common, &config);
- if (status)
- goto fail_set_cdev;
-
- fsg_common_set_inquiry_string(fsg_opts->common, config.vendor_name,
- config.product_name);
-
/* allocate string IDs */
status = usb_string_ids_tab(cdev, strings_dev);
if (unlikely(status < 0))
@@ -430,13 +380,6 @@
kfree(otg_desc[0]);
otg_desc[0] = NULL;
fail_string_ids:
- fsg_common_remove_luns(fsg_opts->common);
-fail_set_cdev:
- fsg_common_free_buffers(fsg_opts->common);
-fail2:
- usb_put_function_instance(fi_msg);
-fail1:
- usb_put_function_instance(fi_acm);
fail0:
#ifdef USB_ETH_RNDIS
usb_put_function_instance(fi_rndis);
diff -urN linux-4.9.37/drivers/usb/gadget/legacy/webcam.c linux-4.9.y/drivers/usb/gadget/legacy/webcam.c
--- linux-4.9.37/drivers/usb/gadget/legacy/webcam.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/gadget/legacy/webcam.c 2021-06-07 13:01:34.000000000 +0300
@@ -26,11 +26,11 @@
module_param(streaming_interval, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(streaming_interval, "1 - 16");
-static unsigned int streaming_maxpacket = 1024;
+static unsigned int streaming_maxpacket = 3072;
module_param(streaming_maxpacket, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(streaming_maxpacket, "1 - 1023 (FS), 1 - 3072 (hs/ss)");
-static unsigned int streaming_maxburst;
+static unsigned int streaming_maxburst = 14;
module_param(streaming_maxburst, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(streaming_maxburst, "0 - 15 (ss only)");
@@ -49,6 +49,17 @@
static char webcam_product_label[] = "Webcam gadget";
static char webcam_config_label[] = "Video";
+/* GUID of the UVC H.264 extension unit:
+{A29E7641-DE04-47E3-8B2B-F4341AFF003B} */
+#define GUID_UVCX_H264_XU {0x41, 0x76, 0x9E, 0xA2, 0x04, 0xDE, 0xE3, 0x47, \
+ 0x8B, 0x2B, 0xF4, 0x34, 0x1A, 0xFF, 0x00, 0x3B}
+
+#define UVC_GUID_BSP_CAMERA {0x91, 0x72, 0x1e, 0x9a, 0x43, 0x68, 0x83, 0x46, \
+ 0x6d, 0x92, 0x39, 0xbc, 0x79, 0x06, 0xee, 0x49}
+
+#define UVC_GUID_FORMAT_H264 {0x48, 0x32, 0x36, 0x34, 0x00, 0x00, 0x10, 0x00, \
+ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+
/* string IDs are assigned dynamically */
#define STRING_DESCRIPTION_IDX USB_GADGET_FIRST_AVAIL_IDX
@@ -77,7 +88,7 @@
static struct usb_device_descriptor webcam_device_descriptor = {
.bLength = USB_DT_DEVICE_SIZE,
.bDescriptorType = USB_DT_DEVICE,
- /* .bcdUSB = DYNAMIC */
+ .bcdUSB = cpu_to_le16(0x0200),
.bDeviceClass = USB_CLASS_MISC,
.bDeviceSubClass = 0x02,
.bDeviceProtocol = 0x01,
@@ -97,7 +108,7 @@
.bLength = UVC_DT_HEADER_SIZE(1),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = UVC_VC_HEADER,
- .bcdUVC = cpu_to_le16(0x0100),
+ .bcdUVC = cpu_to_le16(0x0110),
.wTotalLength = 0, /* dynamic */
.dwClockFrequency = cpu_to_le32(48000000),
.bInCollection = 0, /* dynamic */
@@ -108,7 +119,7 @@
.bLength = UVC_DT_CAMERA_TERMINAL_SIZE(3),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = UVC_VC_INPUT_TERMINAL,
- .bTerminalID = 1,
+ .bTerminalID = 2,
.wTerminalType = cpu_to_le16(0x0201),
.bAssocTerminal = 0,
.iTerminal = 0,
@@ -116,8 +127,8 @@
.wObjectiveFocalLengthMax = cpu_to_le16(0),
.wOcularFocalLength = cpu_to_le16(0),
.bControlSize = 3,
- .bmControls[0] = 2,
- .bmControls[1] = 0,
+ .bmControls[0] = 0x1a,
+ .bmControls[1] = 0x00,
.bmControls[2] = 0,
};
@@ -125,15 +136,45 @@
.bLength = UVC_DT_PROCESSING_UNIT_SIZE(2),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = UVC_VC_PROCESSING_UNIT,
- .bUnitID = 2,
+ .bUnitID = 5,
.bSourceID = 1,
.wMaxMultiplier = cpu_to_le16(16*1024),
.bControlSize = 2,
- .bmControls[0] = 1,
- .bmControls[1] = 0,
+ .bmControls[0] = 0xff,
+ .bmControls[1] = 0xff,
.iProcessing = 0,
};
+static const struct UVC_EXTENSION_UNIT_DESCRIPTOR(1, 2) uvc_xu_h264_desc = {
+ .bLength = UVC_DT_EXTENSION_UNIT_SIZE(1, 2),
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = UVC_VC_EXTENSION_UNIT,
+ .bUnitID = 10,
+ .guidExtensionCode = GUID_UVCX_H264_XU,
+ .bNumControls = 15,
+ .bNrInPins = 1,
+ .baSourceID[0] = 2,
+ .bControlSize = 2,
+ .bmControls[0] = 0xff,
+ .bmControls[1] = 0xff,
+ .iExtension = 0,
+};
+
+static const struct UVC_EXTENSION_UNIT_DESCRIPTOR(1, 2) uvc_xu_camera_desc = {
+ .bLength = UVC_DT_EXTENSION_UNIT_SIZE(1, 2),
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = UVC_VC_EXTENSION_UNIT,
+ .bUnitID = 0x11,
+ .guidExtensionCode = UVC_GUID_BSP_CAMERA,
+ .bNumControls = 15,
+ .bNrInPins = 1,
+ .baSourceID[0] = 10,
+ .bControlSize = 2,
+ .bmControls[0] = 0xff,
+ .bmControls[1] = 0xff,
+ .iExtension = 0,
+};
+
static const struct uvc_output_terminal_descriptor uvc_output_terminal = {
.bLength = UVC_DT_OUTPUT_TERMINAL_SIZE,
.bDescriptorType = USB_DT_CS_INTERFACE,
@@ -141,7 +182,7 @@
.bTerminalID = 3,
.wTerminalType = cpu_to_le16(0x0101),
.bAssocTerminal = 0,
- .bSourceID = 2,
+ .bSourceID = 0x11,
.iTerminal = 0,
};
@@ -169,11 +210,18 @@
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = UVC_VS_FORMAT_UNCOMPRESSED,
.bFormatIndex = 1,
- .bNumFrameDescriptors = 2,
+ .bNumFrameDescriptors = 3,
+#ifndef CONFIG_GOKE_MC
.guidFormat =
{ 'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00,
0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71},
.bBitsPerPixel = 16,
+#else
+ .guidFormat = {
+ 'N', 'V', '2', '1', 0x00, 0x00, 0x10, 0x00,
+ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71},
+ .bBitsPerPixel = 12,
+#endif
.bDefaultFrameIndex = 1,
.bAspectRatioX = 0,
.bAspectRatioY = 0,
@@ -184,22 +232,24 @@
DECLARE_UVC_FRAME_UNCOMPRESSED(1);
DECLARE_UVC_FRAME_UNCOMPRESSED(3);
-static const struct UVC_FRAME_UNCOMPRESSED(3) uvc_frame_yuv_360p = {
- .bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE(3),
+static const struct UVC_FRAME_UNCOMPRESSED(1) uvc_frame_yuv_360p = {
+ .bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE(1),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = UVC_VS_FRAME_UNCOMPRESSED,
.bFrameIndex = 1,
.bmCapabilities = 0,
.wWidth = cpu_to_le16(640),
.wHeight = cpu_to_le16(360),
- .dwMinBitRate = cpu_to_le32(18432000),
+ .dwMinBitRate = cpu_to_le32(55296000),
.dwMaxBitRate = cpu_to_le32(55296000),
+#ifndef CONFIG_GOKE_MC
.dwMaxVideoFrameBufferSize = cpu_to_le32(460800),
- .dwDefaultFrameInterval = cpu_to_le32(666666),
- .bFrameIntervalType = 3,
- .dwFrameInterval[0] = cpu_to_le32(666666),
- .dwFrameInterval[1] = cpu_to_le32(1000000),
- .dwFrameInterval[2] = cpu_to_le32(5000000),
+#else
+ .dwMaxVideoFrameBufferSize = cpu_to_le32(345600),
+#endif
+ .dwDefaultFrameInterval = cpu_to_le32(333333),
+ .bFrameIntervalType = 1,
+ .dwFrameInterval[0] = cpu_to_le32(333333),
};
static const struct UVC_FRAME_UNCOMPRESSED(1) uvc_frame_yuv_720p = {
@@ -212,10 +262,54 @@
.wHeight = cpu_to_le16(720),
.dwMinBitRate = cpu_to_le32(29491200),
.dwMaxBitRate = cpu_to_le32(29491200),
+#ifndef CONFIG_GOKE_MC
.dwMaxVideoFrameBufferSize = cpu_to_le32(1843200),
- .dwDefaultFrameInterval = cpu_to_le32(5000000),
+#else
+ .dwMaxVideoFrameBufferSize = cpu_to_le32(1382400),
+#endif
+ .dwDefaultFrameInterval = cpu_to_le32(333333),
+ .bFrameIntervalType = 1,
+ .dwFrameInterval[0] = cpu_to_le32(333333),
+};
+
+static const struct UVC_FRAME_UNCOMPRESSED(1) uvc_frame_yuv_1080p = {
+ .bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE(1),
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = UVC_VS_FRAME_UNCOMPRESSED,
+ .bFrameIndex = 3,
+ .bmCapabilities = 0,
+ .wWidth = cpu_to_le16(1920),
+ .wHeight = cpu_to_le16(1080),
+ .dwMinBitRate = cpu_to_le32(29491200),
+ .dwMaxBitRate = cpu_to_le32(29491200),
+#ifndef CONFIG_GOKE_MC
+ .dwMaxVideoFrameBufferSize = cpu_to_le32(4147200),
+#else
+ .dwMaxVideoFrameBufferSize = cpu_to_le32(3110400),
+#endif
+ .dwDefaultFrameInterval = cpu_to_le32(333333),
.bFrameIntervalType = 1,
- .dwFrameInterval[0] = cpu_to_le32(5000000),
+ .dwFrameInterval[0] = cpu_to_le32(333333),
+};
+
+static const struct UVC_FRAME_UNCOMPRESSED(1) uvc_frame_yuv_2160p = {
+ .bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE(1),
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = UVC_VS_FRAME_UNCOMPRESSED,
+ .bFrameIndex = 4,
+ .bmCapabilities = 0,
+ .wWidth = cpu_to_le16(3840),
+ .wHeight = cpu_to_le16(2160),
+ .dwMinBitRate = cpu_to_le32(29491200),
+ .dwMaxBitRate = cpu_to_le32(29491200),
+#ifndef CONFIG_GOKE_MC
+ .dwMaxVideoFrameBufferSize = cpu_to_le32(16588800),
+#else
+ .dwMaxVideoFrameBufferSize = cpu_to_le32(12441600),
+#endif
+ .dwDefaultFrameInterval = cpu_to_le32(333333),
+ .bFrameIntervalType = 1,
+ .dwFrameInterval[0] = cpu_to_le32(333333),
};
static const struct uvc_format_mjpeg uvc_format_mjpg = {
@@ -223,7 +317,7 @@
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = UVC_VS_FORMAT_MJPEG,
.bFormatIndex = 2,
- .bNumFrameDescriptors = 2,
+ .bNumFrameDescriptors = 4,
.bmFlags = 0,
.bDefaultFrameIndex = 1,
.bAspectRatioX = 0,
@@ -235,22 +329,20 @@
DECLARE_UVC_FRAME_MJPEG(1);
DECLARE_UVC_FRAME_MJPEG(3);
-static const struct UVC_FRAME_MJPEG(3) uvc_frame_mjpg_360p = {
- .bLength = UVC_DT_FRAME_MJPEG_SIZE(3),
+static const struct UVC_FRAME_MJPEG(1) uvc_frame_mjpg_360p = {
+ .bLength = UVC_DT_FRAME_MJPEG_SIZE(1),
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = UVC_VS_FRAME_MJPEG,
.bFrameIndex = 1,
.bmCapabilities = 0,
.wWidth = cpu_to_le16(640),
.wHeight = cpu_to_le16(360),
- .dwMinBitRate = cpu_to_le32(18432000),
- .dwMaxBitRate = cpu_to_le32(55296000),
+ .dwMinBitRate = cpu_to_le32(10240000),
+ .dwMaxBitRate = cpu_to_le32(10240000),
.dwMaxVideoFrameBufferSize = cpu_to_le32(460800),
- .dwDefaultFrameInterval = cpu_to_le32(666666),
- .bFrameIntervalType = 3,
- .dwFrameInterval[0] = cpu_to_le32(666666),
- .dwFrameInterval[1] = cpu_to_le32(1000000),
- .dwFrameInterval[2] = cpu_to_le32(5000000),
+ .dwDefaultFrameInterval = cpu_to_le32(333333),
+ .bFrameIntervalType = 1,
+ .dwFrameInterval[0] = cpu_to_le32(333333),
};
static const struct UVC_FRAME_MJPEG(1) uvc_frame_mjpg_720p = {
@@ -261,12 +353,125 @@
.bmCapabilities = 0,
.wWidth = cpu_to_le16(1280),
.wHeight = cpu_to_le16(720),
- .dwMinBitRate = cpu_to_le32(29491200),
- .dwMaxBitRate = cpu_to_le32(29491200),
+ .dwMinBitRate = cpu_to_le32(20480000),
+ .dwMaxBitRate = cpu_to_le32(20480000),
.dwMaxVideoFrameBufferSize = cpu_to_le32(1843200),
- .dwDefaultFrameInterval = cpu_to_le32(5000000),
+ .dwDefaultFrameInterval = cpu_to_le32(333333),
.bFrameIntervalType = 1,
- .dwFrameInterval[0] = cpu_to_le32(5000000),
+ .dwFrameInterval[0] = cpu_to_le32(333333),
+};
+
+static const struct UVC_FRAME_MJPEG(1) uvc_frame_mjpg_1080p = {
+ .bLength = UVC_DT_FRAME_MJPEG_SIZE(1),
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = UVC_VS_FRAME_MJPEG,
+ .bFrameIndex = 3,
+ .bmCapabilities = 0,
+ .wWidth = cpu_to_le16(1920),
+ .wHeight = cpu_to_le16(1080),
+ .dwMinBitRate = cpu_to_le32(40960000),
+ .dwMaxBitRate = cpu_to_le32(40960000),
+ .dwMaxVideoFrameBufferSize = cpu_to_le32(4147200),
+ .dwDefaultFrameInterval = cpu_to_le32(333333),
+ .bFrameIntervalType = 1,
+ .dwFrameInterval[0] = cpu_to_le32(333333),
+};
+
+static const struct UVC_FRAME_MJPEG(1) uvc_frame_mjpg_2160p = {
+ .bLength = UVC_DT_FRAME_MJPEG_SIZE(1),
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = UVC_VS_FRAME_MJPEG,
+ .bFrameIndex = 4,
+ .bmCapabilities = 0,
+ .wWidth = cpu_to_le16(3840),
+ .wHeight = cpu_to_le16(2160),
+ .dwMinBitRate = cpu_to_le32(61440000),
+ .dwMaxBitRate = cpu_to_le32(61440000),
+ .dwMaxVideoFrameBufferSize = cpu_to_le32(16588800),
+ .dwDefaultFrameInterval = cpu_to_le32(333333),
+ .bFrameIntervalType = 1,
+ .dwFrameInterval[0] = cpu_to_le32(333333),
+};
+
+static const struct uvc_frame_based_format_desc uvc_frame_based_format_desc = {
+ .bLength = UVC_DT_FRAME_BASED_FORMAT_SIZE,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = UVC_VS_FORMAT_FRAME_BASED,
+ .bFormatIndex = 3,
+ .bNumFrameDescriptors = 4,
+ .guidFormat = UVC_GUID_FORMAT_H264,
+ .bBitsPerPixel = 16,
+ .bDefaultFrameIndex = 1,
+ .bAspectRatioX = 0,
+ .bAspectRatioY = 0,
+ .bmInterfaceFlags = 0,
+ .bCopyProtect = 0,
+ .bVariableSize = 1,
+};
+DECLARE_UVC_FRAME_BASED(1);
+static const struct UVC_FRAME_BASED(1) uvc_frame_based_360p = {
+ .bLength = UVC_DT_FRAME_BASED_FRAME_SIZE(1),
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = UVC_VS_FRAME_FRAME_BASED,
+ .bFrameIndex = 1,
+ .bmCapabilities = 0,
+ .wWidth = cpu_to_le16(640),
+ .wHeight = cpu_to_le16(360),
+ .dwMinBitRate = cpu_to_le32(8192000),
+ .dwMaxBitRate = cpu_to_le32(8192000),
+ .dwDefaultFrameInterval = cpu_to_le32(333333),
+ .bFrameIntervalType = 1,
+ .dwBytesPerLine = 0,
+ .dwFrameInterval[0] = cpu_to_le32(333333),
+};
+
+static const struct UVC_FRAME_BASED(1) uvc_frame_based_720p = {
+ .bLength = UVC_DT_FRAME_BASED_FRAME_SIZE(1),
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = UVC_VS_FRAME_FRAME_BASED,
+ .bFrameIndex = 2,
+ .bmCapabilities = 0,
+ .wWidth = cpu_to_le16(1280),
+ .wHeight = cpu_to_le16(720),
+ .dwMinBitRate = cpu_to_le32(10240000),
+ .dwMaxBitRate = cpu_to_le32(10240000),
+ .dwDefaultFrameInterval = cpu_to_le32(333333),
+ .bFrameIntervalType = 1,
+ .dwBytesPerLine = 0,
+ .dwFrameInterval[0] = cpu_to_le32(333333),
+};
+
+static const struct UVC_FRAME_BASED(1) uvc_frame_based_1080p = {
+ .bLength = UVC_DT_FRAME_BASED_FRAME_SIZE(1),
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = UVC_VS_FRAME_FRAME_BASED,
+ .bFrameIndex = 3,
+ .bmCapabilities = 0,
+ .wWidth = cpu_to_le16(1920),
+ .wHeight = cpu_to_le16(1080),
+ .dwMinBitRate = cpu_to_le32(15360000),
+ .dwMaxBitRate = cpu_to_le32(15360000),
+ .dwDefaultFrameInterval = cpu_to_le32(333333),
+ .bFrameIntervalType = 1,
+ .dwBytesPerLine = 0,
+ .dwFrameInterval[0] = cpu_to_le32(333333),
+};
+
+
+static const struct UVC_FRAME_BASED(1) uvc_frame_based_2160p = {
+ .bLength = UVC_DT_FRAME_BASED_FRAME_SIZE(1),
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = UVC_VS_FRAME_FRAME_BASED,
+ .bFrameIndex = 4,
+ .bmCapabilities = 0,
+ .wWidth = cpu_to_le16(3840),
+ .wHeight = cpu_to_le16(2160),
+ .dwMinBitRate = cpu_to_le32(30720000),
+ .dwMaxBitRate = cpu_to_le32(30720000),
+ .dwDefaultFrameInterval = cpu_to_le32(333333),
+ .bFrameIntervalType = 1,
+ .dwBytesPerLine = 0,
+ .dwFrameInterval[0] = cpu_to_le32(333333),
};
static const struct uvc_color_matching_descriptor uvc_color_matching = {
@@ -282,6 +487,8 @@
(const struct uvc_descriptor_header *) &uvc_control_header,
(const struct uvc_descriptor_header *) &uvc_camera_terminal,
(const struct uvc_descriptor_header *) &uvc_processing,
+ (const struct uvc_descriptor_header *) &uvc_xu_h264_desc,
+ (const struct uvc_descriptor_header *) &uvc_xu_camera_desc,
(const struct uvc_descriptor_header *) &uvc_output_terminal,
NULL,
};
@@ -290,6 +497,8 @@
(const struct uvc_descriptor_header *) &uvc_control_header,
(const struct uvc_descriptor_header *) &uvc_camera_terminal,
(const struct uvc_descriptor_header *) &uvc_processing,
+ (const struct uvc_descriptor_header *) &uvc_xu_h264_desc,
+ (const struct uvc_descriptor_header *) &uvc_xu_camera_desc,
(const struct uvc_descriptor_header *) &uvc_output_terminal,
NULL,
};
@@ -298,10 +507,19 @@
(const struct uvc_descriptor_header *) &uvc_input_header,
(const struct uvc_descriptor_header *) &uvc_format_yuv,
(const struct uvc_descriptor_header *) &uvc_frame_yuv_360p,
- (const struct uvc_descriptor_header *) &uvc_frame_yuv_720p,
+// (const struct uvc_descriptor_header *) &uvc_frame_yuv_720p,
+// (const struct uvc_descriptor_header *) &uvc_frame_yuv_1080p,
+// (const struct uvc_descriptor_header *) &uvc_frame_yuv_2160p,
(const struct uvc_descriptor_header *) &uvc_format_mjpg,
(const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p,
(const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p,
+ (const struct uvc_descriptor_header *) &uvc_frame_mjpg_1080p,
+ (const struct uvc_descriptor_header *) &uvc_frame_mjpg_2160p,
+ (const struct uvc_descriptor_header *) &uvc_frame_based_format_desc,
+ (const struct uvc_descriptor_header *) &uvc_frame_based_360p,
+ (const struct uvc_descriptor_header *) &uvc_frame_based_720p,
+ (const struct uvc_descriptor_header *) &uvc_frame_based_1080p,
+ (const struct uvc_descriptor_header *) &uvc_frame_based_2160p,
(const struct uvc_descriptor_header *) &uvc_color_matching,
NULL,
};
@@ -310,22 +528,41 @@
(const struct uvc_descriptor_header *) &uvc_input_header,
(const struct uvc_descriptor_header *) &uvc_format_yuv,
(const struct uvc_descriptor_header *) &uvc_frame_yuv_360p,
- (const struct uvc_descriptor_header *) &uvc_frame_yuv_720p,
+// (const struct uvc_descriptor_header *) &uvc_frame_yuv_720p,
+// (const struct uvc_descriptor_header *) &uvc_frame_yuv_1080p,
+// (const struct uvc_descriptor_header *) &uvc_frame_yuv_2160p,
(const struct uvc_descriptor_header *) &uvc_format_mjpg,
(const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p,
(const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p,
+ (const struct uvc_descriptor_header *) &uvc_frame_mjpg_1080p,
+ (const struct uvc_descriptor_header *) &uvc_frame_mjpg_2160p,
+ (const struct uvc_descriptor_header *) &uvc_frame_based_format_desc,
+ (const struct uvc_descriptor_header *) &uvc_frame_based_360p,
+ (const struct uvc_descriptor_header *) &uvc_frame_based_720p,
+ (const struct uvc_descriptor_header *) &uvc_frame_based_1080p,
+ (const struct uvc_descriptor_header *) &uvc_frame_based_2160p,
(const struct uvc_descriptor_header *) &uvc_color_matching,
NULL,
};
+
static const struct uvc_descriptor_header * const uvc_ss_streaming_cls[] = {
(const struct uvc_descriptor_header *) &uvc_input_header,
(const struct uvc_descriptor_header *) &uvc_format_yuv,
(const struct uvc_descriptor_header *) &uvc_frame_yuv_360p,
(const struct uvc_descriptor_header *) &uvc_frame_yuv_720p,
+ (const struct uvc_descriptor_header *) &uvc_frame_yuv_1080p,
+// (const struct uvc_descriptor_header *) &uvc_frame_yuv_2160p,
(const struct uvc_descriptor_header *) &uvc_format_mjpg,
(const struct uvc_descriptor_header *) &uvc_frame_mjpg_360p,
(const struct uvc_descriptor_header *) &uvc_frame_mjpg_720p,
+ (const struct uvc_descriptor_header *) &uvc_frame_mjpg_1080p,
+ (const struct uvc_descriptor_header *) &uvc_frame_mjpg_2160p,
+ (const struct uvc_descriptor_header *) &uvc_frame_based_format_desc,
+ (const struct uvc_descriptor_header *) &uvc_frame_based_360p,
+ (const struct uvc_descriptor_header *) &uvc_frame_based_720p,
+ (const struct uvc_descriptor_header *) &uvc_frame_based_1080p,
+ (const struct uvc_descriptor_header *) &uvc_frame_based_2160p,
(const struct uvc_descriptor_header *) &uvc_color_matching,
NULL,
};
diff -urN linux-4.9.37/drivers/usb/gadget/udc/core.c linux-4.9.y/drivers/usb/gadget/udc/core.c
--- linux-4.9.37/drivers/usb/gadget/udc/core.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/gadget/udc/core.c 2021-06-07 13:01:34.000000000 +0300
@@ -966,15 +966,6 @@
if (udc)
sysfs_notify(&udc->dev.kobj, NULL, "state");
}
-
-void usb_gadget_set_state(struct usb_gadget *gadget,
- enum usb_device_state state)
-{
- gadget->state = state;
- schedule_work(&gadget->work);
-}
-EXPORT_SYMBOL_GPL(usb_gadget_set_state);
-
/* ------------------------------------------------------------------------- */
static void usb_udc_connect_control(struct usb_udc *udc)
@@ -985,6 +976,24 @@
usb_gadget_disconnect(udc->gadget);
}
+/* should be called with udc_lock held */
+static int check_pending_gadget_drivers(struct usb_udc *udc)
+{
+ struct usb_gadget_driver *driver;
+ int ret = 0;
+
+ list_for_each_entry(driver, &gadget_driver_pending_list, pending)
+ if (!driver->udc_name || strcmp(driver->udc_name,
+ dev_name(&udc->dev)) == 0) {
+ ret = udc_bind_to_driver(udc, driver);
+ if (ret != -EPROBE_DEFER)
+ list_del(&driver->pending);
+ break;
+ }
+
+ return ret;
+}
+
/**
* usb_udc_vbus_handler - updates the udc core vbus status, and try to
* connect or disconnect gadget
@@ -1005,6 +1014,15 @@
}
EXPORT_SYMBOL_GPL(usb_udc_vbus_handler);
+/* ------------------------------------------------------------------------- */
+void usb_gadget_set_state(struct usb_gadget *gadget,
+ enum usb_device_state state)
+{
+ gadget->state = state;
+}
+EXPORT_SYMBOL_GPL(usb_gadget_set_state);
+/* ------------------------------------------------------------------------- */
+
/**
* usb_gadget_udc_reset - notifies the udc core that bus reset occurs
* @gadget: The gadget which bus reset occurs
@@ -1080,24 +1098,6 @@
dev_vdbg(dev, "%s\n", __func__);
}
-/* should be called with udc_lock held */
-static int check_pending_gadget_drivers(struct usb_udc *udc)
-{
- struct usb_gadget_driver *driver;
- int ret = 0;
-
- list_for_each_entry(driver, &gadget_driver_pending_list, pending)
- if (!driver->udc_name || strcmp(driver->udc_name,
- dev_name(&udc->dev)) == 0) {
- ret = udc_bind_to_driver(udc, driver);
- if (ret != -EPROBE_DEFER)
- list_del(&driver->pending);
- break;
- }
-
- return ret;
-}
-
/**
* usb_add_gadget_udc_release - adds a new gadget to the udc class driver list
* @parent: the parent device to this udc. Usually the controller driver's
diff -urN linux-4.9.37/drivers/usb/gadget/udc/trace.h linux-4.9.y/drivers/usb/gadget/udc/trace.h
--- linux-4.9.37/drivers/usb/gadget/udc/trace.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/gadget/udc/trace.h 2021-06-07 13:01:34.000000000 +0300
@@ -236,6 +236,7 @@
__field(unsigned, short_not_ok)
__field(int, status)
__field(int, ret)
+ __field(struct usb_request *, req)
),
TP_fast_assign(
snprintf(__get_str(name), UDC_TRACE_STR_MAX, "%s", ep->name);
@@ -249,9 +250,10 @@
__entry->short_not_ok = req->short_not_ok;
__entry->status = req->status;
__entry->ret = ret;
+ __entry->req = req;
),
- TP_printk("%s: length %d/%d sgs %d/%d stream %d %s%s%s status %d --> %d",
- __get_str(name), __entry->actual, __entry->length,
+ TP_printk("%s: req %p length %d/%d sgs %d/%d stream %d %s%s%s status %d --> %d",
+ __get_str(name),__entry->req, __entry->actual, __entry->length,
__entry->num_mapped_sgs, __entry->num_sgs, __entry->stream_id,
__entry->zero ? "Z" : "z",
__entry->short_not_ok ? "S" : "s",
diff -urN linux-4.9.37/drivers/usb/host/xhci.c linux-4.9.y/drivers/usb/host/xhci.c
--- linux-4.9.37/drivers/usb/host/xhci.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/host/xhci.c 2021-06-07 13:01:34.000000000 +0300
@@ -4131,7 +4131,7 @@
xhci_dbg(xhci, "%s port %d USB2 hardware LPM\n",
enable ? "enable" : "disable", port_num + 1);
- if (enable) {
+ if (enable && !(xhci->quirks & XHCI_HW_LPM_DISABLE)) {
/* Host supports BESL timeout instead of HIRD */
if (udev->usb2_hw_lpm_besl_capable) {
/* if device doesn't have a preferred BESL value use a
diff -urN linux-4.9.37/drivers/usb/host/xhci.h linux-4.9.y/drivers/usb/host/xhci.h
--- linux-4.9.37/drivers/usb/host/xhci.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/host/xhci.h 2021-06-07 13:01:34.000000000 +0300
@@ -1661,6 +1661,7 @@
#define XHCI_BROKEN_PORT_PED (1 << 25)
#define XHCI_LIMIT_ENDPOINT_INTERVAL_7 (1 << 26)
#define XHCI_U2_DISABLE_WAKE (1 << 27)
+#define XHCI_HW_LPM_DISABLE (1 << 29)
unsigned int num_active_eps;
unsigned int limit_active_eps;
diff -urN linux-4.9.37/drivers/usb/host/xhci-hub.c linux-4.9.y/drivers/usb/host/xhci-hub.c
--- linux-4.9.37/drivers/usb/host/xhci-hub.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/host/xhci-hub.c 2021-06-07 13:01:34.000000000 +0300
@@ -1049,13 +1049,15 @@
break;
}
- /* Software should not attempt to set
- * port link state above '3' (U3) and the port
- * must be enabled.
- */
- if ((temp & PORT_PE) == 0 ||
- (link_state > USB_SS_PORT_LS_U3)) {
- xhci_warn(xhci, "Cannot set link state.\n");
+ /* port must be enabled */
+ if (!(temp & PORT_PE)) {
+ retval = -ENODEV;
+ break;
+ }
+ /* Can't set port link state above '3' (U3)*/
+ if (link_state > USB_SS_PORT_LS_U3) {
+ xhci_warn(xhci, "Cannot set port %d link state %d\n",
+ wIndex, link_state);
goto error;
}
diff -urN linux-4.9.37/drivers/usb/host/xhci-mem.c linux-4.9.y/drivers/usb/host/xhci-mem.c
--- linux-4.9.37/drivers/usb/host/xhci-mem.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/host/xhci-mem.c 2021-06-07 13:01:34.000000000 +0300
@@ -1404,7 +1404,7 @@
if (udev->speed == USB_SPEED_HIGH &&
(usb_endpoint_xfer_isoc(&ep->desc) ||
usb_endpoint_xfer_int(&ep->desc)))
- return (usb_endpoint_maxp(&ep->desc) & 0x1800) >> 11;
+ return usb_endpoint_maxp_mult(&ep->desc) - 1;
return 0;
}
@@ -1450,9 +1450,9 @@
return le16_to_cpu(ep->ss_ep_comp.wBytesPerInterval);
max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc));
- max_burst = (usb_endpoint_maxp(&ep->desc) & 0x1800) >> 11;
+ max_burst = usb_endpoint_maxp_mult(&ep->desc);
/* A 0 in max burst means 1 transfer per ESIT */
- return max_packet * (max_burst + 1);
+ return max_packet * max_burst;
}
/* Set up an endpoint with one ring segment. Do not allocate stream rings.
diff -urN linux-4.9.37/drivers/usb/host/xhci-plat.c linux-4.9.y/drivers/usb/host/xhci-plat.c
--- linux-4.9.37/drivers/usb/host/xhci-plat.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/host/xhci-plat.c 2021-06-07 13:01:34.000000000 +0300
@@ -220,6 +220,9 @@
goto disable_clk;
}
+ if (device_property_read_bool(&pdev->dev, "usb2-lpm-disable"))
+ xhci->quirks |= XHCI_HW_LPM_DISABLE;
+
if (device_property_read_bool(&pdev->dev, "usb3-lpm-capable"))
xhci->quirks |= XHCI_LPM_SUPPORT;
diff -urN linux-4.9.37/drivers/usb/Makefile linux-4.9.y/drivers/usb/Makefile
--- linux-4.9.37/drivers/usb/Makefile 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/usb/Makefile 2021-06-07 13:01:34.000000000 +0300
@@ -7,7 +7,7 @@
obj-$(CONFIG_USB) += core/
obj-$(CONFIG_USB_SUPPORT) += phy/
-obj-$(CONFIG_USB_DWC3) += dwc3/
+obj-$(CONFIG_ARCH_GOKE) += dwc3/
obj-$(CONFIG_USB_DWC2) += dwc2/
obj-$(CONFIG_USB_ISP1760) += isp1760/
diff -urN linux-4.9.37/drivers/video/fbdev/core/fbmem.c linux-4.9.y/drivers/video/fbdev/core/fbmem.c
--- linux-4.9.37/drivers/video/fbdev/core/fbmem.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/video/fbdev/core/fbmem.c 2021-06-07 13:01:34.000000000 +0300
@@ -32,6 +32,7 @@
#include <linux/device.h>
#include <linux/efi.h>
#include <linux/fb.h>
+#include <linux/dma-buf.h>
#include <asm/fb.h>
@@ -1083,7 +1084,24 @@
return ret;
}
EXPORT_SYMBOL(fb_blank);
+#ifdef CONFIG_ARCH_GOKE
+#ifdef CONFIG_DMA_SHARED_BUFFER
+int
+fb_get_dmabuf(struct fb_info *info, int flags)
+{
+ struct dma_buf *dmabuf;
+
+ if (info->fbops->fb_dmabuf_export == NULL)
+ return -ENOTTY;
+
+ dmabuf = info->fbops->fb_dmabuf_export(info);
+ if (IS_ERR(dmabuf))
+ return PTR_ERR(dmabuf);
+ return dma_buf_fd(dmabuf, flags);
+}
+#endif
+#endif /* CONFIG_ARCH_GOKE */
static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
unsigned long arg)
{
@@ -1094,6 +1112,9 @@
struct fb_cmap cmap_from;
struct fb_cmap_user cmap;
struct fb_event event;
+#if defined(CONFIG_ARCH_GOKE) && defined(CONFIG_DMA_SHARED_BUFFER)
+ struct fb_dmabuf_export dmaexp;
+#endif
void __user *argp = (void __user *)arg;
long ret = 0;
@@ -1211,6 +1232,23 @@
unlock_fb_info(info);
console_unlock();
break;
+#if defined(CONFIG_ARCH_GOKE) && defined(CONFIG_DMA_SHARED_BUFFER)
+ case FBIOGET_DMABUF:
+ if (copy_from_user(&dmaexp, argp, sizeof(dmaexp)))
+ return -EFAULT;
+
+ if (!lock_fb_info(info))
+ return -ENODEV;
+ dmaexp.fd = fb_get_dmabuf(info, dmaexp.flags);
+ unlock_fb_info(info);
+
+ if (dmaexp.fd < 0)
+ return dmaexp.fd;
+
+ ret = copy_to_user(argp, &dmaexp, sizeof(dmaexp))
+ ? -EFAULT : 0;
+ break;
+#endif /* CONFIG_ARCH_GOKE */
default:
if (!lock_fb_info(info))
return -ENODEV;
diff -urN linux-4.9.37/drivers/video/logo/.gitignore linux-4.9.y/drivers/video/logo/.gitignore
--- linux-4.9.37/drivers/video/logo/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/video/logo/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,7 +0,0 @@
-#
-# Generated files
-#
-*_mono.c
-*_vga16.c
-*_clut224.c
-*_gray256.c
diff -urN linux-4.9.37/drivers/zorro/.gitignore linux-4.9.y/drivers/zorro/.gitignore
--- linux-4.9.37/drivers/zorro/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/drivers/zorro/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,2 +0,0 @@
-devlist.h
-gen-devlist
diff -urN linux-4.9.37/firmware/cis/.gitignore linux-4.9.y/firmware/cis/.gitignore
--- linux-4.9.37/firmware/cis/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/firmware/cis/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-*.cis
diff -urN linux-4.9.37/firmware/.gitignore linux-4.9.y/firmware/.gitignore
--- linux-4.9.37/firmware/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/firmware/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,6 +0,0 @@
-*.gen.S
-*.fw
-*.bin
-*.csp
-*.dsp
-ihex2fw
diff -urN linux-4.9.37/fs/buffer.c linux-4.9.y/fs/buffer.c
--- linux-4.9.37/fs/buffer.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/fs/buffer.c 2021-06-07 13:01:34.000000000 +0300
@@ -1276,10 +1276,17 @@
*/
static void bh_lru_install(struct buffer_head *bh)
{
- struct buffer_head *evictee = NULL;
+#ifdef CONFIG_GOKE_MC
+ struct buffer_head *evictee = bh;
+ struct bh_lru *b;
+ int i;
+#else
+ struct buffer_head *evictee = NULL;
+#endif
check_irqs_on();
bh_lru_lock();
+#ifndef CONFIG_GOKE_MC
if (__this_cpu_read(bh_lrus.bhs[0]) != bh) {
struct buffer_head *bhs[BH_LRU_SIZE];
int in;
@@ -1310,6 +1317,22 @@
if (evictee)
__brelse(evictee);
+#endif
+
+#ifdef CONFIG_GOKE_MC
+ b = this_cpu_ptr(&bh_lrus);
+ for (i = 0; i < BH_LRU_SIZE; i++) {
+ swap(evictee, b->bhs[i]);
+ if (evictee == bh) {
+ bh_lru_unlock();
+ return;
+ }
+ }
+
+ get_bh(bh);
+ bh_lru_unlock();
+ brelse(evictee);
+#endif
}
/*
diff -urN linux-4.9.37/fs/compat_ioctl.c linux-4.9.y/fs/compat_ioctl.c
--- linux-4.9.37/fs/compat_ioctl.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/fs/compat_ioctl.c 2021-06-07 13:01:34.000000000 +0300
@@ -750,9 +750,9 @@
if (!access_ok(VERIFY_READ, udata, sizeof(*udata)))
return -EFAULT;
- if (__copy_in_user(&tdata->read_write, &udata->read_write, 2 * sizeof(u8)))
+ if (copy_in_user(&tdata->read_write, &udata->read_write, 2 * sizeof(u8)))
return -EFAULT;
- if (__copy_in_user(&tdata->size, &udata->size, 2 * sizeof(u32)))
+ if (copy_in_user(&tdata->size, &udata->size, 2 * sizeof(u32)))
return -EFAULT;
if (__get_user(datap, &udata->data) ||
__put_user(compat_ptr(datap), &tdata->data))
diff -urN linux-4.9.37/fs/dcache.c linux-4.9.y/fs/dcache.c
--- linux-4.9.37/fs/dcache.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/fs/dcache.c 2021-06-07 13:01:34.000000000 +0300
@@ -1137,7 +1137,12 @@
this_cpu_sub(nr_dentry_unused, freed);
shrink_dentry_list(&dispose);
- } while (freed > 0);
+#ifdef CONFIG_GOKE_MC
+ cond_resched();
+ } while (list_lru_count(&sb->s_dentry_lru) > 0);
+#else
+ } while (freed > 0);
+#endif
}
EXPORT_SYMBOL(shrink_dcache_sb);
diff -urN linux-4.9.37/fs/fat/dir.c linux-4.9.y/fs/fat/dir.c
--- linux-4.9.37/fs/fat/dir.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/fs/fat/dir.c 2021-06-07 13:01:34.000000000 +0300
@@ -782,6 +782,388 @@
ret = buf.result;
return ret;
}
+#ifdef CONFIG_GOKE_MC
+/*
+ * This is the "fatfilldirall_t" function type,
+ * used by fat_ioctl_filldirall to let
+ * the kernel specify what kind of dirent layout it wants to have.
+ * This allows the kernel to read directories into kernel space or
+ * to have different dirent layouts depending on the binary type.
+ */
+typedef int (*fatfilldirall_t)(void *__buf, const char *name,
+ int name_len, loff_t offset, u64 ino,
+ unsigned int d_type, struct msdos_dir_entry *de,
+ char *d_createtime);
+struct fatdirall_context {
+ const fatfilldirall_t actor;
+ loff_t pos;
+};
+
+struct fat_ioctl_filldirall_callback {
+ struct fatdirall_context ctx;
+ struct fat_direntall __user *current_dir;
+ struct fat_direntall __user *previous;
+ int count;
+ int usecount;
+ int error;
+ int result;
+ const char *longname;
+ int long_len;
+ const char *shortname;
+ int short_len;
+};
+
+static inline bool fat_dir_emit(struct fatdirall_context *ctx,
+ const char *name, int namelen,
+ u64 ino, unsigned type,
+ struct msdos_dir_entry *de,
+ char *d_createtime)
+{
+ return ctx->actor(ctx, name, namelen, ctx->pos, ino,
+ type, de, d_createtime) == 0;
+}
+static inline bool fat_dir_emit_dot(struct file *file,
+ struct fatdirall_context *ctx,
+ struct msdos_dir_entry *de,
+ char *d_createtime)
+{
+ return ctx->actor(ctx, ".", 1, ctx->pos,
+ file->f_path.dentry->d_inode->i_ino,
+ DT_DIR, de, d_createtime) == 0;
+}
+static inline bool fat_dir_emit_dotdot(struct file *file,
+ struct fatdirall_context *ctx,
+ struct msdos_dir_entry *de,
+ char *d_createtime)
+{
+ return ctx->actor(ctx, "..", 2, ctx->pos,
+ parent_ino(file->f_path.dentry),
+ DT_DIR, de, d_createtime) == 0;
+}
+
+static inline bool fat_dir_emit_dots(struct file *file,
+ struct fatdirall_context *ctx,
+ struct msdos_dir_entry *de,
+ char *d_createtime)
+{
+ if (ctx->pos == 0) {
+ if (!fat_dir_emit_dot(file, ctx, de, d_createtime))
+ return false;
+ ctx->pos = 1;
+ }
+ if (ctx->pos == 1) {
+ if (!fat_dir_emit_dotdot(file, ctx, de, d_createtime))
+ return false;
+ ctx->pos = 2;
+ }
+ return true;
+}
+
+
+static int __fat_readdirall(struct inode *inode, struct file *file,
+ struct fatdirall_context *ctx, int short_only,
+ struct fat_ioctl_filldirall_callback *both)
+{
+ struct super_block *sb = inode->i_sb;
+ struct msdos_sb_info *sbi = MSDOS_SB(sb);
+ struct buffer_head *bh;
+ struct msdos_dir_entry *de;
+ unsigned char nr_slots;
+ wchar_t *unicode = NULL;
+ unsigned char bufname[FAT_MAX_SHORT_SIZE];
+ int isvfat = sbi->options.isvfat;
+ const char *fill_name = NULL;
+ int fake_offset = 0;
+ loff_t cpos;
+ int short_len = 0, fill_len = 0;
+ int ret = 0;
+ char d_createtime[8];
+
+ mutex_lock(&sbi->s_lock);
+
+ cpos = ctx->pos;
+ /* Fake . and .. for the root directory. */
+ if (inode->i_ino == MSDOS_ROOT_INO) {
+ if (!fat_dir_emit_dots(file, ctx, NULL, NULL))
+ goto out;
+ if (ctx->pos == 2) {
+ fake_offset = 1;
+ cpos = 0;
+ }
+ }
+ if (cpos & (sizeof(struct msdos_dir_entry) - 1)) {
+ ret = -ENOENT;
+ goto out;
+ }
+
+ bh = NULL;
+get_new:
+ if (fat_get_entry(inode, &cpos, &bh, &de) == -1)
+ goto end_of_dir;
+parse_record:
+ nr_slots = 0;
+ /*
+ * Check for long filename entry, but if short_only, we don't
+ * need to parse long filename.
+ */
+ if (isvfat && !short_only) {
+ if (de->name[0] == DELETED_FLAG)
+ goto record_end;
+ if (de->attr != ATTR_EXT && (de->attr & ATTR_VOLUME))
+ goto record_end;
+ if (de->attr != ATTR_EXT && IS_FREE(de->name))
+ goto record_end;
+ } else {
+ if ((de->attr & ATTR_VOLUME) || IS_FREE(de->name))
+ goto record_end;
+ }
+
+ if (isvfat && de->attr == ATTR_EXT) {
+ int status = fat_parse_long(inode, &cpos, &bh, &de,
+ &unicode, &nr_slots);
+ if (status < 0) {
+ ctx->pos = cpos;
+ ret = status;
+ goto out;
+ } else if (status == PARSE_INVALID)
+ goto record_end;
+ else if (status == PARSE_NOT_LONGNAME)
+ goto parse_record;
+ else if (status == PARSE_EOF)
+ goto end_of_dir;
+
+ if (nr_slots) {
+ void *longname = unicode + FAT_MAX_UNI_CHARS;
+ int size = PATH_MAX - FAT_MAX_UNI_SIZE;
+ int len = fat_uni_to_x8(sb, unicode, longname, size);
+
+ fill_name = longname;
+ fill_len = len;
+
+ short_len = fat_parse_short(sb, de, bufname,
+ sbi->options.dotsOK);
+ if (short_len == 0)
+ goto record_end;
+
+ /* hack for fat_ioctl_filldir() */
+ both->longname = fill_name;
+ both->long_len = fill_len;
+ both->shortname = bufname;
+ both->short_len = short_len;
+ fill_name = NULL;
+ fill_len = 0;
+ goto start_filldir;
+ }
+ }
+
+ short_len = fat_parse_short(sb, de, bufname, sbi->options.dotsOK);
+ if (short_len == 0)
+ goto record_end;
+
+ fill_name = bufname;
+ fill_len = short_len;
+
+start_filldir:
+ if (!fake_offset)
+ ctx->pos = cpos - (nr_slots + 1)
+ * sizeof(struct msdos_dir_entry);
+
+ memset(d_createtime, 0, 8);
+ fat_time_fat2str(sbi, d_createtime, de->ctime,
+ de->cdate, de->ctime_cs);
+
+ if (!memcmp(de->name, MSDOS_DOT, MSDOS_NAME)) {
+ if (!fat_dir_emit_dot(file, ctx, de, d_createtime))
+ goto fill_failed;
+ } else if (!memcmp(de->name, MSDOS_DOTDOT, MSDOS_NAME)) {
+ if (!fat_dir_emit_dotdot(file, ctx, de, d_createtime))
+ goto fill_failed;
+ } else {
+ unsigned long inum;
+ loff_t i_pos = fat_make_i_pos(sb, bh, de);
+ struct inode *tmp = fat_iget(sb, i_pos);
+
+ if (tmp) {
+ inum = tmp->i_ino;
+ iput(tmp);
+ } else
+ inum = iunique(sb, MSDOS_ROOT_INO);
+ if (!fat_dir_emit(ctx, fill_name, fill_len, inum,
+ (de->attr & ATTR_DIR) ? DT_DIR : DT_REG,
+ de, d_createtime))
+ goto fill_failed;
+ }
+
+record_end:
+ fake_offset = 0;
+ ctx->pos = cpos;
+ goto get_new;
+end_of_dir:
+ ctx->pos = cpos;
+fill_failed:
+ brelse(bh);
+ if (unicode)
+ __putname(unicode);
+out:
+ mutex_unlock(&sbi->s_lock);
+ return ret;
+}
+
+static int fat_ioctl_filldirall(void *__buf, const char *name,
+ int name_len, loff_t offset,
+ u64 ino, unsigned int d_type,
+ struct msdos_dir_entry *de,
+ char *d_createtime)
+{
+ struct fat_direntall __user *dirent;
+ struct fat_ioctl_filldirall_callback *buf;
+ unsigned long d_ino;
+ int reclen = 0;
+ const char *longname = NULL;
+ int long_len = 0;
+ const char *shortname = NULL;
+ int short_len = 0;
+
+ buf = (struct fat_ioctl_filldirall_callback *) __buf;
+
+ if (name != NULL) {
+ reclen = ALIGN(offsetof(struct fat_direntall, d_name)
+ + name_len + 2, sizeof(long));
+ } else {
+ longname = buf->longname;
+ long_len = buf->long_len;
+ shortname = buf->shortname;
+ short_len = buf->short_len;
+ reclen = ALIGN(offsetof(struct fat_direntall, d_name)
+ + long_len + 2, sizeof(long));
+ }
+
+ buf->error = -EINVAL; /* only used if we fail.. */
+
+ if (reclen >= buf->count)
+ return -EINVAL;
+
+ d_ino = ino;
+
+ if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) {
+ buf->error = -EOVERFLOW;
+ return -EOVERFLOW;
+ }
+
+ dirent = buf->previous;
+
+ if (dirent) {
+ if (__put_user(offset, &dirent->d_off))
+ goto efault;
+ }
+
+ dirent = buf->current_dir;
+
+ if (__put_user(d_ino, &dirent->d_ino))
+ goto efault;
+
+ if (__put_user(reclen, &dirent->d_reclen))
+ goto efault;
+
+ if (name != NULL) {
+ if (copy_to_user(dirent->d_name, name, name_len))
+ goto efault;
+ if (__put_user(0, dirent->d_name + name_len))
+ goto efault;
+ } else {
+ if (copy_to_user(dirent->d_name, longname, long_len))
+ goto efault;
+ if (__put_user(0, dirent->d_name + long_len))
+ goto efault;
+ }
+
+ if (__put_user(d_type, &dirent->d_type))
+ goto efault;
+
+ if (de != NULL) {
+ u64 u_size = 0;
+ if (copy_to_user(&dirent->d_size, &u_size, sizeof(u64)))
+ goto efault;
+ if (copy_to_user(&dirent->d_size, &de->size, sizeof(u32)))
+ goto efault;
+ }
+
+ if (d_createtime != NULL) {
+ if (copy_to_user(dirent->d_createtime, d_createtime, 8))
+ goto efault;
+ }
+ buf->previous = dirent;
+ dirent = (void __user *)dirent + reclen;
+ buf->current_dir = dirent;
+ buf->count -= reclen;
+ buf->usecount += reclen;
+ return 0;
+efault:
+ buf->error = -EFAULT;
+ return -EFAULT;
+}
+
+
+static int fat_ioctl_readdirall(struct inode *inode, struct file *file,
+ void __user *dirent,
+ int short_only, int both)
+{
+ struct fat_ioctl_filldirall_callback buf = {
+ .ctx.actor = fat_ioctl_filldirall,
+ };
+
+ struct fat_direntall_buf __user *userbuf = dirent;
+ int ret;
+
+ buf.current_dir = &(userbuf->direntall);
+ buf.previous = NULL;
+ buf.error = 0;
+ buf.result = 0;
+ buf.usecount = 0;
+
+ if (get_user(buf.count, &(userbuf->d_count)))
+ return -EFAULT;
+
+ up_read(&inode->i_rwsem);
+ buf.ctx.pos = file->f_pos;
+ ret = -ENOENT;
+ if (!IS_DEADDIR(inode)) {
+ ret = __fat_readdirall(inode, file, &buf.ctx,
+ short_only, both ? &buf : NULL);
+ file->f_pos = buf.ctx.pos;
+ }
+ down_read(&inode->i_rwsem);
+
+ if (__put_user(buf.usecount, &(userbuf->d_usecount)))
+ return -EFAULT;
+ if (ret >= 0)
+ ret = buf.result;
+ return ret;
+}
+
+static int fat_dir_ioctl_readdirall(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ struct inode *inode = filp->f_path.dentry->d_inode;
+ struct fat_direntall_buf __user *direntallbuf;
+ int short_only, both;
+
+ direntallbuf = (struct fat_direntall_buf __user *)arg;
+
+ if (!access_ok(VERIFY_WRITE, direntallbuf,
+ sizeof(struct fat_direntall_buf)))
+ return -EFAULT;
+ if (put_user(0, &(direntallbuf->direntall.d_reclen)))
+ return -EFAULT;
+ if (put_user(0, &(direntallbuf->d_usecount)))
+ return -EFAULT;
+ short_only = 0;
+ both = 1;
+ return fat_ioctl_readdirall(inode, filp, direntallbuf,
+ short_only, both);
+}
+#endif
+
static long fat_dir_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg)
@@ -789,7 +1171,10 @@
struct inode *inode = file_inode(filp);
struct __fat_dirent __user *d1 = (struct __fat_dirent __user *)arg;
int short_only, both;
-
+#ifdef CONFIG_GOKE_MC
+ if (VFAT_IOCTL_READDIR_ALL == cmd)
+ return fat_dir_ioctl_readdirall(filp, cmd, arg);
+#endif
switch (cmd) {
case VFAT_IOCTL_READDIR_SHORT:
short_only = 1;
diff -urN linux-4.9.37/fs/fat/fatent.c linux-4.9.y/fs/fat/fatent.c
--- linux-4.9.37/fs/fat/fatent.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/fs/fat/fatent.c 2021-06-07 13:01:34.000000000 +0300
@@ -380,6 +380,9 @@
int err, n, copy;
err = 0;
+#ifdef CONFIG_GOKE_MC
+ return 0;
+#endif
for (copy = 1; copy < sbi->fats; copy++) {
sector_t backup_fat = sbi->fat_length * copy;
diff -urN linux-4.9.37/fs/fat/fat.h linux-4.9.y/fs/fat/fat.h
--- linux-4.9.37/fs/fat/fat.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/fs/fat/fat.h 2021-06-07 13:01:34.000000000 +0300
@@ -409,6 +409,10 @@
__le16 __time, __le16 __date, u8 time_cs);
extern void fat_time_unix2fat(struct msdos_sb_info *sbi, struct timespec *ts,
__le16 *time, __le16 *date, u8 *time_cs);
+#ifdef CONFIG_GOKE_MC
+extern void fat_time_fat2str(struct msdos_sb_info *sbi, char *d_createtime,
+ __le16 __time, __le16 __date, u8 time_cs);
+#endif
extern int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs);
int fat_cache_init(void);
diff -urN linux-4.9.37/fs/fat/file.c linux-4.9.y/fs/fat/file.c
--- linux-4.9.37/fs/fat/file.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/fs/fat/file.c 2021-06-07 13:01:34.000000000 +0300
@@ -167,8 +167,17 @@
return res ? res : err;
}
+#ifdef CONFIG_GOKE_MC
+int fat_file_flush(struct file *file, fl_owner_t id)
+{
+ struct address_space * mapping = file->f_mapping;
+ struct inode *inode = mapping->host;
+ inode->i_sb->s_op->write_inode(inode, NULL);
+ return 0;
+}
+#endif
const struct file_operations fat_file_operations = {
.llseek = generic_file_llseek,
.read_iter = generic_file_read_iter,
@@ -182,6 +191,9 @@
.fsync = fat_file_fsync,
.splice_read = generic_file_splice_read,
.fallocate = fat_fallocate,
+#ifdef CONFIG_GOKE_MC
+ .flush = fat_file_flush,
+#endif
};
static int fat_cont_expand(struct inode *inode, loff_t size)
@@ -431,7 +443,13 @@
/* use a default check */
return 0;
}
-
+#ifdef CONFIG_GOKE_MC
+void reset_mmu_private(struct inode *inode, loff_t offset)
+{
+ MSDOS_I(inode)->mmu_private = offset;
+ inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
+}
+#endif
#define TIMES_SET_FLAGS (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)
/* valid file mode bits */
#define FAT_VALID_MODE (S_IFREG | S_IFDIR | S_IRWXUGO)
@@ -464,6 +482,7 @@
* hole before it. XXX: this is no longer true with new truncate
* sequence.
*/
+#ifndef CONFIG_GOKE_MC
if (attr->ia_valid & ATTR_SIZE) {
inode_dio_wait(inode);
@@ -474,7 +493,7 @@
attr->ia_valid &= ~ATTR_SIZE;
}
}
-
+#endif
if (((attr->ia_valid & ATTR_UID) &&
(!uid_eq(attr->ia_uid, sbi->options.fs_uid))) ||
((attr->ia_valid & ATTR_GID) &&
@@ -504,6 +523,9 @@
goto out;
down_write(&MSDOS_I(inode)->truncate_lock);
truncate_setsize(inode, attr->ia_size);
+#ifdef CONFIG_GOKE_MC
+ reset_mmu_private(inode, attr->ia_size);
+#endif
fat_truncate_blocks(inode, attr->ia_size);
up_write(&MSDOS_I(inode)->truncate_lock);
}
diff -urN linux-4.9.37/fs/fat/inode.c linux-4.9.y/fs/fat/inode.c
--- linux-4.9.37/fs/fat/inode.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/fs/fat/inode.c 2021-06-07 13:01:34.000000000 +0300
@@ -615,8 +615,9 @@
round_up(MSDOS_I(inode)->mmu_private,
MSDOS_SB(inode->i_sb)->cluster_size)) {
int err;
-
+#ifndef CONFIG_GOKE_MC
fat_truncate_blocks(inode, MSDOS_I(inode)->mmu_private);
+#endif
/* Fallocate results in updating the i_start/iogstart
* for the zero byte file. So, make it return to
* original state during evict and commit it to avoid
@@ -873,15 +874,87 @@
spin_unlock(&sbi->inode_hash_lock);
mark_buffer_dirty(bh);
err = 0;
- if (wait)
+ if (wait) {
err = sync_dirty_buffer(bh);
+ }
brelse(bh);
return err;
}
+#ifdef CONFIG_GOKE_MC
+static int __fat_write_inode_(struct inode *inode, int wait)
+{
+ struct super_block *sb = inode->i_sb;
+ struct msdos_sb_info *sbi = MSDOS_SB(sb);
+ struct buffer_head *bh;
+ struct msdos_dir_entry *raw_entry;
+ loff_t i_pos;
+ sector_t blocknr;
+ int err = 0;
+ int offset;
+
+ if (inode->i_ino == MSDOS_ROOT_INO)
+ return 0;
+
+retry:
+ i_pos = fat_i_pos_read(sbi, inode);
+ if (!i_pos)
+ return 0;
+
+ fat_get_blknr_offset(sbi, i_pos, &blocknr, &offset);
+ bh = sb_bread(sb, blocknr);
+ if (!bh) {
+ fat_msg(sb, KERN_ERR, "unable to read inode block "
+ "for updating (i_pos %lld)", i_pos);
+ return -EIO;
+ }
+ spin_lock(&sbi->inode_hash_lock);
+ if (i_pos != MSDOS_I(inode)->i_pos) {
+ spin_unlock(&sbi->inode_hash_lock);
+ brelse(bh);
+ goto retry;
+ }
+#if 0
+ dump_stack();
+ printk("%s :inode %p/%s, size %llx, logstart %x, blocknr %lx, wait %d\n",
+ __func__, inode, S_ISDIR(inode->i_mode)? "dir":"file", inode->i_size,
+ MSDOS_I(inode)->i_logstart, blocknr, wait);
+#endif
+ raw_entry = &((struct msdos_dir_entry *) (bh->b_data))[offset];
+ if (S_ISDIR(inode->i_mode))
+ raw_entry->size = 0;
+ else {
+ //raw_entry->size = cpu_to_le32(inode->i_size);
+ if ((0 != raw_entry->start) || (0 != raw_entry->starthi)) {
+ spin_unlock(&sbi->inode_hash_lock);
+ goto file_out;
+ }
+ raw_entry->size = cpu_to_le32(inode->i_size);
+ }
+ raw_entry->attr = fat_make_attrs(inode);
+ fat_set_start(raw_entry, MSDOS_I(inode)->i_logstart);
+ fat_time_unix2fat(sbi, &inode->i_mtime, &raw_entry->time,
+ &raw_entry->date, NULL);
+ if (sbi->options.isvfat) {
+ __le16 atime;
+ fat_time_unix2fat(sbi, &inode->i_ctime, &raw_entry->ctime,
+ &raw_entry->cdate, &raw_entry->ctime_cs);
+ fat_time_unix2fat(sbi, &inode->i_atime, &atime,
+ &raw_entry->adate, NULL);
+ }
+ spin_unlock(&sbi->inode_hash_lock);
+ mark_buffer_dirty(bh);
+ if (wait) {
+ err = sync_dirty_buffer(bh);
+ }
+file_out:
+ brelse(bh);
+ return err;
+}
+#endif
static int fat_write_inode(struct inode *inode, struct writeback_control *wbc)
{
- int err;
+ int err = 0;
if (inode->i_ino == MSDOS_FSINFO_INO) {
struct super_block *sb = inode->i_sb;
@@ -889,8 +962,18 @@
mutex_lock(&MSDOS_SB(sb)->s_lock);
err = fat_clusters_flush(sb);
mutex_unlock(&MSDOS_SB(sb)->s_lock);
- } else
- err = __fat_write_inode(inode, wbc->sync_mode == WB_SYNC_ALL);
+ } else {
+#ifdef CONFIG_GOKE_MC
+ if (NULL == wbc){
+ err = __fat_write_inode(inode, 1);
+ }
+ else{
+ err = __fat_write_inode_(inode, wbc->sync_mode == WB_SYNC_ALL);
+ }
+#else
+ err = __fat_write_inode(inode, wbc->sync_mode == WB_SYNC_ALL);
+#endif
+ }
return err;
}
diff -urN linux-4.9.37/fs/fat/misc.c linux-4.9.y/fs/fat/misc.c
--- linux-4.9.37/fs/fat/misc.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/fs/fat/misc.c 2021-06-07 13:01:34.000000000 +0300
@@ -261,6 +261,37 @@
*time_cs = (ts->tv_sec & 1) * 100 + ts->tv_nsec / 10000000;
}
EXPORT_SYMBOL_GPL(fat_time_unix2fat);
+#ifdef CONFIG_GOKE_MC
+void fat_time_fat2str(struct msdos_sb_info *sbi, char *d_createtime,
+ __le16 __time, __le16 __date, u8 time_cs)
+{
+ u16 time = le16_to_cpu(__time), date = le16_to_cpu(__date);
+ time_t day, month, year;
+
+ year = date >> 9;
+ month = max(1, (date >> 5) & 0xf);
+ day = max(1, date & 0x1f) - 1;
+
+ d_createtime[0] = year;
+ d_createtime[1] = month;
+ d_createtime[2] = day;
+ d_createtime[3] = (time >> 11); /*hour*/
+ d_createtime[4] = ((time >> 5) & 0x3f); /*min*/
+ d_createtime[5] = (time & 0x1f); /*second 2s*/
+
+
+ if (!sbi->options.tz_set)
+ d_createtime[4] += sys_tz.tz_minuteswest;
+ else
+ d_createtime[4] -= sbi->options.time_offset;
+
+ if (time_cs) {
+ /*second 1s*/
+ d_createtime[5] += (time_cs / 100);
+ }
+}
+EXPORT_SYMBOL_GPL(fat_time_fat2str);
+#endif
int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs)
{
diff -urN linux-4.9.37/fs/jffs2/compr.c linux-4.9.y/fs/jffs2/compr.c
--- linux-4.9.37/fs/jffs2/compr.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/fs/jffs2/compr.c 2021-06-07 13:01:34.000000000 +0300
@@ -378,6 +378,9 @@
#ifdef CONFIG_JFFS2_LZO
jffs2_lzo_init();
#endif
+#ifdef CONFIG_JFFS2_LZMA
+ jffs2_lzma_init();
+#endif
/* Setting default compression mode */
#ifdef CONFIG_JFFS2_CMODE_NONE
jffs2_compression_mode = JFFS2_COMPR_MODE_NONE;
@@ -401,6 +404,9 @@
int jffs2_compressors_exit(void)
{
/* Unregistering compressors */
+#ifdef CONFIG_JFFS2_LZMA
+ jffs2_lzma_exit();
+#endif
#ifdef CONFIG_JFFS2_LZO
jffs2_lzo_exit();
#endif
diff -urN linux-4.9.37/fs/jffs2/compr.h linux-4.9.y/fs/jffs2/compr.h
--- linux-4.9.37/fs/jffs2/compr.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/fs/jffs2/compr.h 2021-06-07 13:01:34.000000000 +0300
@@ -29,9 +29,15 @@
#define JFFS2_DYNRUBIN_PRIORITY 20
#define JFFS2_LZARI_PRIORITY 30
#define JFFS2_RTIME_PRIORITY 50
+
+#ifdef CONFIG_GOKE_MC
+#define JFFS2_LZMA_PRIORITY 70
+#define JFFS2_ZLIB_PRIORITY 80
+#define JFFS2_LZO_PRIORITY 90
+#else
#define JFFS2_ZLIB_PRIORITY 60
#define JFFS2_LZO_PRIORITY 80
-
+#endif
#define JFFS2_RUBINMIPS_DISABLED /* RUBINs will be used only */
#define JFFS2_DYNRUBIN_DISABLED /* for decompression */
@@ -101,5 +107,9 @@
int jffs2_lzo_init(void);
void jffs2_lzo_exit(void);
#endif
+#ifdef CONFIG_JFFS2_LZMA
+int jffs2_lzma_init(void);
+void jffs2_lzma_exit(void);
+#endif
#endif /* __JFFS2_COMPR_H__ */
diff -urN linux-4.9.37/fs/jffs2/compr_lzma.c linux-4.9.y/fs/jffs2/compr_lzma.c
--- linux-4.9.37/fs/jffs2/compr_lzma.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/jffs2/compr_lzma.c 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,125 @@
+/*
+ * JFFS2 -- Journalling Flash File System, Version 2.
+ *
+ * For licensing information, see the file 'LICENCE' in this directory.
+ *
+ * JFFS2 wrapper to the LZMA C SDK
+ *
+ */
+
+#include <linux/lzma.h>
+#include "compr.h"
+
+#ifdef __KERNEL__
+ static DEFINE_MUTEX(deflate_mutex);
+#endif
+
+CLzmaEncHandle *p;
+Byte propsEncoded[LZMA_PROPS_SIZE];
+SizeT propsSize = sizeof(propsEncoded);
+
+STATIC void lzma_free_workspace(void)
+{
+ LzmaEnc_Destroy(p, &lzma_alloc, &lzma_alloc);
+}
+
+STATIC int INIT lzma_alloc_workspace(CLzmaEncProps *props)
+{
+ if ((p = (CLzmaEncHandle *)LzmaEnc_Create(&lzma_alloc)) == NULL) {
+ PRINT_ERROR("Failed to allocate lzma deflate workspace\n");
+ return -ENOMEM;
+ }
+
+ if (LzmaEnc_SetProps(p, props) != SZ_OK) {
+ lzma_free_workspace();
+ return -1;
+ }
+
+ if (LzmaEnc_WriteProperties(p, propsEncoded, &propsSize) != SZ_OK) {
+ lzma_free_workspace();
+ return -1;
+ }
+
+ return 0;
+}
+
+STATIC int jffs2_lzma_compress(unsigned char *data_in, unsigned char *cpage_out,
+ uint32_t *sourcelen, uint32_t *dstlen)
+{
+ SizeT compress_size = (SizeT)(*dstlen);
+ int ret;
+
+#ifdef __KERNEL__
+ mutex_lock(&deflate_mutex);
+#endif
+
+ ret = LzmaEnc_MemEncode(p, cpage_out, &compress_size, data_in, *sourcelen,
+ 0, NULL, &lzma_alloc, &lzma_alloc);
+
+#ifdef __KERNEL__
+ mutex_unlock(&deflate_mutex);
+#endif
+
+ if (ret != SZ_OK)
+ return -1;
+
+ *dstlen = (uint32_t)compress_size;
+
+ return 0;
+}
+
+STATIC int jffs2_lzma_decompress(unsigned char *data_in, unsigned char *cpage_out,
+ uint32_t srclen, uint32_t destlen)
+{
+ int ret;
+ SizeT dl = (SizeT)destlen;
+ SizeT sl = (SizeT)srclen;
+ ELzmaStatus status;
+
+ ret = LzmaDecode(cpage_out, &dl, data_in, &sl, propsEncoded,
+ propsSize, LZMA_FINISH_ANY, &status, &lzma_alloc);
+
+ if (ret != SZ_OK || status == LZMA_STATUS_NOT_FINISHED || dl != (SizeT)destlen)
+ return -1;
+
+ return 0;
+}
+
+static struct jffs2_compressor jffs2_lzma_comp = {
+ .priority = JFFS2_LZMA_PRIORITY,
+ .name = "lzma",
+ .compr = JFFS2_COMPR_LZMA,
+ .compress = &jffs2_lzma_compress,
+ .decompress = &jffs2_lzma_decompress,
+ .disabled = 0,
+};
+
+int INIT jffs2_lzma_init(void)
+{
+ int ret;
+ CLzmaEncProps props;
+ LzmaEncProps_Init(&props);
+
+ props.dictSize = LZMA_BEST_DICT(0x2000);
+ props.level = LZMA_BEST_LEVEL;
+ props.lc = LZMA_BEST_LC;
+ props.lp = LZMA_BEST_LP;
+ props.pb = LZMA_BEST_PB;
+ props.fb = LZMA_BEST_FB;
+
+ ret = lzma_alloc_workspace(&props);
+ if (ret < 0)
+ return ret;
+
+ ret = jffs2_register_compressor(&jffs2_lzma_comp);
+ if (ret)
+ lzma_free_workspace();
+
+ return ret;
+}
+
+void jffs2_lzma_exit(void)
+{
+ jffs2_unregister_compressor(&jffs2_lzma_comp);
+ lzma_free_workspace();
+}
diff -urN linux-4.9.37/fs/jffs2/Kconfig linux-4.9.y/fs/jffs2/Kconfig
--- linux-4.9.37/fs/jffs2/Kconfig 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/fs/jffs2/Kconfig 2021-06-07 13:01:34.000000000 +0300
@@ -139,6 +139,15 @@
This feature was added in July, 2007. Say 'N' if you need
compatibility with older bootloaders or kernels.
+config JFFS2_LZMA
+ bool "JFFS2 LZMA compression support" if JFFS2_COMPRESSION_OPTIONS
+ select LZMA_COMPRESS
+ select LZMA_DECOMPRESS
+ depends on JFFS2_FS
+ default n
+ help
+ JFFS2 wrapper to the LZMA C SDK
+
config JFFS2_RTIME
bool "JFFS2 RTIME compression support" if JFFS2_COMPRESSION_OPTIONS
depends on JFFS2_FS
diff -urN linux-4.9.37/fs/jffs2/Makefile linux-4.9.y/fs/jffs2/Makefile
--- linux-4.9.37/fs/jffs2/Makefile 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/fs/jffs2/Makefile 2021-06-07 13:01:34.000000000 +0300
@@ -18,4 +18,7 @@
jffs2-$(CONFIG_JFFS2_RTIME) += compr_rtime.o
jffs2-$(CONFIG_JFFS2_ZLIB) += compr_zlib.o
jffs2-$(CONFIG_JFFS2_LZO) += compr_lzo.o
+jffs2-$(CONFIG_JFFS2_LZMA) += compr_lzma.o
jffs2-$(CONFIG_JFFS2_SUMMARY) += summary.o
+
+CFLAGS_compr_lzma.o += -Iinclude/linux -Ilib/lzma
diff -urN linux-4.9.37/fs/jffs2/super.c linux-4.9.y/fs/jffs2/super.c
--- linux-4.9.37/fs/jffs2/super.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/fs/jffs2/super.c 2021-06-07 13:01:34.000000000 +0300
@@ -372,14 +372,41 @@
BUILD_BUG_ON(sizeof(struct jffs2_raw_inode) != 68);
BUILD_BUG_ON(sizeof(struct jffs2_raw_summary) != 32);
- pr_info("version 2.2."
+ pr_info("version 2.2"
#ifdef CONFIG_JFFS2_FS_WRITEBUFFER
" (NAND)"
#endif
#ifdef CONFIG_JFFS2_SUMMARY
- " (SUMMARY) "
+ " (SUMMARY)"
#endif
- " © 2001-2006 Red Hat, Inc.\n");
+#ifdef CONFIG_JFFS2_ZLIB
+ " (ZLIB)"
+#endif
+#ifdef CONFIG_JFFS2_LZO
+ " (LZO)"
+#endif
+#ifdef CONFIG_JFFS2_LZMA
+ " (LZMA)"
+#endif
+#ifdef CONFIG_JFFS2_RTIME
+ " (RTIME)"
+#endif
+#ifdef CONFIG_JFFS2_RUBIN
+ " (RUBIN)"
+#endif
+#ifdef CONFIG_JFFS2_CMODE_NONE
+ " (CMODE_NONE)"
+#endif
+#ifdef CONFIG_JFFS2_CMODE_PRIORITY
+ " (CMODE_PRIORITY)"
+#endif
+#ifdef CONFIG_JFFS2_CMODE_SIZE
+ " (CMODE_SIZE)"
+#endif
+#ifdef CONFIG_JFFS2_CMODE_FAVOURLZO
+ " (CMODE_FAVOURLZO)"
+#endif
+ " (c) 2001-2006 Red Hat, Inc.\n");
jffs2_inode_cachep = kmem_cache_create("jffs2_i",
sizeof(struct jffs2_inode_info),
diff -urN linux-4.9.37/fs/Kconfig linux-4.9.y/fs/Kconfig
--- linux-4.9.37/fs/Kconfig 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/fs/Kconfig 2021-06-07 13:01:34.000000000 +0300
@@ -232,6 +232,7 @@
source "fs/befs/Kconfig"
source "fs/bfs/Kconfig"
source "fs/efs/Kconfig"
+source "fs/yaffs2/Kconfig"
source "fs/jffs2/Kconfig"
# UBIFS File system configuration
source "fs/ubifs/Kconfig"
diff -urN linux-4.9.37/fs/Makefile linux-4.9.y/fs/Makefile
--- linux-4.9.37/fs/Makefile 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/fs/Makefile 2021-06-07 13:01:34.000000000 +0300
@@ -129,3 +129,4 @@
obj-$(CONFIG_CEPH_FS) += ceph/
obj-$(CONFIG_PSTORE) += pstore/
obj-$(CONFIG_EFIVAR_FS) += efivarfs/
+obj-$(CONFIG_YAFFS_FS) += yaffs2/
diff -urN linux-4.9.37/fs/xfs/xfs_buf.c linux-4.9.y/fs/xfs/xfs_buf.c
--- linux-4.9.37/fs/xfs/xfs_buf.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/fs/xfs/xfs_buf.c 2021-06-07 13:01:34.000000000 +0300
@@ -116,7 +116,7 @@
__xfs_buf_ioacct_dec(
struct xfs_buf *bp)
{
- ASSERT(spin_is_locked(&bp->b_lock));
+ lockdep_assert_held(&bp->b_lock);
if (bp->b_state & XFS_BSTATE_IN_FLIGHT) {
bp->b_state &= ~XFS_BSTATE_IN_FLIGHT;
diff -urN linux-4.9.37/fs/xfs/xfs_icache.c linux-4.9.y/fs/xfs/xfs_icache.c
--- linux-4.9.37/fs/xfs/xfs_icache.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/fs/xfs/xfs_icache.c 2021-06-07 13:01:34.000000000 +0300
@@ -66,7 +66,6 @@
XFS_STATS_INC(mp, vn_active);
ASSERT(atomic_read(&ip->i_pincount) == 0);
- ASSERT(!spin_is_locked(&ip->i_flags_lock));
ASSERT(!xfs_isiflocked(ip));
ASSERT(ip->i_ino == 0);
@@ -192,7 +191,7 @@
{
struct xfs_mount *mp = pag->pag_mount;
- ASSERT(spin_is_locked(&pag->pag_ici_lock));
+ lockdep_assert_held(&pag->pag_ici_lock);
if (pag->pag_ici_reclaimable++)
return;
@@ -214,7 +213,7 @@
{
struct xfs_mount *mp = pag->pag_mount;
- ASSERT(spin_is_locked(&pag->pag_ici_lock));
+ lockdep_assert_held(&pag->pag_ici_lock);
if (--pag->pag_ici_reclaimable)
return;
diff -urN linux-4.9.37/fs/yaffs2/Kconfig linux-4.9.y/fs/yaffs2/Kconfig
--- linux-4.9.37/fs/yaffs2/Kconfig 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/Kconfig 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,171 @@
+#
+# yaffs file system configurations
+#
+
+config YAFFS_FS
+ tristate "yaffs2 file system support"
+ default n
+ depends on MTD_BLOCK
+ select YAFFS_YAFFS1
+ select YAFFS_YAFFS2
+ help
+ yaffs2, or Yet Another Flash File System, is a file system
+ optimised for NAND Flash chips.
+
+ To compile the yaffs2 file system support as a module, choose M
+ here: the module will be called yaffs2.
+
+ If unsure, say N.
+
+ Further information on yaffs2 is available at
+ <http://www.aleph1.co.uk/yaffs/>.
+
+config YAFFS_YAFFS1
+ bool "512 byte / page devices"
+ depends on YAFFS_FS
+ default y
+ help
+ Enable yaffs1 support -- yaffs for 512 byte / page devices
+
+ Not needed for 2K-page devices.
+
+ If unsure, say Y.
+
+config YAFFS_9BYTE_TAGS
+ bool "Use older-style on-NAND data format with pageStatus byte"
+ depends on YAFFS_YAFFS1
+ default n
+ help
+
+ Older-style on-NAND data format has a "pageStatus" byte to record
+ chunk/page state. This byte is zero when the page is discarded.
+ Choose this option if you have existing on-NAND data using this
+ format that you need to continue to support. New data written
+ also uses the older-style format. Note: Use of this option
+ generally requires that MTD's oob layout be adjusted to use the
+ older-style format. See notes on tags formats and MTD versions
+ in yaffs_mtdif1.c.
+
+ If unsure, say N.
+
+config YAFFS_DOES_ECC
+ bool "Lets yaffs do its own ECC"
+ depends on YAFFS_FS && YAFFS_YAFFS1 && !YAFFS_9BYTE_TAGS
+ default n
+ help
+ This enables yaffs to use its own ECC functions instead of using
+ the ones from the generic MTD-NAND driver.
+
+ If unsure, say N.
+
+config YAFFS_ECC_WRONG_ORDER
+ bool "Use the same ecc byte order as Steven Hill's nand_ecc.c"
+ depends on YAFFS_FS && YAFFS_DOES_ECC && !YAFFS_9BYTE_TAGS
+ default n
+ help
+ This makes yaffs_ecc.c use the same ecc byte order as Steven
+ Hill's nand_ecc.c. If not set, then you get the same ecc byte
+ order as SmartMedia.
+
+ If unsure, say N.
+
+config YAFFS_YAFFS2
+ bool "2048 byte (or larger) / page devices"
+ depends on YAFFS_FS
+ default y
+ help
+ Enable yaffs2 support -- yaffs for >= 2K bytes per page devices
+
+ If unsure, say Y.
+
+config YAFFS_AUTO_YAFFS2
+ bool "Autoselect yaffs2 format"
+ depends on YAFFS_YAFFS2
+ default y
+ help
+ Without this, you need to explicitely use yaffs2 as the file
+ system type. With this, you can say "yaffs" and yaffs or yaffs2
+ will be used depending on the device page size (yaffs on
+ 512-byte page devices, yaffs2 on 2K page devices).
+
+ If unsure, say Y.
+
+config YAFFS_DISABLE_TAGS_ECC
+ bool "Disable yaffs from doing ECC on tags by default"
+ depends on YAFFS_FS && YAFFS_YAFFS2
+ default n
+ help
+ This defaults yaffs to using its own ECC calculations on tags instead of
+ just relying on the MTD.
+ This behavior can also be overridden with tags_ecc_on and
+ tags_ecc_off mount options.
+
+ If unsure, say N.
+
+config YAFFS_ALWAYS_CHECK_CHUNK_ERASED
+ bool "Force chunk erase check"
+ depends on YAFFS_FS
+ default n
+ help
+ Normally yaffs only checks chunks before writing until an erased
+ chunk is found. This helps to detect any partially written
+ chunks that might have happened due to power loss.
+
+ Enabling this forces on the test that chunks are erased in flash
+ before writing to them. This takes more time but is potentially
+ a bit more secure.
+
+ Suggest setting Y during development and ironing out driver
+ issues etc. Suggest setting to N if you want faster writing.
+
+ If unsure, say Y.
+
+config YAFFS_EMPTY_LOST_AND_FOUND
+ bool "Empty lost and found on boot"
+ depends on YAFFS_FS
+ default n
+ help
+ If this is enabled then the contents of lost and found is
+ automatically dumped at mount.
+
+ If unsure, say N.
+
+config YAFFS_DISABLE_BLOCK_REFRESHING
+ bool "Disable yaffs2 block refreshing"
+ depends on YAFFS_FS
+ default n
+ help
+ If this is set, then block refreshing is disabled.
+ Block refreshing infrequently refreshes the oldest block in
+ a yaffs2 file system. This mechanism helps to refresh flash to
+ mitigate against data loss. This is particularly useful for MLC.
+
+ If unsure, say N.
+
+config YAFFS_DISABLE_BACKGROUND
+ bool "Disable yaffs2 background processing"
+ depends on YAFFS_FS
+ default n
+ help
+ If this is set, then background processing is disabled.
+ Background processing makes many foreground activities faster.
+
+ If unsure, say N.
+
+config YAFFS_DISABLE_BAD_BLOCK_MARKING
+ bool "Disable yaffs2 bad block marking"
+ depends on YAFFS_FS
+ default n
+ help
+ Useful during early flash bring up to prevent problems causing
+ lots of bad block marking.
+
+ If unsure, say N.
+
+config YAFFS_XATTR
+ bool "Enable yaffs2 xattr support"
+ depends on YAFFS_FS
+ default y
+ help
+ If this is set then yaffs2 will provide xattr support.
+ If unsure, say Y.
diff -urN linux-4.9.37/fs/yaffs2/Makefile linux-4.9.y/fs/yaffs2/Makefile
--- linux-4.9.37/fs/yaffs2/Makefile 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/Makefile 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,19 @@
+#
+# Makefile for the linux YAFFS filesystem routines.
+#
+
+obj-$(CONFIG_YAFFS_FS) += yaffs.o
+
+yaffs-y := yaffs_ecc.o yaffs_vfs.o yaffs_guts.o yaffs_checkptrw.o
+yaffs-y += yaffs_packedtags1.o yaffs_packedtags2.o yaffs_nand.o
+yaffs-y += yaffs_tagscompat.o yaffs_tagsmarshall.o
+yaffs-y += yaffs_endian.o
+yaffs-y += yaffs_mtdif.o
+yaffs-y += yaffs_nameval.o yaffs_attribs.o
+yaffs-y += yaffs_allocator.o
+yaffs-y += yaffs_yaffs1.o
+yaffs-y += yaffs_yaffs2.o
+yaffs-y += yaffs_bitmap.o
+yaffs-y += yaffs_summary.o
+yaffs-y += yaffs_verify.o
+
diff -urN linux-4.9.37/fs/yaffs2/yaffs_allocator.c linux-4.9.y/fs/yaffs2/yaffs_allocator.c
--- linux-4.9.37/fs/yaffs2/yaffs_allocator.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/yaffs_allocator.c 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,357 @@
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * 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 "yaffs_allocator.h"
+#include "yaffs_guts.h"
+#include "yaffs_trace.h"
+#include "yportenv.h"
+
+/*
+ * Each entry in yaffs_tnode_list and yaffs_obj_list hold blocks
+ * of approx 100 objects that are themn allocated singly.
+ * This is basically a simplified slab allocator.
+ *
+ * We don't use the Linux slab allocator because slab does not allow
+ * us to dump all the objects in one hit when we do a umount and tear
+ * down all the tnodes and objects. slab requires that we first free
+ * the individual objects.
+ *
+ * Once yaffs has been mainlined I shall try to motivate for a change
+ * to slab to provide the extra features we need here.
+ */
+
+struct yaffs_tnode_list {
+ struct yaffs_tnode_list *next;
+ struct yaffs_tnode *tnodes;
+};
+
+struct yaffs_obj_list {
+ struct yaffs_obj_list *next;
+ struct yaffs_obj *objects;
+};
+
+struct yaffs_allocator {
+ int n_tnodes_created;
+ struct yaffs_tnode *free_tnodes;
+ int n_free_tnodes;
+ struct yaffs_tnode_list *alloc_tnode_list;
+
+ int n_obj_created;
+ struct list_head free_objs;
+ int n_free_objects;
+
+ struct yaffs_obj_list *allocated_obj_list;
+};
+
+static void yaffs_deinit_raw_tnodes(struct yaffs_dev *dev)
+{
+ struct yaffs_allocator *allocator =
+ (struct yaffs_allocator *)dev->allocator;
+ struct yaffs_tnode_list *tmp;
+
+ if (!allocator) {
+ BUG();
+ return;
+ }
+
+ while (allocator->alloc_tnode_list) {
+ tmp = allocator->alloc_tnode_list->next;
+
+ kfree(allocator->alloc_tnode_list->tnodes);
+ kfree(allocator->alloc_tnode_list);
+ allocator->alloc_tnode_list = tmp;
+ }
+
+ allocator->free_tnodes = NULL;
+ allocator->n_free_tnodes = 0;
+ allocator->n_tnodes_created = 0;
+}
+
+static void yaffs_init_raw_tnodes(struct yaffs_dev *dev)
+{
+ struct yaffs_allocator *allocator = dev->allocator;
+
+ if (!allocator) {
+ BUG();
+ return;
+ }
+
+ allocator->alloc_tnode_list = NULL;
+ allocator->free_tnodes = NULL;
+ allocator->n_free_tnodes = 0;
+ allocator->n_tnodes_created = 0;
+}
+
+static int yaffs_create_tnodes(struct yaffs_dev *dev, int n_tnodes)
+{
+ struct yaffs_allocator *allocator =
+ (struct yaffs_allocator *)dev->allocator;
+ int i;
+ struct yaffs_tnode *new_tnodes;
+ u8 *mem;
+ struct yaffs_tnode *curr;
+ struct yaffs_tnode *next;
+ struct yaffs_tnode_list *tnl;
+
+ if (!allocator) {
+ BUG();
+ return YAFFS_FAIL;
+ }
+
+ if (n_tnodes < 1)
+ return YAFFS_OK;
+
+ /* make these things */
+ new_tnodes = kmalloc(n_tnodes * dev->tnode_size, GFP_NOFS);
+ mem = (u8 *) new_tnodes;
+
+ if (!new_tnodes) {
+ yaffs_trace(YAFFS_TRACE_ERROR,
+ "yaffs: Could not allocate Tnodes");
+ return YAFFS_FAIL;
+ }
+
+ /* New hookup for wide tnodes */
+ for (i = 0; i < n_tnodes - 1; i++) {
+ curr = (struct yaffs_tnode *)&mem[i * dev->tnode_size];
+ next = (struct yaffs_tnode *)&mem[(i + 1) * dev->tnode_size];
+ curr->internal[0] = next;
+ }
+
+ curr = (struct yaffs_tnode *)&mem[(n_tnodes - 1) * dev->tnode_size];
+ curr->internal[0] = allocator->free_tnodes;
+ allocator->free_tnodes = (struct yaffs_tnode *)mem;
+
+ allocator->n_free_tnodes += n_tnodes;
+ allocator->n_tnodes_created += n_tnodes;
+
+ /* Now add this bunch of tnodes to a list for freeing up.
+ * NB If we can't add this to the management list it isn't fatal
+ * but it just means we can't free this bunch of tnodes later.
+ */
+ tnl = kmalloc(sizeof(struct yaffs_tnode_list), GFP_NOFS);
+ if (!tnl) {
+ yaffs_trace(YAFFS_TRACE_ERROR,
+ "Could not add tnodes to management list");
+ return YAFFS_FAIL;
+ } else {
+ tnl->tnodes = new_tnodes;
+ tnl->next = allocator->alloc_tnode_list;
+ allocator->alloc_tnode_list = tnl;
+ }
+
+ yaffs_trace(YAFFS_TRACE_ALLOCATE, "Tnodes added");
+
+ return YAFFS_OK;
+}
+
+struct yaffs_tnode *yaffs_alloc_raw_tnode(struct yaffs_dev *dev)
+{
+ struct yaffs_allocator *allocator =
+ (struct yaffs_allocator *)dev->allocator;
+ struct yaffs_tnode *tn = NULL;
+
+ if (!allocator) {
+ BUG();
+ return NULL;
+ }
+
+ /* If there are none left make more */
+ if (!allocator->free_tnodes)
+ yaffs_create_tnodes(dev, YAFFS_ALLOCATION_NTNODES);
+
+ if (allocator->free_tnodes) {
+ tn = allocator->free_tnodes;
+ allocator->free_tnodes = allocator->free_tnodes->internal[0];
+ allocator->n_free_tnodes--;
+ }
+
+ return tn;
+}
+
+/* FreeTnode frees up a tnode and puts it back on the free list */
+void yaffs_free_raw_tnode(struct yaffs_dev *dev, struct yaffs_tnode *tn)
+{
+ struct yaffs_allocator *allocator = dev->allocator;
+
+ if (!allocator) {
+ BUG();
+ return;
+ }
+
+ if (tn) {
+ tn->internal[0] = allocator->free_tnodes;
+ allocator->free_tnodes = tn;
+ allocator->n_free_tnodes++;
+ }
+ dev->checkpoint_blocks_required = 0; /* force recalculation */
+}
+
+/*--------------- yaffs_obj alloaction ------------------------
+ *
+ * Free yaffs_objs are stored in a list using obj->siblings.
+ * The blocks of allocated objects are stored in a linked list.
+ */
+
+static void yaffs_init_raw_objs(struct yaffs_dev *dev)
+{
+ struct yaffs_allocator *allocator = dev->allocator;
+
+ if (!allocator) {
+ BUG();
+ return;
+ }
+
+ allocator->allocated_obj_list = NULL;
+ INIT_LIST_HEAD(&allocator->free_objs);
+ allocator->n_free_objects = 0;
+}
+
+static void yaffs_deinit_raw_objs(struct yaffs_dev *dev)
+{
+ struct yaffs_allocator *allocator = dev->allocator;
+ struct yaffs_obj_list *tmp;
+
+ if (!allocator) {
+ BUG();
+ return;
+ }
+
+ while (allocator->allocated_obj_list) {
+ tmp = allocator->allocated_obj_list->next;
+ kfree(allocator->allocated_obj_list->objects);
+ kfree(allocator->allocated_obj_list);
+ allocator->allocated_obj_list = tmp;
+ }
+
+ INIT_LIST_HEAD(&allocator->free_objs);
+ allocator->n_free_objects = 0;
+ allocator->n_obj_created = 0;
+}
+
+static int yaffs_create_free_objs(struct yaffs_dev *dev, int n_obj)
+{
+ struct yaffs_allocator *allocator = dev->allocator;
+ int i;
+ struct yaffs_obj *new_objs;
+ struct yaffs_obj_list *list;
+
+ if (!allocator) {
+ BUG();
+ return YAFFS_FAIL;
+ }
+
+ if (n_obj < 1)
+ return YAFFS_OK;
+
+ /* make these things */
+ new_objs = kmalloc(n_obj * sizeof(struct yaffs_obj), GFP_NOFS);
+ list = kmalloc(sizeof(struct yaffs_obj_list), GFP_NOFS);
+
+ if (!new_objs || !list) {
+ kfree(new_objs);
+ new_objs = NULL;
+ kfree(list);
+ list = NULL;
+ yaffs_trace(YAFFS_TRACE_ALLOCATE,
+ "Could not allocate more objects");
+ return YAFFS_FAIL;
+ }
+
+ /* Hook them into the free list */
+ for (i = 0; i < n_obj; i++)
+ list_add(&new_objs[i].siblings, &allocator->free_objs);
+
+ allocator->n_free_objects += n_obj;
+ allocator->n_obj_created += n_obj;
+
+ /* Now add this bunch of Objects to a list for freeing up. */
+
+ list->objects = new_objs;
+ list->next = allocator->allocated_obj_list;
+ allocator->allocated_obj_list = list;
+
+ return YAFFS_OK;
+}
+
+struct yaffs_obj *yaffs_alloc_raw_obj(struct yaffs_dev *dev)
+{
+ struct yaffs_obj *obj = NULL;
+ struct list_head *lh;
+ struct yaffs_allocator *allocator = dev->allocator;
+
+ if (!allocator) {
+ BUG();
+ return obj;
+ }
+
+ /* If there are none left make more */
+ if (list_empty(&allocator->free_objs))
+ yaffs_create_free_objs(dev, YAFFS_ALLOCATION_NOBJECTS);
+
+ if (!list_empty(&allocator->free_objs)) {
+ lh = allocator->free_objs.next;
+ obj = list_entry(lh, struct yaffs_obj, siblings);
+ list_del_init(lh);
+ allocator->n_free_objects--;
+ }
+
+ return obj;
+}
+
+void yaffs_free_raw_obj(struct yaffs_dev *dev, struct yaffs_obj *obj)
+{
+
+ struct yaffs_allocator *allocator = dev->allocator;
+
+ if (!allocator) {
+ BUG();
+ return;
+ }
+
+ /* Link into the free list. */
+ list_add(&obj->siblings, &allocator->free_objs);
+ allocator->n_free_objects++;
+}
+
+void yaffs_deinit_raw_tnodes_and_objs(struct yaffs_dev *dev)
+{
+
+ if (!dev->allocator) {
+ BUG();
+ return;
+ }
+
+ yaffs_deinit_raw_tnodes(dev);
+ yaffs_deinit_raw_objs(dev);
+ kfree(dev->allocator);
+ dev->allocator = NULL;
+}
+
+void yaffs_init_raw_tnodes_and_objs(struct yaffs_dev *dev)
+{
+ struct yaffs_allocator *allocator;
+
+ if (dev->allocator) {
+ BUG();
+ return;
+ }
+
+ allocator = kmalloc(sizeof(struct yaffs_allocator), GFP_NOFS);
+ if (allocator) {
+ dev->allocator = allocator;
+ yaffs_init_raw_tnodes(dev);
+ yaffs_init_raw_objs(dev);
+ }
+}
+
diff -urN linux-4.9.37/fs/yaffs2/yaffs_allocator.h linux-4.9.y/fs/yaffs2/yaffs_allocator.h
--- linux-4.9.37/fs/yaffs2/yaffs_allocator.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/yaffs_allocator.h 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,30 @@
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+#ifndef __YAFFS_ALLOCATOR_H__
+#define __YAFFS_ALLOCATOR_H__
+
+#include "yaffs_guts.h"
+
+void yaffs_init_raw_tnodes_and_objs(struct yaffs_dev *dev);
+void yaffs_deinit_raw_tnodes_and_objs(struct yaffs_dev *dev);
+
+struct yaffs_tnode *yaffs_alloc_raw_tnode(struct yaffs_dev *dev);
+void yaffs_free_raw_tnode(struct yaffs_dev *dev, struct yaffs_tnode *tn);
+
+struct yaffs_obj *yaffs_alloc_raw_obj(struct yaffs_dev *dev);
+void yaffs_free_raw_obj(struct yaffs_dev *dev, struct yaffs_obj *obj);
+
+#endif
diff -urN linux-4.9.37/fs/yaffs2/yaffs_attribs.c linux-4.9.y/fs/yaffs2/yaffs_attribs.c
--- linux-4.9.37/fs/yaffs2/yaffs_attribs.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/yaffs_attribs.c 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,136 @@
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * 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 "yaffs_guts.h"
+#include "yaffs_attribs.h"
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
+#define IATTR_UID ia_uid
+#define IATTR_GID ia_gid
+#else
+#define IATTR_UID ia_uid.val
+#define IATTR_GID ia_gid.val
+#endif
+
+/*
+ * Loading attibs from/to object header assumes the object header
+ * is in cpu endian.
+ */
+void yaffs_load_attribs(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh)
+{
+ obj->yst_uid = oh->yst_uid;
+ obj->yst_gid = oh->yst_gid;
+ obj->yst_atime = oh->yst_atime;
+ obj->yst_mtime = oh->yst_mtime;
+ obj->yst_ctime = oh->yst_ctime;
+ obj->yst_rdev = oh->yst_rdev;
+}
+
+void yaffs_load_attribs_oh(struct yaffs_obj_hdr *oh, struct yaffs_obj *obj)
+{
+ oh->yst_uid = obj->yst_uid;
+ oh->yst_gid = obj->yst_gid;
+ oh->yst_atime = obj->yst_atime;
+ oh->yst_mtime = obj->yst_mtime;
+ oh->yst_ctime = obj->yst_ctime;
+ oh->yst_rdev = obj->yst_rdev;
+
+}
+
+void yaffs_load_current_time(struct yaffs_obj *obj, int do_a, int do_c)
+{
+ obj->yst_mtime = Y_CURRENT_TIME;
+ if (do_a)
+ obj->yst_atime = obj->yst_mtime;
+ if (do_c)
+ obj->yst_ctime = obj->yst_mtime;
+}
+
+void yaffs_attribs_init(struct yaffs_obj *obj, u32 gid, u32 uid, u32 rdev)
+{
+ yaffs_load_current_time(obj, 1, 1);
+ obj->yst_rdev = rdev;
+ obj->yst_uid = uid;
+ obj->yst_gid = gid;
+}
+
+static loff_t yaffs_get_file_size(struct yaffs_obj *obj)
+{
+ YCHAR *alias = NULL;
+ obj = yaffs_get_equivalent_obj(obj);
+
+ switch (obj->variant_type) {
+ case YAFFS_OBJECT_TYPE_FILE:
+ return obj->variant.file_variant.file_size;
+ case YAFFS_OBJECT_TYPE_SYMLINK:
+ alias = obj->variant.symlink_variant.alias;
+ if (!alias)
+ return 0;
+ return strnlen(alias, YAFFS_MAX_ALIAS_LENGTH);
+ default:
+ return 0;
+ }
+}
+
+int yaffs_set_attribs(struct yaffs_obj *obj, struct iattr *attr)
+{
+ unsigned int valid = attr->ia_valid;
+
+ if (valid & ATTR_MODE)
+ obj->yst_mode = attr->ia_mode;
+ if (valid & ATTR_UID)
+ obj->yst_uid = attr->IATTR_UID;
+ if (valid & ATTR_GID)
+ obj->yst_gid = attr->IATTR_GID;
+
+ if (valid & ATTR_ATIME)
+ obj->yst_atime = Y_TIME_CONVERT(attr->ia_atime);
+ if (valid & ATTR_CTIME)
+ obj->yst_ctime = Y_TIME_CONVERT(attr->ia_ctime);
+ if (valid & ATTR_MTIME)
+ obj->yst_mtime = Y_TIME_CONVERT(attr->ia_mtime);
+
+ if (valid & ATTR_SIZE)
+ yaffs_resize_file(obj, attr->ia_size);
+
+ yaffs_update_oh(obj, NULL, 1, 0, 0, NULL);
+
+ return YAFFS_OK;
+
+}
+
+int yaffs_get_attribs(struct yaffs_obj *obj, struct iattr *attr)
+{
+ unsigned int valid = 0;
+
+ attr->ia_mode = obj->yst_mode;
+ valid |= ATTR_MODE;
+ attr->IATTR_UID = obj->yst_uid;
+ valid |= ATTR_UID;
+ attr->IATTR_GID = obj->yst_gid;
+ valid |= ATTR_GID;
+
+ Y_TIME_CONVERT(attr->ia_atime) = obj->yst_atime;
+ valid |= ATTR_ATIME;
+ Y_TIME_CONVERT(attr->ia_ctime) = obj->yst_ctime;
+ valid |= ATTR_CTIME;
+ Y_TIME_CONVERT(attr->ia_mtime) = obj->yst_mtime;
+ valid |= ATTR_MTIME;
+
+ attr->ia_size = yaffs_get_file_size(obj);
+ valid |= ATTR_SIZE;
+
+ attr->ia_valid = valid;
+
+ return YAFFS_OK;
+}
diff -urN linux-4.9.37/fs/yaffs2/yaffs_attribs.h linux-4.9.y/fs/yaffs2/yaffs_attribs.h
--- linux-4.9.37/fs/yaffs2/yaffs_attribs.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/yaffs_attribs.h 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,28 @@
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+#ifndef __YAFFS_ATTRIBS_H__
+#define __YAFFS_ATTRIBS_H__
+
+#include "yaffs_guts.h"
+
+void yaffs_load_attribs(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh);
+void yaffs_load_attribs_oh(struct yaffs_obj_hdr *oh, struct yaffs_obj *obj);
+void yaffs_attribs_init(struct yaffs_obj *obj, u32 gid, u32 uid, u32 rdev);
+void yaffs_load_current_time(struct yaffs_obj *obj, int do_a, int do_c);
+int yaffs_set_attribs(struct yaffs_obj *obj, struct iattr *attr);
+int yaffs_get_attribs(struct yaffs_obj *obj, struct iattr *attr);
+
+#endif
diff -urN linux-4.9.37/fs/yaffs2/yaffs_bitmap.c linux-4.9.y/fs/yaffs2/yaffs_bitmap.c
--- linux-4.9.37/fs/yaffs2/yaffs_bitmap.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/yaffs_bitmap.c 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,99 @@
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * 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 "yaffs_bitmap.h"
+#include "yaffs_trace.h"
+/*
+ * Chunk bitmap manipulations
+ */
+
+static inline u8 *yaffs_block_bits(struct yaffs_dev *dev, int blk)
+{
+ if (blk < (int)dev->internal_start_block ||
+ blk > (int)dev->internal_end_block) {
+ yaffs_trace(YAFFS_TRACE_ERROR,
+ "BlockBits block %d is not valid",
+ blk);
+ BUG();
+ }
+ return dev->chunk_bits +
+ (dev->chunk_bit_stride * (blk - dev->internal_start_block));
+}
+
+void yaffs_verify_chunk_bit_id(struct yaffs_dev *dev, int blk, int chunk)
+{
+ if (blk < (int)dev->internal_start_block ||
+ blk > (int)dev->internal_end_block ||
+ chunk < 0 || chunk >= (int)dev->param.chunks_per_block) {
+ yaffs_trace(YAFFS_TRACE_ERROR,
+ "Chunk Id (%d:%d) invalid",
+ blk, chunk);
+ BUG();
+ }
+}
+
+void yaffs_clear_chunk_bits(struct yaffs_dev *dev, int blk)
+{
+ u8 *blk_bits = yaffs_block_bits(dev, blk);
+
+ memset(blk_bits, 0, dev->chunk_bit_stride);
+}
+
+void yaffs_clear_chunk_bit(struct yaffs_dev *dev, int blk, int chunk)
+{
+ u8 *blk_bits = yaffs_block_bits(dev, blk);
+
+ yaffs_verify_chunk_bit_id(dev, blk, chunk);
+ blk_bits[chunk / 8] &= ~(1 << (chunk & 7));
+}
+
+void yaffs_set_chunk_bit(struct yaffs_dev *dev, int blk, int chunk)
+{
+ u8 *blk_bits = yaffs_block_bits(dev, blk);
+
+ yaffs_verify_chunk_bit_id(dev, blk, chunk);
+ blk_bits[chunk / 8] |= (1 << (chunk & 7));
+}
+
+int yaffs_check_chunk_bit(struct yaffs_dev *dev, int blk, int chunk)
+{
+ u8 *blk_bits = yaffs_block_bits(dev, blk);
+
+ yaffs_verify_chunk_bit_id(dev, blk, chunk);
+ return (blk_bits[chunk / 8] & (1 << (chunk & 7))) ? 1 : 0;
+}
+
+int yaffs_still_some_chunks(struct yaffs_dev *dev, int blk)
+{
+ u8 *blk_bits = yaffs_block_bits(dev, blk);
+ int i;
+
+ for (i = 0; i < dev->chunk_bit_stride; i++) {
+ if (*blk_bits)
+ return 1;
+ blk_bits++;
+ }
+ return 0;
+}
+
+int yaffs_count_chunk_bits(struct yaffs_dev *dev, int blk)
+{
+ u8 *blk_bits = yaffs_block_bits(dev, blk);
+ int i;
+ int n = 0;
+
+ for (i = 0; i < dev->chunk_bit_stride; i++, blk_bits++)
+ n += hweight8(*blk_bits);
+
+ return n;
+}
diff -urN linux-4.9.37/fs/yaffs2/yaffs_bitmap.h linux-4.9.y/fs/yaffs2/yaffs_bitmap.h
--- linux-4.9.37/fs/yaffs2/yaffs_bitmap.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/yaffs_bitmap.h 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,33 @@
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+/*
+ * Chunk bitmap manipulations
+ */
+
+#ifndef __YAFFS_BITMAP_H__
+#define __YAFFS_BITMAP_H__
+
+#include "yaffs_guts.h"
+
+void yaffs_verify_chunk_bit_id(struct yaffs_dev *dev, int blk, int chunk);
+void yaffs_clear_chunk_bits(struct yaffs_dev *dev, int blk);
+void yaffs_clear_chunk_bit(struct yaffs_dev *dev, int blk, int chunk);
+void yaffs_set_chunk_bit(struct yaffs_dev *dev, int blk, int chunk);
+int yaffs_check_chunk_bit(struct yaffs_dev *dev, int blk, int chunk);
+int yaffs_still_some_chunks(struct yaffs_dev *dev, int blk);
+int yaffs_count_chunk_bits(struct yaffs_dev *dev, int blk);
+
+#endif
diff -urN linux-4.9.37/fs/yaffs2/yaffs_checkptrw.c linux-4.9.y/fs/yaffs2/yaffs_checkptrw.c
--- linux-4.9.37/fs/yaffs2/yaffs_checkptrw.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/yaffs_checkptrw.c 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,481 @@
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * 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 "yaffs_checkptrw.h"
+#include "yaffs_getblockinfo.h"
+#include "yaffs_endian.h"
+
+struct yaffs_checkpt_chunk_hdr {
+ int version;
+ int seq;
+ u32 sum;
+ u32 xor;
+} ;
+
+
+static int apply_chunk_offset(struct yaffs_dev *dev, int chunk)
+{
+ return chunk - dev->chunk_offset;
+}
+
+static int apply_block_offset(struct yaffs_dev *dev, int block)
+{
+ return block - dev->block_offset;
+}
+
+
+static void yaffs2_do_endian_hdr(struct yaffs_dev *dev,
+ struct yaffs_checkpt_chunk_hdr *hdr)
+{
+ if (!dev->swap_endian)
+ return;
+ hdr->version = swap_s32(hdr->version);
+ hdr->seq = swap_s32(hdr->seq);
+ hdr->sum = swap_u32(hdr->sum);
+ hdr->xor = swap_u32(hdr->xor);
+}
+
+static void yaffs2_checkpt_init_chunk_hdr(struct yaffs_dev *dev)
+{
+ struct yaffs_checkpt_chunk_hdr hdr;
+
+ hdr.version = YAFFS_CHECKPOINT_VERSION;
+ hdr.seq = dev->checkpt_page_seq;
+ hdr.sum = dev->checkpt_sum;
+ hdr.xor = dev->checkpt_xor;
+
+ dev->checkpt_byte_offs = sizeof(hdr);
+
+ yaffs2_do_endian_hdr(dev, &hdr);
+ memcpy(dev->checkpt_buffer, &hdr, sizeof(hdr));
+}
+
+static int yaffs2_checkpt_check_chunk_hdr(struct yaffs_dev *dev)
+{
+ struct yaffs_checkpt_chunk_hdr hdr;
+
+ memcpy(&hdr, dev->checkpt_buffer, sizeof(hdr));
+ yaffs2_do_endian_hdr(dev, &hdr);
+
+ dev->checkpt_byte_offs = sizeof(hdr);
+
+ return hdr.version == YAFFS_CHECKPOINT_VERSION &&
+ hdr.seq == dev->checkpt_page_seq &&
+ hdr.sum == dev->checkpt_sum &&
+ hdr.xor == dev->checkpt_xor;
+}
+
+static int yaffs2_checkpt_space_ok(struct yaffs_dev *dev)
+{
+ int blocks_avail = dev->n_erased_blocks - dev->param.n_reserved_blocks;
+
+ yaffs_trace(YAFFS_TRACE_CHECKPOINT,
+ "checkpt blocks_avail = %d", blocks_avail);
+
+ return (blocks_avail <= 0) ? 0 : 1;
+}
+
+static int yaffs_checkpt_erase(struct yaffs_dev *dev)
+{
+ u32 i;
+
+ if (!dev->drv.drv_erase_fn)
+ return 0;
+ yaffs_trace(YAFFS_TRACE_CHECKPOINT,
+ "checking blocks %d to %d",
+ dev->internal_start_block, dev->internal_end_block);
+
+ for (i = dev->internal_start_block; i <= dev->internal_end_block; i++) {
+ struct yaffs_block_info *bi = yaffs_get_block_info(dev, i);
+ int offset_i = apply_block_offset(dev, i);
+ int result;
+
+ if (bi->block_state == YAFFS_BLOCK_STATE_CHECKPOINT) {
+ yaffs_trace(YAFFS_TRACE_CHECKPOINT,
+ "erasing checkpt block %d", i);
+
+ dev->n_erasures++;
+
+ result = dev->drv.drv_erase_fn(dev, offset_i);
+ if(result) {
+ bi->block_state = YAFFS_BLOCK_STATE_EMPTY;
+ dev->n_erased_blocks++;
+ dev->n_free_chunks +=
+ dev->param.chunks_per_block;
+ } else {
+ dev->drv.drv_mark_bad_fn(dev, offset_i);
+ bi->block_state = YAFFS_BLOCK_STATE_DEAD;
+ }
+ }
+ }
+
+ dev->blocks_in_checkpt = 0;
+
+ return 1;
+}
+
+static void yaffs2_checkpt_find_erased_block(struct yaffs_dev *dev)
+{
+ u32 i;
+ int blocks_avail = dev->n_erased_blocks - dev->param.n_reserved_blocks;
+
+ yaffs_trace(YAFFS_TRACE_CHECKPOINT,
+ "allocating checkpt block: erased %d reserved %d avail %d next %d ",
+ dev->n_erased_blocks, dev->param.n_reserved_blocks,
+ blocks_avail, dev->checkpt_next_block);
+
+ if (dev->checkpt_next_block >= 0 &&
+ dev->checkpt_next_block <= (int)dev->internal_end_block &&
+ blocks_avail > 0) {
+
+ for (i = dev->checkpt_next_block; i <= dev->internal_end_block;
+ i++) {
+ struct yaffs_block_info *bi;
+
+ bi = yaffs_get_block_info(dev, i);
+ if (bi->block_state == YAFFS_BLOCK_STATE_EMPTY) {
+ dev->checkpt_next_block = i + 1;
+ dev->checkpt_cur_block = i;
+ yaffs_trace(YAFFS_TRACE_CHECKPOINT,
+ "allocating checkpt block %d", i);
+ return;
+ }
+ }
+ }
+ yaffs_trace(YAFFS_TRACE_CHECKPOINT, "out of checkpt blocks");
+
+ dev->checkpt_next_block = -1;
+ dev->checkpt_cur_block = -1;
+}
+
+static void yaffs2_checkpt_find_block(struct yaffs_dev *dev)
+{
+ u32 i;
+ struct yaffs_ext_tags tags;
+
+ yaffs_trace(YAFFS_TRACE_CHECKPOINT,
+ "find next checkpt block: start: blocks %d next %d",
+ dev->blocks_in_checkpt, dev->checkpt_next_block);
+
+ if (dev->blocks_in_checkpt < dev->checkpt_max_blocks)
+ for (i = dev->checkpt_next_block; i <= dev->internal_end_block;
+ i++) {
+ int chunk = i * dev->param.chunks_per_block;
+ enum yaffs_block_state state;
+ u32 seq;
+
+ dev->tagger.read_chunk_tags_fn(dev,
+ apply_chunk_offset(dev, chunk),
+ NULL, &tags);
+ yaffs_trace(YAFFS_TRACE_CHECKPOINT,
+ "find next checkpt block: search: block %d state %d oid %d seq %d eccr %d",
+ i, (int) state,
+ tags.obj_id, tags.seq_number,
+ tags.ecc_result);
+
+ if (tags.seq_number != YAFFS_SEQUENCE_CHECKPOINT_DATA)
+ continue;
+
+ dev->tagger.query_block_fn(dev,
+ apply_block_offset(dev, i),
+ &state, &seq);
+ if (state == YAFFS_BLOCK_STATE_DEAD)
+ continue;
+
+ /* Right kind of block */
+ dev->checkpt_next_block = tags.obj_id;
+ dev->checkpt_cur_block = i;
+ dev->checkpt_block_list[dev->blocks_in_checkpt] = i;
+ dev->blocks_in_checkpt++;
+ yaffs_trace(YAFFS_TRACE_CHECKPOINT,
+ "found checkpt block %d", i);
+ return;
+ }
+
+ yaffs_trace(YAFFS_TRACE_CHECKPOINT, "found no more checkpt blocks");
+
+ dev->checkpt_next_block = -1;
+ dev->checkpt_cur_block = -1;
+}
+
+int yaffs2_checkpt_open(struct yaffs_dev *dev, int writing)
+{
+ u32 i;
+
+ dev->checkpt_open_write = writing;
+
+ /* Got the functions we need? */
+ if (!dev->tagger.write_chunk_tags_fn ||
+ !dev->tagger.read_chunk_tags_fn ||
+ !dev->drv.drv_erase_fn ||
+ !dev->drv.drv_mark_bad_fn)
+ return 0;
+
+ if (writing && !yaffs2_checkpt_space_ok(dev))
+ return 0;
+
+ if (!dev->checkpt_buffer)
+ dev->checkpt_buffer =
+ kmalloc(dev->param.total_bytes_per_chunk, GFP_NOFS);
+ if (!dev->checkpt_buffer)
+ return 0;
+
+ dev->checkpt_page_seq = 0;
+ dev->checkpt_byte_count = 0;
+ dev->checkpt_sum = 0;
+ dev->checkpt_xor = 0;
+ dev->checkpt_cur_block = -1;
+ dev->checkpt_cur_chunk = -1;
+ dev->checkpt_next_block = dev->internal_start_block;
+
+ if (writing) {
+ memset(dev->checkpt_buffer, 0, dev->data_bytes_per_chunk);
+ yaffs2_checkpt_init_chunk_hdr(dev);
+ return yaffs_checkpt_erase(dev);
+ }
+
+ /* Opening for a read */
+ /* Set to a value that will kick off a read */
+ dev->checkpt_byte_offs = dev->data_bytes_per_chunk;
+ /* A checkpoint block list of 1 checkpoint block per 16 block is
+ * (hopefully) going to be way more than we need */
+ dev->blocks_in_checkpt = 0;
+ dev->checkpt_max_blocks =
+ (dev->internal_end_block - dev->internal_start_block) / 16 + 2;
+ if (!dev->checkpt_block_list)
+ dev->checkpt_block_list =
+ kmalloc(sizeof(int) * dev->checkpt_max_blocks, GFP_NOFS);
+
+ if (!dev->checkpt_block_list)
+ return 0;
+
+ for (i = 0; i < dev->checkpt_max_blocks; i++)
+ dev->checkpt_block_list[i] = -1;
+
+ return 1;
+}
+
+int yaffs2_get_checkpt_sum(struct yaffs_dev *dev, u32 * sum)
+{
+ u32 composite_sum;
+
+ composite_sum = (dev->checkpt_sum << 8) | (dev->checkpt_xor & 0xff);
+ *sum = composite_sum;
+ return 1;
+}
+
+static int yaffs2_checkpt_flush_buffer(struct yaffs_dev *dev)
+{
+ int chunk;
+ int offset_chunk;
+ struct yaffs_ext_tags tags;
+
+ if (dev->checkpt_cur_block < 0) {
+ yaffs2_checkpt_find_erased_block(dev);
+ dev->checkpt_cur_chunk = 0;
+ }
+
+ if (dev->checkpt_cur_block < 0)
+ return 0;
+
+ tags.is_deleted = 0;
+ tags.obj_id = dev->checkpt_next_block; /* Hint to next place to look */
+ tags.chunk_id = dev->checkpt_page_seq + 1;
+ tags.seq_number = YAFFS_SEQUENCE_CHECKPOINT_DATA;
+ tags.n_bytes = dev->data_bytes_per_chunk;
+ if (dev->checkpt_cur_chunk == 0) {
+ /* First chunk we write for the block? Set block state to
+ checkpoint */
+ struct yaffs_block_info *bi =
+ yaffs_get_block_info(dev, dev->checkpt_cur_block);
+ bi->block_state = YAFFS_BLOCK_STATE_CHECKPOINT;
+ dev->blocks_in_checkpt++;
+ }
+
+ chunk =
+ dev->checkpt_cur_block * dev->param.chunks_per_block +
+ dev->checkpt_cur_chunk;
+
+ yaffs_trace(YAFFS_TRACE_CHECKPOINT,
+ "checkpoint wite buffer nand %d(%d:%d) objid %d chId %d",
+ chunk, dev->checkpt_cur_block, dev->checkpt_cur_chunk,
+ tags.obj_id, tags.chunk_id);
+
+ offset_chunk = apply_chunk_offset(dev, chunk);
+
+ dev->n_page_writes++;
+
+ dev->tagger.write_chunk_tags_fn(dev, offset_chunk,
+ dev->checkpt_buffer, &tags);
+ dev->checkpt_page_seq++;
+ dev->checkpt_cur_chunk++;
+ if (dev->checkpt_cur_chunk >= (int)dev->param.chunks_per_block) {
+ dev->checkpt_cur_chunk = 0;
+ dev->checkpt_cur_block = -1;
+ }
+ memset(dev->checkpt_buffer, 0, dev->data_bytes_per_chunk);
+
+ yaffs2_checkpt_init_chunk_hdr(dev);
+
+
+ return 1;
+}
+
+int yaffs2_checkpt_wr(struct yaffs_dev *dev, const void *data, int n_bytes)
+{
+ int i = 0;
+ int ok = 1;
+ u8 *data_bytes = (u8 *) data;
+
+ if (!dev->checkpt_buffer)
+ return 0;
+
+ if (!dev->checkpt_open_write)
+ return -1;
+
+ while (i < n_bytes && ok) {
+ dev->checkpt_buffer[dev->checkpt_byte_offs] = *data_bytes;
+ dev->checkpt_sum += *data_bytes;
+ dev->checkpt_xor ^= *data_bytes;
+
+ dev->checkpt_byte_offs++;
+ i++;
+ data_bytes++;
+ dev->checkpt_byte_count++;
+
+ if (dev->checkpt_byte_offs < 0 ||
+ dev->checkpt_byte_offs >= (int)dev->data_bytes_per_chunk)
+ ok = yaffs2_checkpt_flush_buffer(dev);
+ }
+
+ return i;
+}
+
+int yaffs2_checkpt_rd(struct yaffs_dev *dev, void *data, int n_bytes)
+{
+ int i = 0;
+ struct yaffs_ext_tags tags;
+ int chunk;
+ int offset_chunk;
+ u8 *data_bytes = (u8 *) data;
+
+ if (!dev->checkpt_buffer)
+ return 0;
+
+ if (dev->checkpt_open_write)
+ return -1;
+
+ while (i < n_bytes) {
+
+ if (dev->checkpt_byte_offs < 0 ||
+ dev->checkpt_byte_offs >= (int)dev->data_bytes_per_chunk) {
+
+ if (dev->checkpt_cur_block < 0) {
+ yaffs2_checkpt_find_block(dev);
+ dev->checkpt_cur_chunk = 0;
+ }
+
+ /* Bail out if we can't find a checpoint block */
+ if (dev->checkpt_cur_block < 0)
+ break;
+
+ chunk = dev->checkpt_cur_block *
+ dev->param.chunks_per_block +
+ dev->checkpt_cur_chunk;
+
+ offset_chunk = apply_chunk_offset(dev, chunk);
+ dev->n_page_reads++;
+
+ /* Read in the next chunk */
+ dev->tagger.read_chunk_tags_fn(dev,
+ offset_chunk,
+ dev->checkpt_buffer,
+ &tags);
+
+ /* Bail out if the chunk is corrupted. */
+ if (tags.chunk_id != (u32)(dev->checkpt_page_seq + 1) ||
+ tags.ecc_result > YAFFS_ECC_RESULT_FIXED ||
+ tags.seq_number != YAFFS_SEQUENCE_CHECKPOINT_DATA)
+ break;
+
+ /* Bail out if it is not a checkpoint chunk. */
+ if(!yaffs2_checkpt_check_chunk_hdr(dev))
+ break;
+
+ dev->checkpt_page_seq++;
+ dev->checkpt_cur_chunk++;
+
+ if (dev->checkpt_cur_chunk >=
+ (int)dev->param.chunks_per_block)
+ dev->checkpt_cur_block = -1;
+
+ }
+
+ *data_bytes = dev->checkpt_buffer[dev->checkpt_byte_offs];
+ dev->checkpt_sum += *data_bytes;
+ dev->checkpt_xor ^= *data_bytes;
+ dev->checkpt_byte_offs++;
+ i++;
+ data_bytes++;
+ dev->checkpt_byte_count++;
+ }
+
+ return i; /* Number of bytes read */
+}
+
+int yaffs_checkpt_close(struct yaffs_dev *dev)
+{
+ u32 i;
+
+ if (dev->checkpt_open_write) {
+ if (dev->checkpt_byte_offs !=
+ sizeof(sizeof(struct yaffs_checkpt_chunk_hdr)))
+ yaffs2_checkpt_flush_buffer(dev);
+ } else if (dev->checkpt_block_list) {
+ for (i = 0;
+ i < dev->blocks_in_checkpt &&
+ dev->checkpt_block_list[i] >= 0; i++) {
+ int blk = dev->checkpt_block_list[i];
+ struct yaffs_block_info *bi = NULL;
+
+ if ((int)dev->internal_start_block <= blk &&
+ blk <= (int)dev->internal_end_block)
+ bi = yaffs_get_block_info(dev, blk);
+ if (bi && bi->block_state == YAFFS_BLOCK_STATE_EMPTY)
+ bi->block_state = YAFFS_BLOCK_STATE_CHECKPOINT;
+ }
+ }
+
+ dev->n_free_chunks -=
+ dev->blocks_in_checkpt * dev->param.chunks_per_block;
+ dev->n_erased_blocks -= dev->blocks_in_checkpt;
+
+ yaffs_trace(YAFFS_TRACE_CHECKPOINT, "checkpoint byte count %d",
+ dev->checkpt_byte_count);
+
+ if (dev->checkpt_buffer)
+ return 1;
+ else
+ return 0;
+}
+
+int yaffs2_checkpt_invalidate_stream(struct yaffs_dev *dev)
+{
+ /* Erase the checkpoint data */
+
+ yaffs_trace(YAFFS_TRACE_CHECKPOINT,
+ "checkpoint invalidate of %d blocks",
+ dev->blocks_in_checkpt);
+
+ return yaffs_checkpt_erase(dev);
+}
diff -urN linux-4.9.37/fs/yaffs2/yaffs_checkptrw.h linux-4.9.y/fs/yaffs2/yaffs_checkptrw.h
--- linux-4.9.37/fs/yaffs2/yaffs_checkptrw.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/yaffs_checkptrw.h 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,33 @@
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+#ifndef __YAFFS_CHECKPTRW_H__
+#define __YAFFS_CHECKPTRW_H__
+
+#include "yaffs_guts.h"
+
+int yaffs2_checkpt_open(struct yaffs_dev *dev, int writing);
+
+int yaffs2_checkpt_wr(struct yaffs_dev *dev, const void *data, int n_bytes);
+
+int yaffs2_checkpt_rd(struct yaffs_dev *dev, void *data, int n_bytes);
+
+int yaffs2_get_checkpt_sum(struct yaffs_dev *dev, u32 * sum);
+
+int yaffs_checkpt_close(struct yaffs_dev *dev);
+
+int yaffs2_checkpt_invalidate_stream(struct yaffs_dev *dev);
+
+#endif
diff -urN linux-4.9.37/fs/yaffs2/yaffs_ecc.c linux-4.9.y/fs/yaffs2/yaffs_ecc.c
--- linux-4.9.37/fs/yaffs2/yaffs_ecc.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/yaffs_ecc.c 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,281 @@
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * 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.
+ */
+
+/*
+ * This code implements the ECC algorithm used in SmartMedia.
+ *
+ * The ECC comprises 22 bits of parity information and is stuffed into 3 bytes.
+ * The two unused bit are set to 1.
+ * The ECC can correct single bit errors in a 256-byte page of data. Thus, two
+ * such ECC blocks are used on a 512-byte NAND page.
+ *
+ */
+
+#include "yportenv.h"
+
+#include "yaffs_ecc.h"
+
+/* Table generated by gen-ecc.c
+ * Using a table means we do not have to calculate p1..p4 and p1'..p4'
+ * for each byte of data. These are instead provided in a table in bits7..2.
+ * Bit 0 of each entry indicates whether the entry has an odd or even parity,
+ * and therefore this bytes influence on the line parity.
+ */
+
+static const unsigned char column_parity_table[] = {
+ 0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69,
+ 0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00,
+ 0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc,
+ 0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95,
+ 0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0,
+ 0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99,
+ 0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65,
+ 0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c,
+ 0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc,
+ 0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5,
+ 0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59,
+ 0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30,
+ 0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55,
+ 0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c,
+ 0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0,
+ 0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9,
+ 0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0,
+ 0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9,
+ 0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55,
+ 0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c,
+ 0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59,
+ 0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30,
+ 0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc,
+ 0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5,
+ 0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65,
+ 0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c,
+ 0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0,
+ 0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99,
+ 0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc,
+ 0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95,
+ 0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69,
+ 0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00,
+};
+
+
+/* Calculate the ECC for a 256-byte block of data */
+void yaffs_ecc_calc(const unsigned char *data, unsigned char *ecc)
+{
+ unsigned int i;
+ unsigned char col_parity = 0;
+ unsigned char line_parity = 0;
+ unsigned char line_parity_prime = 0;
+ unsigned char t;
+ unsigned char b;
+
+ for (i = 0; i < 256; i++) {
+ b = column_parity_table[*data++];
+ col_parity ^= b;
+
+ if (b & 0x01) { /* odd number of bits in the byte */
+ line_parity ^= i;
+ line_parity_prime ^= ~i;
+ }
+ }
+
+ ecc[2] = (~col_parity) | 0x03;
+
+ t = 0;
+ if (line_parity & 0x80)
+ t |= 0x80;
+ if (line_parity_prime & 0x80)
+ t |= 0x40;
+ if (line_parity & 0x40)
+ t |= 0x20;
+ if (line_parity_prime & 0x40)
+ t |= 0x10;
+ if (line_parity & 0x20)
+ t |= 0x08;
+ if (line_parity_prime & 0x20)
+ t |= 0x04;
+ if (line_parity & 0x10)
+ t |= 0x02;
+ if (line_parity_prime & 0x10)
+ t |= 0x01;
+ ecc[1] = ~t;
+
+ t = 0;
+ if (line_parity & 0x08)
+ t |= 0x80;
+ if (line_parity_prime & 0x08)
+ t |= 0x40;
+ if (line_parity & 0x04)
+ t |= 0x20;
+ if (line_parity_prime & 0x04)
+ t |= 0x10;
+ if (line_parity & 0x02)
+ t |= 0x08;
+ if (line_parity_prime & 0x02)
+ t |= 0x04;
+ if (line_parity & 0x01)
+ t |= 0x02;
+ if (line_parity_prime & 0x01)
+ t |= 0x01;
+ ecc[0] = ~t;
+
+}
+
+/* Correct the ECC on a 256 byte block of data */
+
+int yaffs_ecc_correct(unsigned char *data, unsigned char *read_ecc,
+ const unsigned char *test_ecc)
+{
+ unsigned char d0, d1, d2; /* deltas */
+
+ d0 = read_ecc[0] ^ test_ecc[0];
+ d1 = read_ecc[1] ^ test_ecc[1];
+ d2 = read_ecc[2] ^ test_ecc[2];
+
+ if ((d0 | d1 | d2) == 0)
+ return 0; /* no error */
+
+ if (((d0 ^ (d0 >> 1)) & 0x55) == 0x55 &&
+ ((d1 ^ (d1 >> 1)) & 0x55) == 0x55 &&
+ ((d2 ^ (d2 >> 1)) & 0x54) == 0x54) {
+ /* Single bit (recoverable) error in data */
+
+ unsigned byte;
+ unsigned bit;
+
+ bit = byte = 0;
+
+ if (d1 & 0x80)
+ byte |= 0x80;
+ if (d1 & 0x20)
+ byte |= 0x40;
+ if (d1 & 0x08)
+ byte |= 0x20;
+ if (d1 & 0x02)
+ byte |= 0x10;
+ if (d0 & 0x80)
+ byte |= 0x08;
+ if (d0 & 0x20)
+ byte |= 0x04;
+ if (d0 & 0x08)
+ byte |= 0x02;
+ if (d0 & 0x02)
+ byte |= 0x01;
+
+ if (d2 & 0x80)
+ bit |= 0x04;
+ if (d2 & 0x20)
+ bit |= 0x02;
+ if (d2 & 0x08)
+ bit |= 0x01;
+
+ data[byte] ^= (1 << bit);
+
+ return 1; /* Corrected the error */
+ }
+
+ if ((hweight8(d0) + hweight8(d1) + hweight8(d2)) == 1) {
+ /* Reccoverable error in ecc */
+
+ read_ecc[0] = test_ecc[0];
+ read_ecc[1] = test_ecc[1];
+ read_ecc[2] = test_ecc[2];
+
+ return 1; /* Corrected the error */
+ }
+
+ /* Unrecoverable error */
+
+ return -1;
+
+}
+
+/*
+ * ECCxxxOther does ECC calcs on arbitrary n bytes of data
+ */
+void yaffs_ecc_calc_other(const unsigned char *data, unsigned n_bytes,
+ struct yaffs_ecc_other *ecc_other)
+{
+ unsigned int i;
+ unsigned char col_parity = 0;
+ unsigned line_parity = 0;
+ unsigned line_parity_prime = 0;
+ unsigned char b;
+
+ for (i = 0; i < n_bytes; i++) {
+ b = column_parity_table[*data++];
+ col_parity ^= b;
+
+ if (b & 0x01) {
+ /* odd number of bits in the byte */
+ line_parity ^= i;
+ line_parity_prime ^= ~i;
+ }
+
+ }
+
+ ecc_other->col_parity = (col_parity >> 2) & 0x3f;
+ ecc_other->line_parity = line_parity;
+ ecc_other->line_parity_prime = line_parity_prime;
+}
+
+int yaffs_ecc_correct_other(unsigned char *data, unsigned n_bytes,
+ struct yaffs_ecc_other *read_ecc,
+ const struct yaffs_ecc_other *test_ecc)
+{
+ unsigned char delta_col; /* column parity delta */
+ unsigned delta_line; /* line parity delta */
+ unsigned delta_line_prime; /* line parity delta */
+ unsigned bit;
+
+ delta_col = read_ecc->col_parity ^ test_ecc->col_parity;
+ delta_line = read_ecc->line_parity ^ test_ecc->line_parity;
+ delta_line_prime =
+ read_ecc->line_parity_prime ^ test_ecc->line_parity_prime;
+
+ if ((delta_col | delta_line | delta_line_prime) == 0)
+ return 0; /* no error */
+
+ if (delta_line == ~delta_line_prime &&
+ (((delta_col ^ (delta_col >> 1)) & 0x15) == 0x15)) {
+ /* Single bit (recoverable) error in data */
+
+ bit = 0;
+
+ if (delta_col & 0x20)
+ bit |= 0x04;
+ if (delta_col & 0x08)
+ bit |= 0x02;
+ if (delta_col & 0x02)
+ bit |= 0x01;
+
+ if (delta_line >= n_bytes)
+ return -1;
+
+ data[delta_line] ^= (1 << bit);
+
+ return 1; /* corrected */
+ }
+
+ if ((hweight32(delta_line) +
+ hweight32(delta_line_prime) +
+ hweight8(delta_col)) == 1) {
+ /* Reccoverable error in ecc */
+
+ *read_ecc = *test_ecc;
+ return 1; /* corrected */
+ }
+
+ /* Unrecoverable error */
+
+ return -1;
+}
diff -urN linux-4.9.37/fs/yaffs2/yaffs_ecc.h linux-4.9.y/fs/yaffs2/yaffs_ecc.h
--- linux-4.9.37/fs/yaffs2/yaffs_ecc.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/yaffs_ecc.h 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,44 @@
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+/*
+ * This code implements the ECC algorithm used in SmartMedia.
+ *
+ * The ECC comprises 22 bits of parity information and is stuffed into 3 bytes.
+ * The two unused bit are set to 1.
+ * The ECC can correct single bit errors in a 256-byte page of data.
+ * Thus, two such ECC blocks are used on a 512-byte NAND page.
+ *
+ */
+
+#ifndef __YAFFS_ECC_H__
+#define __YAFFS_ECC_H__
+
+struct yaffs_ecc_other {
+ unsigned char col_parity;
+ unsigned line_parity;
+ unsigned line_parity_prime;
+};
+
+void yaffs_ecc_calc(const unsigned char *data, unsigned char *ecc);
+int yaffs_ecc_correct(unsigned char *data, unsigned char *read_ecc,
+ const unsigned char *test_ecc);
+
+void yaffs_ecc_calc_other(const unsigned char *data, unsigned n_bytes,
+ struct yaffs_ecc_other *ecc);
+int yaffs_ecc_correct_other(unsigned char *data, unsigned n_bytes,
+ struct yaffs_ecc_other *read_ecc,
+ const struct yaffs_ecc_other *test_ecc);
+#endif
diff -urN linux-4.9.37/fs/yaffs2/yaffs_endian.c linux-4.9.y/fs/yaffs2/yaffs_endian.c
--- linux-4.9.37/fs/yaffs2/yaffs_endian.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/yaffs_endian.c 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,106 @@
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * 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.
+ *
+ * Endian processing functions.
+ */
+
+#include "yaffs_endian.h"
+#include "yaffs_guts.h"
+
+
+void yaffs_do_endian_u32(struct yaffs_dev *dev, u32 *val)
+{
+ if (!dev->swap_endian)
+ return;
+ *val = swap_u32(*val);
+}
+
+void yaffs_do_endian_s32(struct yaffs_dev *dev, s32 *val)
+{
+ if (!dev->swap_endian)
+ return;
+ *val = swap_s32(*val);
+}
+
+void yaffs_do_endian_oh(struct yaffs_dev *dev, struct yaffs_obj_hdr *oh)
+{
+ if (!dev->swap_endian)
+ return;
+ /* Change every field */
+ oh->type = swap_u32(oh->type);
+ oh->parent_obj_id = swap_u32(oh->parent_obj_id);
+
+ oh->yst_mode = swap_u32(oh->yst_mode);
+
+ oh->yst_uid = swap_u32(oh->yst_uid);
+ oh->yst_gid = swap_u32(oh->yst_gid);
+ oh->yst_atime = swap_u32(oh->yst_atime);
+ oh->yst_mtime = swap_u32(oh->yst_mtime);
+ oh->yst_ctime = swap_u32(oh->yst_ctime);
+
+ oh->file_size_low = swap_u32(oh->file_size_low);
+
+ oh->equiv_id = swap_u32(oh->equiv_id);
+
+ oh->yst_rdev = swap_u32(oh->yst_rdev);
+
+ oh->win_ctime[0] = swap_u32(oh->win_ctime[0]);
+ oh->win_ctime[1] = swap_u32(oh->win_ctime[1]);
+ oh->win_atime[0] = swap_u32(oh->win_atime[0]);
+ oh->win_atime[1] = swap_u32(oh->win_atime[1]);
+ oh->win_mtime[0] = swap_u32(oh->win_mtime[0]);
+ oh->win_mtime[1] = swap_u32(oh->win_mtime[1]);
+
+ oh->inband_shadowed_obj_id = swap_u32(oh->inband_shadowed_obj_id);
+ oh->inband_is_shrink = swap_u32(oh->inband_is_shrink);
+
+ oh->file_size_high = swap_u32(oh->file_size_high);
+ oh->reserved[0] = swap_u32(oh->reserved[0]);
+ oh->shadows_obj = swap_s32(oh->shadows_obj);
+
+ oh->is_shrink = swap_u32(oh->is_shrink);
+}
+
+
+void yaffs_do_endian_packed_tags2(struct yaffs_dev *dev,
+ struct yaffs_packed_tags2_tags_only *ptt)
+{
+ if (!dev->swap_endian)
+ return;
+ ptt->seq_number = swap_u32(ptt->seq_number);
+ ptt->obj_id = swap_u32(ptt->obj_id);
+ ptt->chunk_id = swap_u32(ptt->chunk_id);
+ ptt->n_bytes = swap_u32(ptt->n_bytes);
+}
+
+void yaffs_endian_config(struct yaffs_dev *dev)
+{
+ u32 x = 1;
+
+ if (dev->tnode_size < 1)
+ BUG();
+
+ dev->swap_endian = 0;
+
+ if (((char *)&x)[0] == 1) {
+ /* Little Endian. */
+ if (dev->param.stored_endian == 2 /* big endian */)
+ dev->swap_endian = 1;
+ } else {
+ /* Big Endian. */
+ if (dev->param.stored_endian == 1 /* little endian */)
+ dev->swap_endian = 1;
+ }
+
+ if (dev->swap_endian)
+ dev->tn_swap_buffer = kmalloc(dev->tnode_size, GFP_NOFS);
+}
diff -urN linux-4.9.37/fs/yaffs2/yaffs_endian.h linux-4.9.y/fs/yaffs2/yaffs_endian.h
--- linux-4.9.37/fs/yaffs2/yaffs_endian.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/yaffs_endian.h 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,55 @@
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+#ifndef __YAFFS_ENDIAN_H__
+#define __YAFFS_ENDIAN_H__
+#include "yaffs_guts.h"
+#include "yaffs_packedtags2.h"
+
+static inline u32 swap_u32(u32 val)
+{
+ return ((val >>24) & 0x000000ff) |
+ ((val >> 8) & 0x0000ff00) |
+ ((val << 8) & 0x00ff0000) |
+ ((val <<24) & 0xff000000);
+}
+
+#define swap_s32(val) \
+ (s32)(swap_u32((u32)(val)))
+
+static inline loff_t swap_loff_t(loff_t lval)
+{
+ u32 vall = swap_u32(FSIZE_LOW(lval));
+ u32 valh;
+
+ if (sizeof(loff_t) == sizeof(u32))
+ return (loff_t) vall;
+
+ valh = swap_u32(FSIZE_HIGH(lval));
+
+ return FSIZE_COMBINE(vall, valh); /*NB: h and l are swapped. */
+}
+
+
+
+struct yaffs_dev;
+void yaffs_do_endian_s32(struct yaffs_dev *dev, s32 *val);
+void yaffs_do_endian_u32(struct yaffs_dev *dev, u32 *val);
+void yaffs_do_endian_oh(struct yaffs_dev *dev, struct yaffs_obj_hdr *oh);
+void yaffs_do_endian_packed_tags2(struct yaffs_dev *dev,
+ struct yaffs_packed_tags2_tags_only *ptt);
+void yaffs_endian_config(struct yaffs_dev *dev);
+
+#endif
diff -urN linux-4.9.37/fs/yaffs2/yaffs_getblockinfo.h linux-4.9.y/fs/yaffs2/yaffs_getblockinfo.h
--- linux-4.9.37/fs/yaffs2/yaffs_getblockinfo.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/yaffs_getblockinfo.h 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,36 @@
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+#ifndef __YAFFS_GETBLOCKINFO_H__
+#define __YAFFS_GETBLOCKINFO_H__
+
+#include "yaffs_guts.h"
+#include "yaffs_trace.h"
+
+/* Function to manipulate block info */
+static inline struct yaffs_block_info *yaffs_get_block_info(struct yaffs_dev
+ *dev, int blk)
+{
+ if (blk < (int)dev->internal_start_block ||
+ blk > (int)dev->internal_end_block) {
+ yaffs_trace(YAFFS_TRACE_ERROR,
+ "**>> yaffs: get_block_info block %d is not valid",
+ blk);
+ BUG();
+ }
+ return &dev->block_info[blk - dev->internal_start_block];
+}
+
+#endif
diff -urN linux-4.9.37/fs/yaffs2/yaffs_guts.c linux-4.9.y/fs/yaffs2/yaffs_guts.c
--- linux-4.9.37/fs/yaffs2/yaffs_guts.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/yaffs_guts.c 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,5215 @@
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * 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 "yportenv.h"
+#include "yaffs_trace.h"
+
+#include "yaffs_guts.h"
+#include "yaffs_endian.h"
+#include "yaffs_getblockinfo.h"
+#include "yaffs_tagscompat.h"
+#include "yaffs_tagsmarshall.h"
+#include "yaffs_nand.h"
+#include "yaffs_yaffs1.h"
+#include "yaffs_yaffs2.h"
+#include "yaffs_bitmap.h"
+#include "yaffs_verify.h"
+#include "yaffs_nand.h"
+#include "yaffs_packedtags2.h"
+#include "yaffs_nameval.h"
+#include "yaffs_allocator.h"
+#include "yaffs_attribs.h"
+#include "yaffs_summary.h"
+
+/* Note YAFFS_GC_GOOD_ENOUGH must be <= YAFFS_GC_PASSIVE_THRESHOLD */
+#define YAFFS_GC_GOOD_ENOUGH 2
+#define YAFFS_GC_PASSIVE_THRESHOLD 4
+
+#include "yaffs_ecc.h"
+
+/* Forward declarations */
+
+static int yaffs_wr_data_obj(struct yaffs_obj *in, int inode_chunk,
+ const u8 *buffer, int n_bytes, int use_reserve);
+
+static void yaffs_fix_null_name(struct yaffs_obj *obj, YCHAR *name,
+ int buffer_size);
+
+/* Function to calculate chunk and offset */
+
+void yaffs_addr_to_chunk(struct yaffs_dev *dev, loff_t addr,
+ int *chunk_out, u32 *offset_out)
+{
+ int chunk;
+ u32 offset;
+
+ chunk = (u32) (addr >> dev->chunk_shift);
+
+ if (dev->chunk_div == 1) {
+ /* easy power of 2 case */
+ offset = (u32) (addr & dev->chunk_mask);
+ } else {
+ /* Non power-of-2 case */
+
+ loff_t chunk_base;
+
+ chunk /= dev->chunk_div;
+
+ chunk_base = ((loff_t) chunk) * dev->data_bytes_per_chunk;
+ offset = (u32) (addr - chunk_base);
+ }
+
+ *chunk_out = chunk;
+ *offset_out = offset;
+}
+
+/* Function to return the number of shifts for a power of 2 greater than or
+ * equal to the given number
+ * Note we don't try to cater for all possible numbers and this does not have to
+ * be hellishly efficient.
+ */
+
+static inline u32 calc_shifts_ceiling(u32 x)
+{
+ int extra_bits;
+ int shifts;
+
+ shifts = extra_bits = 0;
+
+ while (x > 1) {
+ if (x & 1)
+ extra_bits++;
+ x >>= 1;
+ shifts++;
+ }
+
+ if (extra_bits)
+ shifts++;
+
+ return shifts;
+}
+
+/* Function to return the number of shifts to get a 1 in bit 0
+ */
+
+static inline u32 calc_shifts(u32 x)
+{
+ u32 shifts;
+
+ shifts = 0;
+
+ if (!x)
+ return 0;
+
+ while (!(x & 1)) {
+ x >>= 1;
+ shifts++;
+ }
+
+ return shifts;
+}
+
+/*
+ * Temporary buffer manipulations.
+ */
+
+static int yaffs_init_tmp_buffers(struct yaffs_dev *dev)
+{
+ int i;
+ u8 *buf = (u8 *) 1;
+
+ memset(dev->temp_buffer, 0, sizeof(dev->temp_buffer));
+
+ for (i = 0; buf && i < YAFFS_N_TEMP_BUFFERS; i++) {
+ dev->temp_buffer[i].in_use = 0;
+ buf = kmalloc(dev->param.total_bytes_per_chunk, GFP_NOFS);
+ dev->temp_buffer[i].buffer = buf;
+ }
+
+ return buf ? YAFFS_OK : YAFFS_FAIL;
+}
+
+u8 *yaffs_get_temp_buffer(struct yaffs_dev * dev)
+{
+ int i;
+
+ dev->temp_in_use++;
+ if (dev->temp_in_use > dev->max_temp)
+ dev->max_temp = dev->temp_in_use;
+
+ for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
+ if (dev->temp_buffer[i].in_use == 0) {
+ dev->temp_buffer[i].in_use = 1;
+ return dev->temp_buffer[i].buffer;
+ }
+ }
+
+ yaffs_trace(YAFFS_TRACE_BUFFERS, "Out of temp buffers");
+ /*
+ * If we got here then we have to allocate an unmanaged one
+ * This is not good.
+ */
+
+ dev->unmanaged_buffer_allocs++;
+ return kmalloc(dev->data_bytes_per_chunk, GFP_NOFS);
+
+}
+
+void yaffs_release_temp_buffer(struct yaffs_dev *dev, u8 *buffer)
+{
+ int i;
+
+ dev->temp_in_use--;
+
+ for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
+ if (dev->temp_buffer[i].buffer == buffer) {
+ dev->temp_buffer[i].in_use = 0;
+ return;
+ }
+ }
+
+ if (buffer) {
+ /* assume it is an unmanaged one. */
+ yaffs_trace(YAFFS_TRACE_BUFFERS,
+ "Releasing unmanaged temp buffer");
+ kfree(buffer);
+ dev->unmanaged_buffer_deallocs++;
+ }
+
+}
+
+/*
+ * Functions for robustisizing TODO
+ *
+ */
+
+static void yaffs_handle_chunk_wr_ok(struct yaffs_dev *dev, int nand_chunk,
+ const u8 *data,
+ const struct yaffs_ext_tags *tags)
+{
+ (void) dev;
+ (void) nand_chunk;
+ (void) data;
+ (void) tags;
+}
+
+static void yaffs_handle_chunk_update(struct yaffs_dev *dev, int nand_chunk,
+ const struct yaffs_ext_tags *tags)
+{
+ (void) dev;
+ (void) nand_chunk;
+ (void) tags;
+}
+
+void yaffs_handle_chunk_error(struct yaffs_dev *dev,
+ struct yaffs_block_info *bi)
+{
+ if (!bi->gc_prioritise) {
+ bi->gc_prioritise = 1;
+ dev->has_pending_prioritised_gc = 1;
+ bi->chunk_error_strikes++;
+
+ if (bi->chunk_error_strikes > 3) {
+ bi->needs_retiring = 1; /* Too many stikes, so retire */
+ yaffs_trace(YAFFS_TRACE_ALWAYS,
+ "yaffs: Block struck out");
+
+ }
+ }
+}
+
+static void yaffs_handle_chunk_wr_error(struct yaffs_dev *dev, int nand_chunk,
+ int erased_ok)
+{
+ int flash_block = nand_chunk / dev->param.chunks_per_block;
+ struct yaffs_block_info *bi = yaffs_get_block_info(dev, flash_block);
+
+ yaffs_handle_chunk_error(dev, bi);
+
+ if (erased_ok) {
+ /* Was an actual write failure,
+ * so mark the block for retirement.*/
+ bi->needs_retiring = 1;
+ yaffs_trace(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,
+ "**>> Block %d needs retiring", flash_block);
+ }
+
+ /* Delete the chunk */
+ yaffs_chunk_del(dev, nand_chunk, 1, __LINE__);
+ yaffs_skip_rest_of_block(dev);
+}
+
+/*
+ * Verification code
+ */
+
+/*
+ * Simple hash function. Needs to have a reasonable spread
+ */
+
+static inline int yaffs_hash_fn(int n)
+{
+ if (n < 0)
+ n = -n;
+ return n % YAFFS_NOBJECT_BUCKETS;
+}
+
+/*
+ * Access functions to useful fake objects.
+ * Note that root might have a presence in NAND if permissions are set.
+ */
+
+struct yaffs_obj *yaffs_root(struct yaffs_dev *dev)
+{
+ return dev->root_dir;
+}
+
+struct yaffs_obj *yaffs_lost_n_found(struct yaffs_dev *dev)
+{
+ return dev->lost_n_found;
+}
+
+/*
+ * Erased NAND checking functions
+ */
+
+int yaffs_check_ff(u8 *buffer, int n_bytes)
+{
+ /* Horrible, slow implementation */
+ while (n_bytes--) {
+ if (*buffer != 0xff)
+ return 0;
+ buffer++;
+ }
+ return 1;
+}
+
+static int yaffs_check_chunk_erased(struct yaffs_dev *dev, int nand_chunk)
+{
+ int retval = YAFFS_OK;
+ u8 *data = yaffs_get_temp_buffer(dev);
+ struct yaffs_ext_tags tags;
+ int result;
+
+ result = yaffs_rd_chunk_tags_nand(dev, nand_chunk, data, &tags);
+
+ if (result == YAFFS_FAIL ||
+ tags.ecc_result > YAFFS_ECC_RESULT_NO_ERROR)
+ retval = YAFFS_FAIL;
+
+ if (!yaffs_check_ff(data, dev->data_bytes_per_chunk) ||
+ tags.chunk_used) {
+ yaffs_trace(YAFFS_TRACE_NANDACCESS,
+ "Chunk %d not erased", nand_chunk);
+ retval = YAFFS_FAIL;
+ }
+
+ yaffs_release_temp_buffer(dev, data);
+
+ return retval;
+
+}
+
+static int yaffs_verify_chunk_written(struct yaffs_dev *dev,
+ int nand_chunk,
+ const u8 *data,
+ struct yaffs_ext_tags *tags)
+{
+ int retval = YAFFS_OK;
+ struct yaffs_ext_tags temp_tags;
+ u8 *buffer = yaffs_get_temp_buffer(dev);
+ int result;
+
+ result = yaffs_rd_chunk_tags_nand(dev, nand_chunk, buffer, &temp_tags);
+ if (result == YAFFS_FAIL ||
+ memcmp(buffer, data, dev->data_bytes_per_chunk) ||
+ temp_tags.obj_id != tags->obj_id ||
+ temp_tags.chunk_id != tags->chunk_id ||
+ temp_tags.n_bytes != tags->n_bytes)
+ retval = YAFFS_FAIL;
+
+ yaffs_release_temp_buffer(dev, buffer);
+
+ return retval;
+}
+
+
+int yaffs_check_alloc_available(struct yaffs_dev *dev, int n_chunks)
+{
+ int reserved_chunks;
+ int reserved_blocks = dev->param.n_reserved_blocks;
+ int checkpt_blocks;
+
+ checkpt_blocks = yaffs_calc_checkpt_blocks_required(dev);
+
+ reserved_chunks =
+ (reserved_blocks + checkpt_blocks) * dev->param.chunks_per_block;
+
+ return (dev->n_free_chunks > (reserved_chunks + n_chunks));
+}
+
+static int yaffs_find_alloc_block(struct yaffs_dev *dev)
+{
+ u32 i;
+ struct yaffs_block_info *bi;
+
+ if (dev->n_erased_blocks < 1) {
+ /* Hoosterman we've got a problem.
+ * Can't get space to gc
+ */
+ yaffs_trace(YAFFS_TRACE_ERROR,
+ "yaffs tragedy: no more erased blocks");
+
+ return -1;
+ }
+
+ /* Find an empty block. */
+
+ for (i = dev->internal_start_block; i <= dev->internal_end_block; i++) {
+ dev->alloc_block_finder++;
+ if (dev->alloc_block_finder < (int)dev->internal_start_block
+ || dev->alloc_block_finder > (int)dev->internal_end_block) {
+ dev->alloc_block_finder = dev->internal_start_block;
+ }
+
+ bi = yaffs_get_block_info(dev, dev->alloc_block_finder);
+
+ if (bi->block_state == YAFFS_BLOCK_STATE_EMPTY) {
+ bi->block_state = YAFFS_BLOCK_STATE_ALLOCATING;
+ dev->seq_number++;
+ bi->seq_number = dev->seq_number;
+ dev->n_erased_blocks--;
+ yaffs_trace(YAFFS_TRACE_ALLOCATE,
+ "Allocated block %d, seq %d, %d left" ,
+ dev->alloc_block_finder, dev->seq_number,
+ dev->n_erased_blocks);
+ return dev->alloc_block_finder;
+ }
+ }
+
+ yaffs_trace(YAFFS_TRACE_ALWAYS,
+ "yaffs tragedy: no more erased blocks, but there should have been %d",
+ dev->n_erased_blocks);
+
+ return -1;
+}
+
+static int yaffs_alloc_chunk(struct yaffs_dev *dev, int use_reserver,
+ struct yaffs_block_info **block_ptr)
+{
+ int ret_val;
+ struct yaffs_block_info *bi;
+
+ if (dev->alloc_block < 0) {
+ /* Get next block to allocate off */
+ dev->alloc_block = yaffs_find_alloc_block(dev);
+ dev->alloc_page = 0;
+ }
+
+ if (!use_reserver && !yaffs_check_alloc_available(dev, 1)) {
+ /* No space unless we're allowed to use the reserve. */
+ return -1;
+ }
+
+ if (dev->n_erased_blocks < (int)dev->param.n_reserved_blocks
+ && dev->alloc_page == 0)
+ yaffs_trace(YAFFS_TRACE_ALLOCATE, "Allocating reserve");
+
+ /* Next page please.... */
+ if (dev->alloc_block >= 0) {
+ bi = yaffs_get_block_info(dev, dev->alloc_block);
+
+ ret_val = (dev->alloc_block * dev->param.chunks_per_block) +
+ dev->alloc_page;
+ bi->pages_in_use++;
+ yaffs_set_chunk_bit(dev, dev->alloc_block, dev->alloc_page);
+
+ dev->alloc_page++;
+
+ dev->n_free_chunks--;
+
+ /* If the block is full set the state to full */
+ if (dev->alloc_page >= dev->param.chunks_per_block) {
+ bi->block_state = YAFFS_BLOCK_STATE_FULL;
+ dev->alloc_block = -1;
+ }
+
+ if (block_ptr)
+ *block_ptr = bi;
+
+ return ret_val;
+ }
+
+ yaffs_trace(YAFFS_TRACE_ERROR,
+ "!!!!!!!!! Allocator out !!!!!!!!!!!!!!!!!");
+
+ return -1;
+}
+
+static int yaffs_get_erased_chunks(struct yaffs_dev *dev)
+{
+ int n;
+
+ n = dev->n_erased_blocks * dev->param.chunks_per_block;
+
+ if (dev->alloc_block > 0)
+ n += (dev->param.chunks_per_block - dev->alloc_page);
+
+ return n;
+
+}
+
+/*
+ * yaffs_skip_rest_of_block() skips over the rest of the allocation block
+ * if we don't want to write to it.
+ */
+void yaffs_skip_rest_of_block(struct yaffs_dev *dev)
+{
+ struct yaffs_block_info *bi;
+
+ if (dev->alloc_block > 0) {
+ bi = yaffs_get_block_info(dev, dev->alloc_block);
+ if (bi->block_state == YAFFS_BLOCK_STATE_ALLOCATING) {
+ bi->block_state = YAFFS_BLOCK_STATE_FULL;
+ dev->alloc_block = -1;
+ }
+ }
+}
+
+static int yaffs_write_new_chunk(struct yaffs_dev *dev,
+ const u8 *data,
+ struct yaffs_ext_tags *tags, int use_reserver)
+{
+ u32 attempts = 0;
+ int write_ok = 0;
+ int chunk;
+
+ yaffs2_checkpt_invalidate(dev);
+
+ do {
+ struct yaffs_block_info *bi = 0;
+ int erased_ok = 0;
+
+ chunk = yaffs_alloc_chunk(dev, use_reserver, &bi);
+ if (chunk < 0) {
+ /* no space */
+ break;
+ }
+
+ /* First check this chunk is erased, if it needs
+ * checking. The checking policy (unless forced
+ * always on) is as follows:
+ *
+ * Check the first page we try to write in a block.
+ * If the check passes then we don't need to check any
+ * more. If the check fails, we check again...
+ * If the block has been erased, we don't need to check.
+ *
+ * However, if the block has been prioritised for gc,
+ * then we think there might be something odd about
+ * this block and stop using it.
+ *
+ * Rationale: We should only ever see chunks that have
+ * not been erased if there was a partially written
+ * chunk due to power loss. This checking policy should
+ * catch that case with very few checks and thus save a
+ * lot of checks that are most likely not needed.
+ *
+ * Mods to the above
+ * If an erase check fails or the write fails we skip the
+ * rest of the block.
+ */
+
+ /* let's give it a try */
+ attempts++;
+
+ if (dev->param.always_check_erased)
+ bi->skip_erased_check = 0;
+
+ if (!bi->skip_erased_check) {
+ erased_ok = yaffs_check_chunk_erased(dev, chunk);
+ if (erased_ok != YAFFS_OK) {
+ yaffs_trace(YAFFS_TRACE_ERROR,
+ "**>> yaffs chunk %d was not erased",
+ chunk);
+
+ /* If not erased, delete this one,
+ * skip rest of block and
+ * try another chunk */
+ yaffs_chunk_del(dev, chunk, 1, __LINE__);
+ yaffs_skip_rest_of_block(dev);
+ continue;
+ }
+ }
+
+ write_ok = yaffs_wr_chunk_tags_nand(dev, chunk, data, tags);
+
+ if (!bi->skip_erased_check)
+ write_ok =
+ yaffs_verify_chunk_written(dev, chunk, data, tags);
+
+ if (write_ok != YAFFS_OK) {
+ /* Clean up aborted write, skip to next block and
+ * try another chunk */
+ yaffs_handle_chunk_wr_error(dev, chunk, erased_ok);
+ continue;
+ }
+
+ bi->skip_erased_check = 1;
+
+ /* Copy the data into the robustification buffer */
+ yaffs_handle_chunk_wr_ok(dev, chunk, data, tags);
+
+ } while (write_ok != YAFFS_OK &&
+ (yaffs_wr_attempts == 0 || attempts <= yaffs_wr_attempts));
+
+ if (!write_ok)
+ chunk = -1;
+
+ if (attempts > 1) {
+ yaffs_trace(YAFFS_TRACE_ERROR,
+ "**>> yaffs write required %d attempts",
+ attempts);
+ dev->n_retried_writes += (attempts - 1);
+ }
+
+ return chunk;
+}
+
+/*
+ * Block retiring for handling a broken block.
+ */
+
+static void yaffs_retire_block(struct yaffs_dev *dev, int flash_block)
+{
+ struct yaffs_block_info *bi = yaffs_get_block_info(dev, flash_block);
+
+ yaffs2_checkpt_invalidate(dev);
+
+ yaffs2_clear_oldest_dirty_seq(dev, bi);
+
+ if (yaffs_mark_bad(dev, flash_block) != YAFFS_OK) {
+ if (yaffs_erase_block(dev, flash_block) != YAFFS_OK) {
+ yaffs_trace(YAFFS_TRACE_ALWAYS,
+ "yaffs: Failed to mark bad and erase block %d",
+ flash_block);
+ } else {
+ struct yaffs_ext_tags tags;
+ int chunk_id =
+ flash_block * dev->param.chunks_per_block;
+
+ u8 *buffer = yaffs_get_temp_buffer(dev);
+
+ memset(buffer, 0xff, dev->data_bytes_per_chunk);
+ memset(&tags, 0, sizeof(tags));
+ tags.seq_number = YAFFS_SEQUENCE_BAD_BLOCK;
+ if (dev->tagger.write_chunk_tags_fn(dev, chunk_id -
+ dev->chunk_offset,
+ buffer,
+ &tags) != YAFFS_OK)
+ yaffs_trace(YAFFS_TRACE_ALWAYS,
+ "yaffs: Failed to write bad block marker to block %d",
+ flash_block);
+
+ yaffs_release_temp_buffer(dev, buffer);
+ }
+ }
+
+ bi->block_state = YAFFS_BLOCK_STATE_DEAD;
+ bi->gc_prioritise = 0;
+ bi->needs_retiring = 0;
+
+ dev->n_retired_blocks++;
+}
+
+/*---------------- Name handling functions ------------*/
+
+static void yaffs_load_name_from_oh(struct yaffs_dev *dev, YCHAR *name,
+ const YCHAR *oh_name, int buff_size)
+{
+#ifdef CONFIG_YAFFS_AUTO_UNICODE
+ if (dev->param.auto_unicode) {
+ if (*oh_name) {
+ /* It is an ASCII name, do an ASCII to
+ * unicode conversion */
+ const char *ascii_oh_name = (const char *)oh_name;
+ int n = buff_size - 1;
+ while (n > 0 && *ascii_oh_name) {
+ *name = *ascii_oh_name;
+ name++;
+ ascii_oh_name++;
+ n--;
+ }
+ } else {
+ strncpy(name, oh_name + 1, buff_size - 1);
+ }
+ } else {
+#else
+ (void) dev;
+ {
+#endif
+ strncpy(name, oh_name, buff_size - 1);
+ }
+}
+
+static void yaffs_load_oh_from_name(struct yaffs_dev *dev, YCHAR *oh_name,
+ const YCHAR *name)
+{
+#ifdef CONFIG_YAFFS_AUTO_UNICODE
+
+ int is_ascii;
+ const YCHAR *w;
+
+ if (dev->param.auto_unicode) {
+
+ is_ascii = 1;
+ w = name;
+
+ /* Figure out if the name will fit in ascii character set */
+ while (is_ascii && *w) {
+ if ((*w) & 0xff00)
+ is_ascii = 0;
+ w++;
+ }
+
+ if (is_ascii) {
+ /* It is an ASCII name, so convert unicode to ascii */
+ char *ascii_oh_name = (char *)oh_name;
+ int n = YAFFS_MAX_NAME_LENGTH - 1;
+ while (n > 0 && *name) {
+ *ascii_oh_name = *name;
+ name++;
+ ascii_oh_name++;
+ n--;
+ }
+ } else {
+ /* Unicode name, so save starting at the second YCHAR */
+ *oh_name = 0;
+ strncpy(oh_name + 1, name, YAFFS_MAX_NAME_LENGTH - 2);
+ }
+ } else {
+#else
+ dev = dev;
+ {
+#endif
+ strncpy(oh_name, name, YAFFS_MAX_NAME_LENGTH - 1);
+ }
+}
+
+static u16 yaffs_calc_name_sum(const YCHAR *name)
+{
+ u16 sum = 0;
+ u16 i = 1;
+
+ if (!name)
+ return 0;
+
+ while ((*name) && i < (YAFFS_MAX_NAME_LENGTH / 2)) {
+
+ /* 0x1f mask is case insensitive */
+ sum += ((*name) & 0x1f) * i;
+ i++;
+ name++;
+ }
+ return sum;
+}
+
+
+void yaffs_set_obj_name(struct yaffs_obj *obj, const YCHAR * name)
+{
+ memset(obj->short_name, 0, sizeof(obj->short_name));
+
+ if (name && !name[0]) {
+ yaffs_fix_null_name(obj, obj->short_name,
+ YAFFS_SHORT_NAME_LENGTH);
+ name = obj->short_name;
+ } else if (name &&
+ strnlen(name, YAFFS_SHORT_NAME_LENGTH + 1) <=
+ YAFFS_SHORT_NAME_LENGTH) {
+ strcpy(obj->short_name, name);
+ }
+
+ obj->sum = yaffs_calc_name_sum(name);
+}
+
+void yaffs_set_obj_name_from_oh(struct yaffs_obj *obj,
+ const struct yaffs_obj_hdr *oh)
+{
+#ifdef CONFIG_YAFFS_AUTO_UNICODE
+ YCHAR tmp_name[YAFFS_MAX_NAME_LENGTH + 1];
+ memset(tmp_name, 0, sizeof(tmp_name));
+ yaffs_load_name_from_oh(obj->my_dev, tmp_name, oh->name,
+ YAFFS_MAX_NAME_LENGTH + 1);
+ yaffs_set_obj_name(obj, tmp_name);
+#else
+ yaffs_set_obj_name(obj, oh->name);
+#endif
+}
+
+loff_t yaffs_max_file_size(struct yaffs_dev *dev)
+{
+ if (sizeof(loff_t) < 8)
+ return YAFFS_MAX_FILE_SIZE_32;
+ else
+ return ((loff_t) YAFFS_MAX_CHUNK_ID) * dev->data_bytes_per_chunk;
+}
+
+/*-------------------- TNODES -------------------
+
+ * List of spare tnodes
+ * The list is hooked together using the first pointer
+ * in the tnode.
+ */
+
+struct yaffs_tnode *yaffs_get_tnode(struct yaffs_dev *dev)
+{
+ struct yaffs_tnode *tn = yaffs_alloc_raw_tnode(dev);
+
+ if (tn) {
+ memset(tn, 0, dev->tnode_size);
+ dev->n_tnodes++;
+ }
+
+ dev->checkpoint_blocks_required = 0; /* force recalculation */
+
+ return tn;
+}
+
+/* FreeTnode frees up a tnode and puts it back on the free list */
+static void yaffs_free_tnode(struct yaffs_dev *dev, struct yaffs_tnode *tn)
+{
+ yaffs_free_raw_tnode(dev, tn);
+ dev->n_tnodes--;
+ dev->checkpoint_blocks_required = 0; /* force recalculation */
+}
+
+static void yaffs_deinit_tnodes_and_objs(struct yaffs_dev *dev)
+{
+ yaffs_deinit_raw_tnodes_and_objs(dev);
+ dev->n_obj = 0;
+ dev->n_tnodes = 0;
+}
+
+static void yaffs_load_tnode_0(struct yaffs_dev *dev, struct yaffs_tnode *tn,
+ unsigned pos, unsigned val)
+{
+ u32 *map = (u32 *) tn;
+ u32 bit_in_map;
+ u32 bit_in_word;
+ u32 word_in_map;
+ u32 mask;
+
+ pos &= YAFFS_TNODES_LEVEL0_MASK;
+ val >>= dev->chunk_grp_bits;
+
+ bit_in_map = pos * dev->tnode_width;
+ word_in_map = bit_in_map / 32;
+ bit_in_word = bit_in_map & (32 - 1);
+
+ mask = dev->tnode_mask << bit_in_word;
+
+ map[word_in_map] &= ~mask;
+ map[word_in_map] |= (mask & (val << bit_in_word));
+
+ if (dev->tnode_width > (32 - bit_in_word)) {
+ bit_in_word = (32 - bit_in_word);
+ word_in_map++;
+ mask =
+ dev->tnode_mask >> bit_in_word;
+ map[word_in_map] &= ~mask;
+ map[word_in_map] |= (mask & (val >> bit_in_word));
+ }
+}
+
+u32 yaffs_get_group_base(struct yaffs_dev *dev, struct yaffs_tnode *tn,
+ unsigned pos)
+{
+ u32 *map = (u32 *) tn;
+ u32 bit_in_map;
+ u32 bit_in_word;
+ u32 word_in_map;
+ u32 val;
+
+ pos &= YAFFS_TNODES_LEVEL0_MASK;
+
+ bit_in_map = pos * dev->tnode_width;
+ word_in_map = bit_in_map / 32;
+ bit_in_word = bit_in_map & (32 - 1);
+
+ val = map[word_in_map] >> bit_in_word;
+
+ if (dev->tnode_width > (32 - bit_in_word)) {
+ bit_in_word = (32 - bit_in_word);
+ word_in_map++;
+ val |= (map[word_in_map] << bit_in_word);
+ }
+
+ val &= dev->tnode_mask;
+ val <<= dev->chunk_grp_bits;
+
+ return val;
+}
+
+/* ------------------- End of individual tnode manipulation -----------------*/
+
+/* ---------Functions to manipulate the look-up tree (made up of tnodes) ------
+ * The look up tree is represented by the top tnode and the number of top_level
+ * in the tree. 0 means only the level 0 tnode is in the tree.
+ */
+
+/* FindLevel0Tnode finds the level 0 tnode, if one exists. */
+struct yaffs_tnode *yaffs_find_tnode_0(struct yaffs_dev *dev,
+ struct yaffs_file_var *file_struct,
+ u32 chunk_id)
+{
+ struct yaffs_tnode *tn = file_struct->top;
+ u32 i;
+ int required_depth;
+ int level = file_struct->top_level;
+
+ (void) dev;
+
+ /* Check sane level and chunk Id */
+ if (level < 0 || level > YAFFS_TNODES_MAX_LEVEL)
+ return NULL;
+
+ if (chunk_id > YAFFS_MAX_CHUNK_ID)
+ return NULL;
+
+ /* First check we're tall enough (ie enough top_level) */
+
+ i = chunk_id >> YAFFS_TNODES_LEVEL0_BITS;
+ required_depth = 0;
+ while (i) {
+ i >>= YAFFS_TNODES_INTERNAL_BITS;
+ required_depth++;
+ }
+
+ if (required_depth > file_struct->top_level)
+ return NULL; /* Not tall enough, so we can't find it */
+
+ /* Traverse down to level 0 */
+ while (level > 0 && tn) {
+ tn = tn->internal[(chunk_id >>
+ (YAFFS_TNODES_LEVEL0_BITS +
+ (level - 1) *
+ YAFFS_TNODES_INTERNAL_BITS)) &
+ YAFFS_TNODES_INTERNAL_MASK];
+ level--;
+ }
+
+ return tn;
+}
+
+/* add_find_tnode_0 finds the level 0 tnode if it exists,
+ * otherwise first expands the tree.
+ * This happens in two steps:
+ * 1. If the tree isn't tall enough, then make it taller.
+ * 2. Scan down the tree towards the level 0 tnode adding tnodes if required.
+ *
+ * Used when modifying the tree.
+ *
+ * If the tn argument is NULL, then a fresh tnode will be added otherwise the
+ * specified tn will be plugged into the ttree.
+ */
+
+struct yaffs_tnode *yaffs_add_find_tnode_0(struct yaffs_dev *dev,
+ struct yaffs_file_var *file_struct,
+ u32 chunk_id,
+ struct yaffs_tnode *passed_tn)
+{
+ int required_depth;
+ int i;
+ int l;
+ struct yaffs_tnode *tn;
+ u32 x;
+
+ /* Check sane level and page Id */
+ if (file_struct->top_level < 0 ||
+ file_struct->top_level > YAFFS_TNODES_MAX_LEVEL)
+ return NULL;
+
+ if (chunk_id > YAFFS_MAX_CHUNK_ID)
+ return NULL;
+
+ /* First check we're tall enough (ie enough top_level) */
+
+ x = chunk_id >> YAFFS_TNODES_LEVEL0_BITS;
+ required_depth = 0;
+ while (x) {
+ x >>= YAFFS_TNODES_INTERNAL_BITS;
+ required_depth++;
+ }
+
+ if (required_depth > file_struct->top_level) {
+ /* Not tall enough, gotta make the tree taller */
+ for (i = file_struct->top_level; i < required_depth; i++) {
+
+ tn = yaffs_get_tnode(dev);
+
+ if (tn) {
+ tn->internal[0] = file_struct->top;
+ file_struct->top = tn;
+ file_struct->top_level++;
+ } else {
+ yaffs_trace(YAFFS_TRACE_ERROR,
+ "yaffs: no more tnodes");
+ return NULL;
+ }
+ }
+ }
+
+ /* Traverse down to level 0, adding anything we need */
+
+ l = file_struct->top_level;
+ tn = file_struct->top;
+
+ if (l > 0) {
+ while (l > 0 && tn) {
+ x = (chunk_id >>
+ (YAFFS_TNODES_LEVEL0_BITS +
+ (l - 1) * YAFFS_TNODES_INTERNAL_BITS)) &
+ YAFFS_TNODES_INTERNAL_MASK;
+
+ if ((l > 1) && !tn->internal[x]) {
+ /* Add missing non-level-zero tnode */
+ tn->internal[x] = yaffs_get_tnode(dev);
+ if (!tn->internal[x])
+ return NULL;
+ } else if (l == 1) {
+ /* Looking from level 1 at level 0 */
+ if (passed_tn) {
+ /* If we already have one, release it */
+ if (tn->internal[x])
+ yaffs_free_tnode(dev,
+ tn->internal[x]);
+ tn->internal[x] = passed_tn;
+
+ } else if (!tn->internal[x]) {
+ /* Don't have one, none passed in */
+ tn->internal[x] = yaffs_get_tnode(dev);
+ if (!tn->internal[x])
+ return NULL;
+ }
+ }
+
+ tn = tn->internal[x];
+ l--;
+ }
+ } else {
+ /* top is level 0 */
+ if (passed_tn) {
+ memcpy(tn, passed_tn,
+ (dev->tnode_width * YAFFS_NTNODES_LEVEL0) / 8);
+ yaffs_free_tnode(dev, passed_tn);
+ }
+ }
+
+ return tn;
+}
+
+static int yaffs_tags_match(const struct yaffs_ext_tags *tags, int obj_id,
+ int chunk_obj)
+{
+ return (tags->chunk_id == (u32)chunk_obj &&
+ tags->obj_id == (u32)obj_id &&
+ !tags->is_deleted) ? 1 : 0;
+
+}
+
+static int yaffs_find_chunk_in_group(struct yaffs_dev *dev, int the_chunk,
+ struct yaffs_ext_tags *tags, int obj_id,
+ int inode_chunk)
+{
+ int j;
+
+ for (j = 0; the_chunk && j < dev->chunk_grp_size; j++) {
+ if (yaffs_check_chunk_bit
+ (dev, the_chunk / dev->param.chunks_per_block,
+ the_chunk % dev->param.chunks_per_block)) {
+
+ if (dev->chunk_grp_size == 1)
+ return the_chunk;
+ else {
+ yaffs_rd_chunk_tags_nand(dev, the_chunk, NULL,
+ tags);
+ if (yaffs_tags_match(tags,
+ obj_id, inode_chunk)) {
+ /* found it; */
+ return the_chunk;
+ }
+ }
+ }
+ the_chunk++;
+ }
+ return -1;
+}
+
+int yaffs_find_chunk_in_file(struct yaffs_obj *in, int inode_chunk,
+ struct yaffs_ext_tags *tags)
+{
+ /*Get the Tnode, then get the level 0 offset chunk offset */
+ struct yaffs_tnode *tn;
+ int the_chunk = -1;
+ struct yaffs_ext_tags local_tags;
+ int ret_val = -1;
+ struct yaffs_dev *dev = in->my_dev;
+
+ if (!tags) {
+ /* Passed a NULL, so use our own tags space */
+ tags = &local_tags;
+ }
+
+ tn = yaffs_find_tnode_0(dev, &in->variant.file_variant, inode_chunk);
+
+ if (!tn)
+ return ret_val;
+
+ the_chunk = yaffs_get_group_base(dev, tn, inode_chunk);
+
+ ret_val = yaffs_find_chunk_in_group(dev, the_chunk, tags, in->obj_id,
+ inode_chunk);
+ return ret_val;
+}
+
+static int yaffs_find_del_file_chunk(struct yaffs_obj *in, int inode_chunk,
+ struct yaffs_ext_tags *tags)
+{
+ /* Get the Tnode, then get the level 0 offset chunk offset */
+ struct yaffs_tnode *tn;
+ int the_chunk = -1;
+ struct yaffs_ext_tags local_tags;
+ struct yaffs_dev *dev = in->my_dev;
+ int ret_val = -1;
+
+ if (!tags) {
+ /* Passed a NULL, so use our own tags space */
+ tags = &local_tags;
+ }
+
+ tn = yaffs_find_tnode_0(dev, &in->variant.file_variant, inode_chunk);
+
+ if (!tn)
+ return ret_val;
+
+ the_chunk = yaffs_get_group_base(dev, tn, inode_chunk);
+
+ ret_val = yaffs_find_chunk_in_group(dev, the_chunk, tags, in->obj_id,
+ inode_chunk);
+
+ /* Delete the entry in the filestructure (if found) */
+ if (ret_val != -1)
+ yaffs_load_tnode_0(dev, tn, inode_chunk, 0);
+
+ return ret_val;
+}
+
+int yaffs_put_chunk_in_file(struct yaffs_obj *in, int inode_chunk,
+ int nand_chunk, int in_scan)
+{
+ /* NB in_scan is zero unless scanning.
+ * For forward scanning, in_scan is > 0;
+ * for backward scanning in_scan is < 0
+ *
+ * nand_chunk = 0 is a dummy insert to make sure the tnodes are there.
+ */
+
+ struct yaffs_tnode *tn;
+ struct yaffs_dev *dev = in->my_dev;
+ int existing_cunk;
+ struct yaffs_ext_tags existing_tags;
+ struct yaffs_ext_tags new_tags;
+ unsigned existing_serial, new_serial;
+
+ if (in->variant_type != YAFFS_OBJECT_TYPE_FILE) {
+ /* Just ignore an attempt at putting a chunk into a non-file
+ * during scanning.
+ * If it is not during Scanning then something went wrong!
+ */
+ if (!in_scan) {
+ yaffs_trace(YAFFS_TRACE_ERROR,
+ "yaffs tragedy:attempt to put data chunk into a non-file"
+ );
+ BUG();
+ }
+
+ yaffs_chunk_del(dev, nand_chunk, 1, __LINE__);
+ return YAFFS_OK;
+ }
+
+ tn = yaffs_add_find_tnode_0(dev,
+ &in->variant.file_variant,
+ inode_chunk, NULL);
+ if (!tn)
+ return YAFFS_FAIL;
+
+ if (!nand_chunk)
+ /* Dummy insert, bail now */
+ return YAFFS_OK;
+
+ existing_cunk = yaffs_get_group_base(dev, tn, inode_chunk);
+
+ if (in_scan != 0) {
+ /* If we're scanning then we need to test for duplicates
+ * NB This does not need to be efficient since it should only
+ * happen when the power fails during a write, then only one
+ * chunk should ever be affected.
+ *
+ * Correction for YAFFS2: This could happen quite a lot and we
+ * need to think about efficiency! TODO
+ * Update: For backward scanning we don't need to re-read tags
+ * so this is quite cheap.
+ */
+
+ if (existing_cunk > 0) {
+ /* NB Right now existing chunk will not be real
+ * chunk_id if the chunk group size > 1
+ * thus we have to do a FindChunkInFile to get the
+ * real chunk id.
+ *
+ * We have a duplicate now we need to decide which
+ * one to use:
+ *
+ * Backwards scanning YAFFS2: The old one is what
+ * we use, dump the new one.
+ * YAFFS1: Get both sets of tags and compare serial
+ * numbers.
+ */
+
+ if (in_scan > 0) {
+ /* Only do this for forward scanning */
+ yaffs_rd_chunk_tags_nand(dev,
+ nand_chunk,
+ NULL, &new_tags);
+
+ /* Do a proper find */
+ existing_cunk =
+ yaffs_find_chunk_in_file(in, inode_chunk,
+ &existing_tags);
+ }
+
+ if (existing_cunk <= 0) {
+ /*Hoosterman - how did this happen? */
+
+ yaffs_trace(YAFFS_TRACE_ERROR,
+ "yaffs tragedy: existing chunk < 0 in scan"
+ );
+
+ }
+
+ /* NB The deleted flags should be false, otherwise
+ * the chunks will not be loaded during a scan
+ */
+
+ if (in_scan > 0) {
+ new_serial = new_tags.serial_number;
+ existing_serial = existing_tags.serial_number;
+ }
+
+ if ((in_scan > 0) &&
+ (existing_cunk <= 0 ||
+ ((existing_serial + 1) & 3) == new_serial)) {
+ /* Forward scanning.
+ * Use new
+ * Delete the old one and drop through to
+ * update the tnode
+ */
+ yaffs_chunk_del(dev, existing_cunk, 1,
+ __LINE__);
+ } else {
+ /* Backward scanning or we want to use the
+ * existing one
+ * Delete the new one and return early so that
+ * the tnode isn't changed
+ */
+ yaffs_chunk_del(dev, nand_chunk, 1, __LINE__);
+ return YAFFS_OK;
+ }
+ }
+
+ }
+
+ if (existing_cunk == 0)
+ in->n_data_chunks++;
+
+ yaffs_load_tnode_0(dev, tn, inode_chunk, nand_chunk);
+
+ return YAFFS_OK;
+}
+
+static void yaffs_soft_del_chunk(struct yaffs_dev *dev, int chunk)
+{
+ struct yaffs_block_info *the_block;
+ unsigned block_no;
+
+ yaffs_trace(YAFFS_TRACE_DELETION, "soft delete chunk %d", chunk);
+
+ block_no = chunk / dev->param.chunks_per_block;
+ the_block = yaffs_get_block_info(dev, block_no);
+ if (the_block) {
+ the_block->soft_del_pages++;
+ dev->n_free_chunks++;
+ yaffs2_update_oldest_dirty_seq(dev, block_no, the_block);
+ }
+}
+
+/* SoftDeleteWorker scans backwards through the tnode tree and soft deletes all
+ * the chunks in the file.
+ * All soft deleting does is increment the block's softdelete count and pulls
+ * the chunk out of the tnode.
+ * Thus, essentially this is the same as DeleteWorker except that the chunks
+ * are soft deleted.
+ */
+
+static int yaffs_soft_del_worker(struct yaffs_obj *in, struct yaffs_tnode *tn,
+ u32 level, int chunk_offset)
+{
+ int i;
+ int the_chunk;
+ int all_done = 1;
+ struct yaffs_dev *dev = in->my_dev;
+
+ if (!tn)
+ return 1;
+
+ if (level > 0) {
+ for (i = YAFFS_NTNODES_INTERNAL - 1;
+ all_done && i >= 0;
+ i--) {
+ if (tn->internal[i]) {
+ all_done =
+ yaffs_soft_del_worker(in,
+ tn->internal[i],
+ level - 1,
+ (chunk_offset <<
+ YAFFS_TNODES_INTERNAL_BITS)
+ + i);
+ if (all_done) {
+ yaffs_free_tnode(dev,
+ tn->internal[i]);
+ tn->internal[i] = NULL;
+ } else {
+ /* Can this happen? */
+ }
+ }
+ }
+ return (all_done) ? 1 : 0;
+ }
+
+ /* level 0 */
+ for (i = YAFFS_NTNODES_LEVEL0 - 1; i >= 0; i--) {
+ the_chunk = yaffs_get_group_base(dev, tn, i);
+ if (the_chunk) {
+ yaffs_soft_del_chunk(dev, the_chunk);
+ yaffs_load_tnode_0(dev, tn, i, 0);
+ }
+ }
+ return 1;
+}
+
+static void yaffs_remove_obj_from_dir(struct yaffs_obj *obj)
+{
+ struct yaffs_dev *dev = obj->my_dev;
+ struct yaffs_obj *parent;
+
+ yaffs_verify_obj_in_dir(obj);
+ parent = obj->parent;
+
+ yaffs_verify_dir(parent);
+
+ if (dev && dev->param.remove_obj_fn)
+ dev->param.remove_obj_fn(obj);
+
+ list_del_init(&obj->siblings);
+ obj->parent = NULL;
+
+ yaffs_verify_dir(parent);
+}
+
+void yaffs_add_obj_to_dir(struct yaffs_obj *directory, struct yaffs_obj *obj)
+{
+ if (!directory) {
+ yaffs_trace(YAFFS_TRACE_ALWAYS,
+ "tragedy: Trying to add an object to a null pointer directory"
+ );
+ BUG();
+ return;
+ }
+ if (directory->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) {
+ yaffs_trace(YAFFS_TRACE_ALWAYS,
+ "tragedy: Trying to add an object to a non-directory"
+ );
+ BUG();
+ }
+
+ if (obj->siblings.prev == NULL) {
+ /* Not initialised */
+ BUG();
+ }
+
+ yaffs_verify_dir(directory);
+
+ yaffs_remove_obj_from_dir(obj);
+
+ /* Now add it */
+ list_add(&obj->siblings, &directory->variant.dir_variant.children);
+ obj->parent = directory;
+
+ if (directory == obj->my_dev->unlinked_dir
+ || directory == obj->my_dev->del_dir) {
+ obj->unlinked = 1;
+ obj->my_dev->n_unlinked_files++;
+ obj->rename_allowed = 0;
+ }
+
+ yaffs_verify_dir(directory);
+ yaffs_verify_obj_in_dir(obj);
+}
+
+static int yaffs_change_obj_name(struct yaffs_obj *obj,
+ struct yaffs_obj *new_dir,
+ const YCHAR *new_name, int force, int shadows)
+{
+ int unlink_op;
+ int del_op;
+ struct yaffs_obj *existing_target;
+
+ if (new_dir == NULL)
+ new_dir = obj->parent; /* use the old directory */
+
+ if (new_dir->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) {
+ yaffs_trace(YAFFS_TRACE_ALWAYS,
+ "tragedy: yaffs_change_obj_name: new_dir is not a directory"
+ );
+ BUG();
+ }
+
+ unlink_op = (new_dir == obj->my_dev->unlinked_dir);
+ del_op = (new_dir == obj->my_dev->del_dir);
+
+ existing_target = yaffs_find_by_name(new_dir, new_name);
+
+ /* If the object is a file going into the unlinked directory,
+ * then it is OK to just stuff it in since duplicate names are OK.
+ * else only proceed if the new name does not exist and we're putting
+ * it into a directory.
+ */
+ if (!(unlink_op || del_op || force ||
+ shadows > 0 || !existing_target) ||
+ new_dir->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY)
+ return YAFFS_FAIL;
+
+ yaffs_set_obj_name(obj, new_name);
+ obj->dirty = 1;
+ yaffs_add_obj_to_dir(new_dir, obj);
+
+ if (unlink_op)
+ obj->unlinked = 1;
+
+ /* If it is a deletion then we mark it as a shrink for gc */
+ if (yaffs_update_oh(obj, new_name, 0, del_op, shadows, NULL) >= 0)
+ return YAFFS_OK;
+
+ return YAFFS_FAIL;
+}
+
+/*------------------------ Short Operations Cache ------------------------------
+ * In many situations where there is no high level buffering a lot of
+ * reads might be short sequential reads, and a lot of writes may be short
+ * sequential writes. eg. scanning/writing a jpeg file.
+ * In these cases, a short read/write cache can provide a huge perfomance
+ * benefit with dumb-as-a-rock code.
+ * In Linux, the page cache provides read buffering and the short op cache
+ * provides write buffering.
+ *
+ * There are a small number (~10) of cache chunks per device so that we don't
+ * need a very intelligent search.
+ */
+
+static int yaffs_obj_cache_dirty(struct yaffs_obj *obj)
+{
+ struct yaffs_dev *dev = obj->my_dev;
+ int i;
+ struct yaffs_cache *cache;
+ int n_caches = obj->my_dev->param.n_caches;
+
+ for (i = 0; i < n_caches; i++) {
+ cache = &dev->cache[i];
+ if (cache->object == obj && cache->dirty)
+ return 1;
+ }
+
+ return 0;
+}
+
+static void yaffs_flush_single_cache(struct yaffs_cache *cache, int discard)
+{
+
+ if (!cache || cache->locked)
+ return;
+
+ /* Write it out and free it up if need be.*/
+ if (cache->dirty) {
+ yaffs_wr_data_obj(cache->object,
+ cache->chunk_id,
+ cache->data,
+ cache->n_bytes,
+ 1);
+
+ cache->dirty = 0;
+ }
+
+ if (discard)
+ cache->object = NULL;
+}
+
+static void yaffs_flush_file_cache(struct yaffs_obj *obj, int discard)
+{
+ struct yaffs_dev *dev = obj->my_dev;
+ int i;
+ struct yaffs_cache *cache;
+ int n_caches = obj->my_dev->param.n_caches;
+
+ if (n_caches < 1)
+ return;
+
+
+ /* Find the chunks for this object and flush them. */
+ for (i = 0; i < n_caches; i++) {
+ cache = &dev->cache[i];
+ if (cache->object == obj)
+ yaffs_flush_single_cache(cache, discard);
+ }
+
+}
+
+
+void yaffs_flush_whole_cache(struct yaffs_dev *dev, int discard)
+{
+ struct yaffs_obj *obj;
+ int n_caches = dev->param.n_caches;
+ int i;
+
+ /* Find a dirty object in the cache and flush it...
+ * until there are no further dirty objects.
+ */
+ do {
+ obj = NULL;
+ for (i = 0; i < n_caches && !obj; i++) {
+ if (dev->cache[i].object && dev->cache[i].dirty)
+ obj = dev->cache[i].object;
+ }
+ if (obj)
+ yaffs_flush_file_cache(obj, discard);
+ } while (obj);
+
+}
+
+/* Grab us an unused cache chunk for use.
+ * First look for an empty one.
+ * Then look for the least recently used non-dirty one.
+ * Then look for the least recently used dirty one...., flush and look again.
+ */
+static struct yaffs_cache *yaffs_grab_chunk_worker(struct yaffs_dev *dev)
+{
+ u32 i;
+
+ if (dev->param.n_caches > 0) {
+ for (i = 0; i < dev->param.n_caches; i++) {
+ if (!dev->cache[i].object)
+ return &dev->cache[i];
+ }
+ }
+
+ return NULL;
+}
+
+static struct yaffs_cache *yaffs_grab_chunk_cache(struct yaffs_dev *dev)
+{
+ struct yaffs_cache *cache;
+ int usage;
+ u32 i;
+
+ if (dev->param.n_caches < 1)
+ return NULL;
+
+ /* First look for an unused cache */
+
+ cache = yaffs_grab_chunk_worker(dev);
+
+ if (cache)
+ return cache;
+
+ /*
+ * Thery were all in use.
+ * Find the LRU cache and flush it if it is dirty.
+ */
+
+ usage = -1;
+ cache = NULL;
+
+ for (i = 0; i < dev->param.n_caches; i++) {
+ if (dev->cache[i].object &&
+ !dev->cache[i].locked &&
+ (dev->cache[i].last_use < usage || !cache)) {
+ usage = dev->cache[i].last_use;
+ cache = &dev->cache[i];
+ }
+ }
+
+#if 1
+ yaffs_flush_single_cache(cache, 1);
+#else
+ yaffs_flush_file_cache(cache->object, 1);
+ cache = yaffs_grab_chunk_worker(dev);
+#endif
+
+ return cache;
+}
+
+/* Find a cached chunk */
+static struct yaffs_cache *yaffs_find_chunk_cache(const struct yaffs_obj *obj,
+ int chunk_id)
+{
+ struct yaffs_dev *dev = obj->my_dev;
+ u32 i;
+
+ if (dev->param.n_caches < 1)
+ return NULL;
+
+ for (i = 0; i < dev->param.n_caches; i++) {
+ if (dev->cache[i].object == obj &&
+ dev->cache[i].chunk_id == chunk_id) {
+ dev->cache_hits++;
+
+ return &dev->cache[i];
+ }
+ }
+ return NULL;
+}
+
+/* Mark the chunk for the least recently used algorithym */
+static void yaffs_use_cache(struct yaffs_dev *dev, struct yaffs_cache *cache,
+ int is_write)
+{
+ u32 i;
+
+ if (dev->param.n_caches < 1)
+ return;
+
+ if (dev->cache_last_use < 0 ||
+ dev->cache_last_use > 100000000) {
+ /* Reset the cache usages */
+ for (i = 1; i < dev->param.n_caches; i++)
+ dev->cache[i].last_use = 0;
+
+ dev->cache_last_use = 0;
+ }
+ dev->cache_last_use++;
+ cache->last_use = dev->cache_last_use;
+
+ if (is_write)
+ cache->dirty = 1;
+}
+
+/* Invalidate a single cache page.
+ * Do this when a whole page gets written,
+ * ie the short cache for this page is no longer valid.
+ */
+static void yaffs_invalidate_chunk_cache(struct yaffs_obj *object, int chunk_id)
+{
+ struct yaffs_cache *cache;
+
+ if (object->my_dev->param.n_caches > 0) {
+ cache = yaffs_find_chunk_cache(object, chunk_id);
+
+ if (cache)
+ cache->object = NULL;
+ }
+}
+
+/* Invalidate all the cache pages associated with this object
+ * Do this whenever ther file is deleted or resized.
+ */
+static void yaffs_invalidate_whole_cache(struct yaffs_obj *in)
+{
+ u32 i;
+ struct yaffs_dev *dev = in->my_dev;
+
+ if (dev->param.n_caches > 0) {
+ /* Invalidate it. */
+ for (i = 0; i < dev->param.n_caches; i++) {
+ if (dev->cache[i].object == in)
+ dev->cache[i].object = NULL;
+ }
+ }
+}
+
+static void yaffs_unhash_obj(struct yaffs_obj *obj)
+{
+ int bucket;
+ struct yaffs_dev *dev = obj->my_dev;
+
+ /* If it is still linked into the bucket list, free from the list */
+ if (!list_empty(&obj->hash_link)) {
+ list_del_init(&obj->hash_link);
+ bucket = yaffs_hash_fn(obj->obj_id);
+ dev->obj_bucket[bucket].count--;
+ }
+}
+
+/* FreeObject frees up a Object and puts it back on the free list */
+static void yaffs_free_obj(struct yaffs_obj *obj)
+{
+ struct yaffs_dev *dev;
+
+ if (!obj) {
+ BUG();
+ return;
+ }
+ dev = obj->my_dev;
+ yaffs_trace(YAFFS_TRACE_OS, "FreeObject %p inode %p",
+ obj, obj->my_inode);
+ if (obj->parent)
+ BUG();
+ if (!list_empty(&obj->siblings))
+ BUG();
+
+ if (obj->my_inode) {
+ /* We're still hooked up to a cached inode.
+ * Don't delete now, but mark for later deletion
+ */
+ obj->defered_free = 1;
+ return;
+ }
+
+ yaffs_unhash_obj(obj);
+
+ yaffs_free_raw_obj(dev, obj);
+ dev->n_obj--;
+ dev->checkpoint_blocks_required = 0; /* force recalculation */
+}
+
+void yaffs_handle_defered_free(struct yaffs_obj *obj)
+{
+ if (obj->defered_free)
+ yaffs_free_obj(obj);
+}
+
+static int yaffs_generic_obj_del(struct yaffs_obj *in)
+{
+ /* Iinvalidate the file's data in the cache, without flushing. */
+ yaffs_invalidate_whole_cache(in);
+
+ if (in->my_dev->param.is_yaffs2 && in->parent != in->my_dev->del_dir) {
+ /* Move to unlinked directory so we have a deletion record */
+ yaffs_change_obj_name(in, in->my_dev->del_dir, _Y("deleted"), 0,
+ 0);
+ }
+
+ yaffs_remove_obj_from_dir(in);
+ yaffs_chunk_del(in->my_dev, in->hdr_chunk, 1, __LINE__);
+ in->hdr_chunk = 0;
+
+ yaffs_free_obj(in);
+ return YAFFS_OK;
+
+}
+
+static void yaffs_soft_del_file(struct yaffs_obj *obj)
+{
+ if (!obj->deleted ||
+ obj->variant_type != YAFFS_OBJECT_TYPE_FILE ||
+ obj->soft_del)
+ return;
+
+ if (obj->n_data_chunks <= 0) {
+ /* Empty file with no duplicate object headers,
+ * just delete it immediately */
+ yaffs_free_tnode(obj->my_dev, obj->variant.file_variant.top);
+ obj->variant.file_variant.top = NULL;
+ yaffs_trace(YAFFS_TRACE_TRACING,
+ "yaffs: Deleting empty file %d",
+ obj->obj_id);
+ yaffs_generic_obj_del(obj);
+ } else {
+ yaffs_soft_del_worker(obj,
+ obj->variant.file_variant.top,
+ obj->variant.
+ file_variant.top_level, 0);
+ obj->soft_del = 1;
+ }
+}
+
+/* Pruning removes any part of the file structure tree that is beyond the
+ * bounds of the file (ie that does not point to chunks).
+ *
+ * A file should only get pruned when its size is reduced.
+ *
+ * Before pruning, the chunks must be pulled from the tree and the
+ * level 0 tnode entries must be zeroed out.
+ * Could also use this for file deletion, but that's probably better handled
+ * by a special case.
+ *
+ * This function is recursive. For levels > 0 the function is called again on
+ * any sub-tree. For level == 0 we just check if the sub-tree has data.
+ * If there is no data in a subtree then it is pruned.
+ */
+
+static struct yaffs_tnode *yaffs_prune_worker(struct yaffs_dev *dev,
+ struct yaffs_tnode *tn, u32 level,
+ int del0)
+{
+ int i;
+ int has_data;
+
+ if (!tn)
+ return tn;
+
+ has_data = 0;
+
+ if (level > 0) {
+ for (i = 0; i < YAFFS_NTNODES_INTERNAL; i++) {
+ if (tn->internal[i]) {
+ tn->internal[i] =
+ yaffs_prune_worker(dev,
+ tn->internal[i],
+ level - 1,
+ (i == 0) ? del0 : 1);
+ }
+
+ if (tn->internal[i])
+ has_data++;
+ }
+ } else {
+ int tnode_size_u32 = dev->tnode_size / sizeof(u32);
+ u32 *map = (u32 *) tn;
+
+ for (i = 0; !has_data && i < tnode_size_u32; i++) {
+ if (map[i])
+ has_data++;
+ }
+ }
+
+ if (has_data == 0 && del0) {
+ /* Free and return NULL */
+ yaffs_free_tnode(dev, tn);
+ tn = NULL;
+ }
+ return tn;
+}
+
+static int yaffs_prune_tree(struct yaffs_dev *dev,
+ struct yaffs_file_var *file_struct)
+{
+ int i;
+ int has_data;
+ int done = 0;
+ struct yaffs_tnode *tn;
+
+ if (file_struct->top_level < 1)
+ return YAFFS_OK;
+
+ file_struct->top =
+ yaffs_prune_worker(dev, file_struct->top, file_struct->top_level, 0);
+
+ /* Now we have a tree with all the non-zero branches NULL but
+ * the height is the same as it was.
+ * Let's see if we can trim internal tnodes to shorten the tree.
+ * We can do this if only the 0th element in the tnode is in use
+ * (ie all the non-zero are NULL)
+ */
+
+ while (file_struct->top_level && !done) {
+ tn = file_struct->top;
+
+ has_data = 0;
+ for (i = 1; i < YAFFS_NTNODES_INTERNAL; i++) {
+ if (tn->internal[i])
+ has_data++;
+ }
+
+ if (!has_data) {
+ file_struct->top = tn->internal[0];
+ file_struct->top_level--;
+ yaffs_free_tnode(dev, tn);
+ } else {
+ done = 1;
+ }
+ }
+
+ return YAFFS_OK;
+}
+
+/*-------------------- End of File Structure functions.-------------------*/
+
+/* alloc_empty_obj gets us a clean Object.*/
+static struct yaffs_obj *yaffs_alloc_empty_obj(struct yaffs_dev *dev)
+{
+ struct yaffs_obj *obj = yaffs_alloc_raw_obj(dev);
+
+ if (!obj)
+ return obj;
+
+ dev->n_obj++;
+
+ /* Now sweeten it up... */
+
+ memset(obj, 0, sizeof(struct yaffs_obj));
+ obj->being_created = 1;
+
+ obj->my_dev = dev;
+ obj->hdr_chunk = 0;
+ obj->variant_type = YAFFS_OBJECT_TYPE_UNKNOWN;
+ INIT_LIST_HEAD(&(obj->hard_links));
+ INIT_LIST_HEAD(&(obj->hash_link));
+ INIT_LIST_HEAD(&obj->siblings);
+
+ /* Now make the directory sane */
+ if (dev->root_dir) {
+ obj->parent = dev->root_dir;
+ list_add(&(obj->siblings),
+ &dev->root_dir->variant.dir_variant.children);
+ }
+
+ /* Add it to the lost and found directory.
+ * NB Can't put root or lost-n-found in lost-n-found so
+ * check if lost-n-found exists first
+ */
+ if (dev->lost_n_found)
+ yaffs_add_obj_to_dir(dev->lost_n_found, obj);
+
+ obj->being_created = 0;
+
+ dev->checkpoint_blocks_required = 0; /* force recalculation */
+
+ return obj;
+}
+
+static int yaffs_find_nice_bucket(struct yaffs_dev *dev)
+{
+ int i;
+ int l = 999;
+ int lowest = 999999;
+
+ /* Search for the shortest list or one that
+ * isn't too long.
+ */
+
+ for (i = 0; i < 10 && lowest > 4; i++) {
+ dev->bucket_finder++;
+ dev->bucket_finder %= YAFFS_NOBJECT_BUCKETS;
+ if (dev->obj_bucket[dev->bucket_finder].count < lowest) {
+ lowest = dev->obj_bucket[dev->bucket_finder].count;
+ l = dev->bucket_finder;
+ }
+ }
+
+ return l;
+}
+
+static int yaffs_new_obj_id(struct yaffs_dev *dev)
+{
+ int bucket = yaffs_find_nice_bucket(dev);
+ int found = 0;
+ struct list_head *i;
+ u32 n = (u32) bucket;
+
+ /*
+ * Now find an object value that has not already been taken
+ * by scanning the list, incrementing each time by number of buckets.
+ */
+ while (!found) {
+ found = 1;
+ n += YAFFS_NOBJECT_BUCKETS;
+ list_for_each(i, &dev->obj_bucket[bucket].list) {
+ /* Check if this value is already taken. */
+ if (i && list_entry(i, struct yaffs_obj,
+ hash_link)->obj_id == n)
+ found = 0;
+ }
+ }
+ return n;
+}
+
+static void yaffs_hash_obj(struct yaffs_obj *in)
+{
+ int bucket = yaffs_hash_fn(in->obj_id);
+ struct yaffs_dev *dev = in->my_dev;
+
+ list_add(&in->hash_link, &dev->obj_bucket[bucket].list);
+ dev->obj_bucket[bucket].count++;
+}
+
+struct yaffs_obj *yaffs_find_by_number(struct yaffs_dev *dev, u32 number)
+{
+ int bucket = yaffs_hash_fn(number);
+ struct list_head *i;
+ struct yaffs_obj *in;
+
+ list_for_each(i, &dev->obj_bucket[bucket].list) {
+ /* Look if it is in the list */
+ in = list_entry(i, struct yaffs_obj, hash_link);
+ if (in->obj_id == number) {
+ /* Don't show if it is defered free */
+ if (in->defered_free)
+ return NULL;
+ return in;
+ }
+ }
+
+ return NULL;
+}
+
+static struct yaffs_obj *yaffs_new_obj(struct yaffs_dev *dev, int number,
+ enum yaffs_obj_type type)
+{
+ struct yaffs_obj *the_obj = NULL;
+ struct yaffs_tnode *tn = NULL;
+
+ if (number < 0)
+ number = yaffs_new_obj_id(dev);
+
+ if (type == YAFFS_OBJECT_TYPE_FILE) {
+ tn = yaffs_get_tnode(dev);
+ if (!tn)
+ return NULL;
+ }
+
+ the_obj = yaffs_alloc_empty_obj(dev);
+ if (!the_obj) {
+ if (tn)
+ yaffs_free_tnode(dev, tn);
+ return NULL;
+ }
+
+ the_obj->fake = 0;
+ the_obj->rename_allowed = 1;
+ the_obj->unlink_allowed = 1;
+ the_obj->obj_id = number;
+ yaffs_hash_obj(the_obj);
+ the_obj->variant_type = type;
+ yaffs_load_current_time(the_obj, 1, 1);
+
+ switch (type) {
+ case YAFFS_OBJECT_TYPE_FILE:
+ the_obj->variant.file_variant.file_size = 0;
+ the_obj->variant.file_variant.stored_size = 0;
+ the_obj->variant.file_variant.shrink_size =
+ yaffs_max_file_size(dev);
+ the_obj->variant.file_variant.top_level = 0;
+ the_obj->variant.file_variant.top = tn;
+ break;
+ case YAFFS_OBJECT_TYPE_DIRECTORY:
+ INIT_LIST_HEAD(&the_obj->variant.dir_variant.children);
+ INIT_LIST_HEAD(&the_obj->variant.dir_variant.dirty);
+ break;
+ case YAFFS_OBJECT_TYPE_SYMLINK:
+ case YAFFS_OBJECT_TYPE_HARDLINK:
+ case YAFFS_OBJECT_TYPE_SPECIAL:
+ /* No action required */
+ break;
+ case YAFFS_OBJECT_TYPE_UNKNOWN:
+ /* todo this should not happen */
+ break;
+ }
+ return the_obj;
+}
+
+static struct yaffs_obj *yaffs_create_fake_dir(struct yaffs_dev *dev,
+ int number, u32 mode)
+{
+
+ struct yaffs_obj *obj =
+ yaffs_new_obj(dev, number, YAFFS_OBJECT_TYPE_DIRECTORY);
+
+ if (!obj)
+ return NULL;
+
+ obj->fake = 1; /* it is fake so it might not use NAND */
+ obj->rename_allowed = 0;
+ obj->unlink_allowed = 0;
+ obj->deleted = 0;
+ obj->unlinked = 0;
+ obj->yst_mode = mode;
+ obj->my_dev = dev;
+ obj->hdr_chunk = 0; /* Not a valid chunk. */
+ return obj;
+
+}
+
+
+static void yaffs_init_tnodes_and_objs(struct yaffs_dev *dev)
+{
+ int i;
+
+ dev->n_obj = 0;
+ dev->n_tnodes = 0;
+ yaffs_init_raw_tnodes_and_objs(dev);
+
+ for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) {
+ INIT_LIST_HEAD(&dev->obj_bucket[i].list);
+ dev->obj_bucket[i].count = 0;
+ }
+}
+
+struct yaffs_obj *yaffs_find_or_create_by_number(struct yaffs_dev *dev,
+ int number,
+ enum yaffs_obj_type type)
+{
+ struct yaffs_obj *the_obj = NULL;
+
+ if (number > 0)
+ the_obj = yaffs_find_by_number(dev, number);
+
+ if (!the_obj)
+ the_obj = yaffs_new_obj(dev, number, type);
+
+ return the_obj;
+
+}
+
+YCHAR *yaffs_clone_str(const YCHAR *str)
+{
+ YCHAR *new_str = NULL;
+ int len;
+
+ if (!str)
+ str = _Y("");
+
+ len = strnlen(str, YAFFS_MAX_ALIAS_LENGTH);
+ new_str = kmalloc((len + 1) * sizeof(YCHAR), GFP_NOFS);
+ if (new_str) {
+ strncpy(new_str, str, len);
+ new_str[len] = 0;
+ }
+ return new_str;
+
+}
+/*
+ *yaffs_update_parent() handles fixing a directories mtime and ctime when a new
+ * link (ie. name) is created or deleted in the directory.
+ *
+ * ie.
+ * create dir/a : update dir's mtime/ctime
+ * rm dir/a: update dir's mtime/ctime
+ * modify dir/a: don't update dir's mtimme/ctime
+ *
+ * This can be handled immediately or defered. Defering helps reduce the number
+ * of updates when many files in a directory are changed within a brief period.
+ *
+ * If the directory updating is defered then yaffs_update_dirty_dirs must be
+ * called periodically.
+ */
+
+static void yaffs_update_parent(struct yaffs_obj *obj)
+{
+ struct yaffs_dev *dev;
+
+ if (!obj)
+ return;
+ dev = obj->my_dev;
+ obj->dirty = 1;
+ yaffs_load_current_time(obj, 0, 1);
+ if (dev->param.defered_dir_update) {
+ struct list_head *link = &obj->variant.dir_variant.dirty;
+
+ if (list_empty(link)) {
+ list_add(link, &dev->dirty_dirs);
+ yaffs_trace(YAFFS_TRACE_BACKGROUND,
+ "Added object %d to dirty directories",
+ obj->obj_id);
+ }
+
+ } else {
+ yaffs_update_oh(obj, NULL, 0, 0, 0, NULL);
+ }
+}
+
+void yaffs_update_dirty_dirs(struct yaffs_dev *dev)
+{
+ struct list_head *link;
+ struct yaffs_obj *obj;
+ struct yaffs_dir_var *d_s;
+ union yaffs_obj_var *o_v;
+
+ yaffs_trace(YAFFS_TRACE_BACKGROUND, "Update dirty directories");
+
+ while (!list_empty(&dev->dirty_dirs)) {
+ link = dev->dirty_dirs.next;
+ list_del_init(link);
+
+ d_s = list_entry(link, struct yaffs_dir_var, dirty);
+ o_v = list_entry(d_s, union yaffs_obj_var, dir_variant);
+ obj = list_entry(o_v, struct yaffs_obj, variant);
+
+ yaffs_trace(YAFFS_TRACE_BACKGROUND, "Update directory %d",
+ obj->obj_id);
+
+ if (obj->dirty)
+ yaffs_update_oh(obj, NULL, 0, 0, 0, NULL);
+ }
+}
+
+/*
+ * Mknod (create) a new object.
+ * equiv_obj only has meaning for a hard link;
+ * alias_str only has meaning for a symlink.
+ * rdev only has meaning for devices (a subset of special objects)
+ */
+
+static struct yaffs_obj *yaffs_create_obj(enum yaffs_obj_type type,
+ struct yaffs_obj *parent,
+ const YCHAR *name,
+ u32 mode,
+ u32 uid,
+ u32 gid,
+ struct yaffs_obj *equiv_obj,
+ const YCHAR *alias_str, u32 rdev)
+{
+ struct yaffs_obj *in;
+ YCHAR *str = NULL;
+ struct yaffs_dev *dev = parent->my_dev;
+
+ /* Check if the entry exists.
+ * If it does then fail the call since we don't want a dup. */
+ if (yaffs_find_by_name(parent, name))
+ return NULL;
+
+ if (type == YAFFS_OBJECT_TYPE_SYMLINK) {
+ str = yaffs_clone_str(alias_str);
+ if (!str)
+ return NULL;
+ }
+
+ in = yaffs_new_obj(dev, -1, type);
+
+ if (!in) {
+ kfree(str);
+ return NULL;
+ }
+
+ in->hdr_chunk = 0;
+ in->valid = 1;
+ in->variant_type = type;
+
+ in->yst_mode = mode;
+
+ yaffs_attribs_init(in, gid, uid, rdev);
+
+ in->n_data_chunks = 0;
+
+ yaffs_set_obj_name(in, name);
+ in->dirty = 1;
+
+ yaffs_add_obj_to_dir(parent, in);
+
+ in->my_dev = parent->my_dev;
+
+ switch (type) {
+ case YAFFS_OBJECT_TYPE_SYMLINK:
+ in->variant.symlink_variant.alias = str;
+ break;
+ case YAFFS_OBJECT_TYPE_HARDLINK:
+ in->variant.hardlink_variant.equiv_obj = equiv_obj;
+ in->variant.hardlink_variant.equiv_id = equiv_obj->obj_id;
+ list_add(&in->hard_links, &equiv_obj->hard_links);
+ break;
+ case YAFFS_OBJECT_TYPE_FILE:
+ case YAFFS_OBJECT_TYPE_DIRECTORY:
+ case YAFFS_OBJECT_TYPE_SPECIAL:
+ case YAFFS_OBJECT_TYPE_UNKNOWN:
+ /* do nothing */
+ break;
+ }
+
+ if (yaffs_update_oh(in, name, 0, 0, 0, NULL) < 0) {
+ /* Could not create the object header, fail */
+ yaffs_del_obj(in);
+ in = NULL;
+ }
+
+ if (in)
+ yaffs_update_parent(parent);
+
+ return in;
+}
+
+struct yaffs_obj *yaffs_create_file(struct yaffs_obj *parent,
+ const YCHAR *name, u32 mode, u32 uid,
+ u32 gid)
+{
+ return yaffs_create_obj(YAFFS_OBJECT_TYPE_FILE, parent, name, mode,
+ uid, gid, NULL, NULL, 0);
+}
+
+struct yaffs_obj *yaffs_create_dir(struct yaffs_obj *parent, const YCHAR *name,
+ u32 mode, u32 uid, u32 gid)
+{
+ return yaffs_create_obj(YAFFS_OBJECT_TYPE_DIRECTORY, parent, name,
+ mode, uid, gid, NULL, NULL, 0);
+}
+
+struct yaffs_obj *yaffs_create_special(struct yaffs_obj *parent,
+ const YCHAR *name, u32 mode, u32 uid,
+ u32 gid, u32 rdev)
+{
+ return yaffs_create_obj(YAFFS_OBJECT_TYPE_SPECIAL, parent, name, mode,
+ uid, gid, NULL, NULL, rdev);
+}
+
+struct yaffs_obj *yaffs_create_symlink(struct yaffs_obj *parent,
+ const YCHAR *name, u32 mode, u32 uid,
+ u32 gid, const YCHAR *alias)
+{
+ return yaffs_create_obj(YAFFS_OBJECT_TYPE_SYMLINK, parent, name, mode,
+ uid, gid, NULL, alias, 0);
+}
+
+/* yaffs_link_obj returns the object id of the equivalent object.*/
+struct yaffs_obj *yaffs_link_obj(struct yaffs_obj *parent, const YCHAR * name,
+ struct yaffs_obj *equiv_obj)
+{
+ /* Get the real object in case we were fed a hard link obj */
+ equiv_obj = yaffs_get_equivalent_obj(equiv_obj);
+
+ if (yaffs_create_obj(YAFFS_OBJECT_TYPE_HARDLINK,
+ parent, name, 0, 0, 0,
+ equiv_obj, NULL, 0))
+ return equiv_obj;
+
+ return NULL;
+
+}
+
+
+
+/*---------------------- Block Management and Page Allocation -------------*/
+
+static void yaffs_deinit_blocks(struct yaffs_dev *dev)
+{
+ if (dev->block_info_alt && dev->block_info)
+ vfree(dev->block_info);
+ else
+ kfree(dev->block_info);
+
+ dev->block_info_alt = 0;
+
+ dev->block_info = NULL;
+
+ if (dev->chunk_bits_alt && dev->chunk_bits)
+ vfree(dev->chunk_bits);
+ else
+ kfree(dev->chunk_bits);
+ dev->chunk_bits_alt = 0;
+ dev->chunk_bits = NULL;
+}
+
+static int yaffs_init_blocks(struct yaffs_dev *dev)
+{
+ int n_blocks = dev->internal_end_block - dev->internal_start_block + 1;
+
+ dev->block_info = NULL;
+ dev->chunk_bits = NULL;
+ dev->alloc_block = -1; /* force it to get a new one */
+
+ /* If the first allocation strategy fails, thry the alternate one */
+ dev->block_info =
+ kmalloc(n_blocks * sizeof(struct yaffs_block_info), GFP_NOFS);
+ if (!dev->block_info) {
+ dev->block_info =
+ vmalloc(n_blocks * sizeof(struct yaffs_block_info));
+ dev->block_info_alt = 1;
+ } else {
+ dev->block_info_alt = 0;
+ }
+
+ if (!dev->block_info)
+ goto alloc_error;
+
+ /* Set up dynamic blockinfo stuff. Round up bytes. */
+ dev->chunk_bit_stride = (dev->param.chunks_per_block + 7) / 8;
+ dev->chunk_bits =
+ kmalloc(dev->chunk_bit_stride * n_blocks, GFP_NOFS);
+ if (!dev->chunk_bits) {
+ dev->chunk_bits =
+ vmalloc(dev->chunk_bit_stride * n_blocks);
+ dev->chunk_bits_alt = 1;
+ } else {
+ dev->chunk_bits_alt = 0;
+ }
+ if (!dev->chunk_bits)
+ goto alloc_error;
+
+
+ memset(dev->block_info, 0, n_blocks * sizeof(struct yaffs_block_info));
+ memset(dev->chunk_bits, 0, dev->chunk_bit_stride * n_blocks);
+ return YAFFS_OK;
+
+alloc_error:
+ yaffs_deinit_blocks(dev);
+ return YAFFS_FAIL;
+}
+
+
+void yaffs_block_became_dirty(struct yaffs_dev *dev, int block_no)
+{
+ struct yaffs_block_info *bi = yaffs_get_block_info(dev, block_no);
+ int erased_ok = 0;
+ u32 i;
+
+ /* If the block is still healthy erase it and mark as clean.
+ * If the block has had a data failure, then retire it.
+ */
+
+ yaffs_trace(YAFFS_TRACE_GC | YAFFS_TRACE_ERASE,
+ "yaffs_block_became_dirty block %d state %d %s",
+ block_no, bi->block_state,
+ (bi->needs_retiring) ? "needs retiring" : "");
+
+ yaffs2_clear_oldest_dirty_seq(dev, bi);
+
+ bi->block_state = YAFFS_BLOCK_STATE_DIRTY;
+
+ /* If this is the block being garbage collected then stop gc'ing */
+ if (block_no == (int)dev->gc_block)
+ dev->gc_block = 0;
+
+ /* If this block is currently the best candidate for gc
+ * then drop as a candidate */
+ if (block_no == (int)dev->gc_dirtiest) {
+ dev->gc_dirtiest = 0;
+ dev->gc_pages_in_use = 0;
+ }
+
+ if (!bi->needs_retiring) {
+ yaffs2_checkpt_invalidate(dev);
+ erased_ok = yaffs_erase_block(dev, block_no);
+ if (!erased_ok) {
+ dev->n_erase_failures++;
+ yaffs_trace(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,
+ "**>> Erasure failed %d", block_no);
+ }
+ }
+
+ /* Verify erasure if needed */
+ if (erased_ok &&
+ ((yaffs_trace_mask & YAFFS_TRACE_ERASE) ||
+ !yaffs_skip_verification(dev))) {
+ for (i = 0; i < dev->param.chunks_per_block; i++) {
+ if (!yaffs_check_chunk_erased(dev,
+ block_no * dev->param.chunks_per_block + i)) {
+ yaffs_trace(YAFFS_TRACE_ERROR,
+ ">>Block %d erasure supposedly OK, but chunk %d not erased",
+ block_no, i);
+ }
+ }
+ }
+
+ if (!erased_ok) {
+ /* We lost a block of free space */
+ dev->n_free_chunks -= dev->param.chunks_per_block;
+ yaffs_retire_block(dev, block_no);
+ yaffs_trace(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,
+ "**>> Block %d retired", block_no);
+ return;
+ }
+
+ /* Clean it up... */
+ bi->block_state = YAFFS_BLOCK_STATE_EMPTY;
+ bi->seq_number = 0;
+ dev->n_erased_blocks++;
+ bi->pages_in_use = 0;
+ bi->soft_del_pages = 0;
+ bi->has_shrink_hdr = 0;
+ bi->skip_erased_check = 1; /* Clean, so no need to check */
+ bi->gc_prioritise = 0;
+ bi->has_summary = 0;
+
+ yaffs_clear_chunk_bits(dev, block_no);
+
+ yaffs_trace(YAFFS_TRACE_ERASE, "Erased block %d", block_no);
+}
+
+static inline int yaffs_gc_process_chunk(struct yaffs_dev *dev,
+ struct yaffs_block_info *bi,
+ int old_chunk, u8 *buffer)
+{
+ int new_chunk;
+ int mark_flash = 1;
+ struct yaffs_ext_tags tags;
+ struct yaffs_obj *object;
+ int matching_chunk;
+ int ret_val = YAFFS_OK;
+
+ memset(&tags, 0, sizeof(tags));
+ yaffs_rd_chunk_tags_nand(dev, old_chunk,
+ buffer, &tags);
+ object = yaffs_find_by_number(dev, tags.obj_id);
+
+ yaffs_trace(YAFFS_TRACE_GC_DETAIL,
+ "Collecting chunk in block %d, %d %d %d ",
+ dev->gc_chunk, tags.obj_id,
+ tags.chunk_id, tags.n_bytes);
+
+ if (object && !yaffs_skip_verification(dev)) {
+ if (tags.chunk_id == 0)
+ matching_chunk =
+ object->hdr_chunk;
+ else if (object->soft_del)
+ /* Defeat the test */
+ matching_chunk = old_chunk;
+ else
+ matching_chunk =
+ yaffs_find_chunk_in_file
+ (object, tags.chunk_id,
+ NULL);
+
+ if (old_chunk != matching_chunk)
+ yaffs_trace(YAFFS_TRACE_ERROR,
+ "gc: page in gc mismatch: %d %d %d %d",
+ old_chunk,
+ matching_chunk,
+ tags.obj_id,
+ tags.chunk_id);
+ }
+
+ if (!object) {
+ yaffs_trace(YAFFS_TRACE_ERROR,
+ "page %d in gc has no object: %d %d %d ",
+ old_chunk,
+ tags.obj_id, tags.chunk_id,
+ tags.n_bytes);
+ }
+
+ if (object &&
+ object->deleted &&
+ object->soft_del && tags.chunk_id != 0) {
+ /* Data chunk in a soft deleted file,
+ * throw it away.
+ * It's a soft deleted data chunk,
+ * No need to copy this, just forget
+ * about it and fix up the object.
+ */
+
+ /* Free chunks already includes
+ * softdeleted chunks, how ever this
+ * chunk is going to soon be really
+ * deleted which will increment free
+ * chunks. We have to decrement free
+ * chunks so this works out properly.
+ */
+ dev->n_free_chunks--;
+ bi->soft_del_pages--;
+
+ object->n_data_chunks--;
+ if (object->n_data_chunks <= 0) {
+ /* remeber to clean up obj */
+ dev->gc_cleanup_list[dev->n_clean_ups] = tags.obj_id;
+ dev->n_clean_ups++;
+ }
+ mark_flash = 0;
+ } else if (object) {
+ /* It's either a data chunk in a live
+ * file or an ObjectHeader, so we're
+ * interested in it.
+ * NB Need to keep the ObjectHeaders of
+ * deleted files until the whole file
+ * has been deleted off
+ */
+ tags.serial_number++;
+ dev->n_gc_copies++;
+
+ if (tags.chunk_id == 0) {
+ /* It is an object Id,
+ * We need to nuke the shrinkheader flags since its
+ * work is done.
+ * Also need to clean up shadowing.
+ * NB We don't want to do all the work of translating
+ * object header endianism back and forth so we leave
+ * the oh endian in its stored order.
+ */
+
+ struct yaffs_obj_hdr *oh;
+ oh = (struct yaffs_obj_hdr *) buffer;
+
+ oh->is_shrink = 0;
+ tags.extra_is_shrink = 0;
+ oh->shadows_obj = 0;
+ oh->inband_shadowed_obj_id = 0;
+ tags.extra_shadows = 0;
+
+ /* Update file size */
+ if (object->variant_type == YAFFS_OBJECT_TYPE_FILE) {
+ yaffs_oh_size_load(dev, oh,
+ object->variant.file_variant.stored_size, 1);
+ tags.extra_file_size =
+ object->variant.file_variant.stored_size;
+ }
+
+ yaffs_verify_oh(object, oh, &tags, 1);
+ new_chunk =
+ yaffs_write_new_chunk(dev, (u8 *) oh, &tags, 1);
+ } else {
+ new_chunk =
+ yaffs_write_new_chunk(dev, buffer, &tags, 1);
+ }
+
+ if (new_chunk < 0) {
+ ret_val = YAFFS_FAIL;
+ } else {
+
+ /* Now fix up the Tnodes etc. */
+
+ if (tags.chunk_id == 0) {
+ /* It's a header */
+ object->hdr_chunk = new_chunk;
+ object->serial = tags.serial_number;
+ } else {
+ /* It's a data chunk */
+ yaffs_put_chunk_in_file(object, tags.chunk_id,
+ new_chunk, 0);
+ }
+ }
+ }
+ if (ret_val == YAFFS_OK)
+ yaffs_chunk_del(dev, old_chunk, mark_flash, __LINE__);
+ return ret_val;
+}
+
+static int yaffs_gc_block(struct yaffs_dev *dev, int block, int whole_block)
+{
+ int old_chunk;
+ int ret_val = YAFFS_OK;
+ u32 i;
+ int is_checkpt_block;
+ int max_copies;
+ int chunks_before = yaffs_get_erased_chunks(dev);
+ int chunks_after;
+ struct yaffs_block_info *bi = yaffs_get_block_info(dev, block);
+
+ is_checkpt_block = (bi->block_state == YAFFS_BLOCK_STATE_CHECKPOINT);
+
+ yaffs_trace(YAFFS_TRACE_TRACING,
+ "Collecting block %d, in use %d, shrink %d, whole_block %d",
+ block, bi->pages_in_use, bi->has_shrink_hdr,
+ whole_block);
+
+ /*yaffs_verify_free_chunks(dev); */
+
+ if (bi->block_state == YAFFS_BLOCK_STATE_FULL)
+ bi->block_state = YAFFS_BLOCK_STATE_COLLECTING;
+
+ bi->has_shrink_hdr = 0; /* clear the flag so that the block can erase */
+
+ dev->gc_disable = 1;
+
+ yaffs_summary_gc(dev, block);
+
+ if (is_checkpt_block || !yaffs_still_some_chunks(dev, block)) {
+ yaffs_trace(YAFFS_TRACE_TRACING,
+ "Collecting block %d that has no chunks in use",
+ block);
+ yaffs_block_became_dirty(dev, block);
+ } else {
+
+ u8 *buffer = yaffs_get_temp_buffer(dev);
+
+ yaffs_verify_blk(dev, bi, block);
+
+ max_copies = (whole_block) ? dev->param.chunks_per_block : 5;
+ old_chunk = block * dev->param.chunks_per_block + dev->gc_chunk;
+
+ for (/* init already done */ ;
+ ret_val == YAFFS_OK &&
+ dev->gc_chunk < dev->param.chunks_per_block &&
+ (bi->block_state == YAFFS_BLOCK_STATE_COLLECTING) &&
+ max_copies > 0;
+ dev->gc_chunk++, old_chunk++) {
+ if (yaffs_check_chunk_bit(dev, block, dev->gc_chunk)) {
+ /* Page is in use and might need to be copied */
+ max_copies--;
+ ret_val = yaffs_gc_process_chunk(dev, bi,
+ old_chunk, buffer);
+ }
+ }
+ yaffs_release_temp_buffer(dev, buffer);
+ }
+
+ yaffs_verify_collected_blk(dev, bi, block);
+
+ if (bi->block_state == YAFFS_BLOCK_STATE_COLLECTING) {
+ /*
+ * The gc did not complete. Set block state back to FULL
+ * because checkpointing does not restore gc.
+ */
+ bi->block_state = YAFFS_BLOCK_STATE_FULL;
+ } else {
+ /* The gc completed. */
+ /* Do any required cleanups */
+ for (i = 0; i < dev->n_clean_ups; i++) {
+ /* Time to delete the file too */
+ struct yaffs_obj *object =
+ yaffs_find_by_number(dev, dev->gc_cleanup_list[i]);
+ if (object) {
+ yaffs_free_tnode(dev,
+ object->variant.file_variant.top);
+ object->variant.file_variant.top = NULL;
+ yaffs_trace(YAFFS_TRACE_GC,
+ "yaffs: About to finally delete object %d",
+ object->obj_id);
+ yaffs_generic_obj_del(object);
+ object->my_dev->n_deleted_files--;
+ }
+
+ }
+ chunks_after = yaffs_get_erased_chunks(dev);
+ if (chunks_before >= chunks_after)
+ yaffs_trace(YAFFS_TRACE_GC,
+ "gc did not increase free chunks before %d after %d",
+ chunks_before, chunks_after);
+ dev->gc_block = 0;
+ dev->gc_chunk = 0;
+ dev->n_clean_ups = 0;
+ }
+
+ dev->gc_disable = 0;
+
+ return ret_val;
+}
+
+/*
+ * find_gc_block() selects the dirtiest block (or close enough)
+ * for garbage collection.
+ */
+
+static unsigned yaffs_find_gc_block(struct yaffs_dev *dev,
+ int aggressive, int background)
+{
+ u32 i;
+ u32 iterations;
+ u32 selected = 0;
+ int prioritised = 0;
+ int prioritised_exist = 0;
+ struct yaffs_block_info *bi;
+ u32 threshold;
+
+ /* First let's see if we need to grab a prioritised block */
+ if (dev->has_pending_prioritised_gc && !aggressive) {
+ dev->gc_dirtiest = 0;
+ bi = dev->block_info;
+ for (i = dev->internal_start_block;
+ i <= dev->internal_end_block && !selected; i++) {
+
+ if (bi->gc_prioritise) {
+ prioritised_exist = 1;
+ if (bi->block_state == YAFFS_BLOCK_STATE_FULL &&
+ yaffs_block_ok_for_gc(dev, bi)) {
+ selected = i;
+ prioritised = 1;
+ }
+ }
+ bi++;
+ }
+
+ /*
+ * If there is a prioritised block and none was selected then
+ * this happened because there is at least one old dirty block
+ * gumming up the works. Let's gc the oldest dirty block.
+ */
+
+ if (prioritised_exist &&
+ !selected && dev->oldest_dirty_block > 0)
+ selected = dev->oldest_dirty_block;
+
+ if (!prioritised_exist) /* None found, so we can clear this */
+ dev->has_pending_prioritised_gc = 0;
+ }
+
+ /* If we're doing aggressive GC then we are happy to take a less-dirty
+ * block, and search harder.
+ * else (leasurely gc), then we only bother to do this if the
+ * block has only a few pages in use.
+ */
+
+ if (!selected) {
+ u32 pages_used;
+ int n_blocks =
+ dev->internal_end_block - dev->internal_start_block + 1;
+ if (aggressive) {
+ threshold = dev->param.chunks_per_block;
+ iterations = n_blocks;
+ } else {
+ u32 max_threshold;
+
+ if (background)
+ max_threshold = dev->param.chunks_per_block / 2;
+ else
+ max_threshold = dev->param.chunks_per_block / 8;
+
+ if (max_threshold < YAFFS_GC_PASSIVE_THRESHOLD)
+ max_threshold = YAFFS_GC_PASSIVE_THRESHOLD;
+
+ threshold = background ? (dev->gc_not_done + 2) * 2 : 0;
+ if (threshold < YAFFS_GC_PASSIVE_THRESHOLD)
+ threshold = YAFFS_GC_PASSIVE_THRESHOLD;
+ if (threshold > max_threshold)
+ threshold = max_threshold;
+
+ iterations = n_blocks / 16 + 1;
+ if (iterations > 100)
+ iterations = 100;
+ }
+
+ for (i = 0;
+ i < iterations &&
+ (dev->gc_dirtiest < 1 ||
+ dev->gc_pages_in_use > YAFFS_GC_GOOD_ENOUGH);
+ i++) {
+ dev->gc_block_finder++;
+ if (dev->gc_block_finder < dev->internal_start_block ||
+ dev->gc_block_finder > dev->internal_end_block)
+ dev->gc_block_finder =
+ dev->internal_start_block;
+
+ bi = yaffs_get_block_info(dev, dev->gc_block_finder);
+
+ pages_used = bi->pages_in_use - bi->soft_del_pages;
+
+ if (bi->block_state == YAFFS_BLOCK_STATE_FULL &&
+ pages_used < dev->param.chunks_per_block &&
+ (dev->gc_dirtiest < 1 ||
+ pages_used < dev->gc_pages_in_use) &&
+ yaffs_block_ok_for_gc(dev, bi)) {
+ dev->gc_dirtiest = dev->gc_block_finder;
+ dev->gc_pages_in_use = pages_used;
+ }
+ }
+
+ if (dev->gc_dirtiest > 0 && dev->gc_pages_in_use <= threshold)
+ selected = dev->gc_dirtiest;
+ }
+
+ /*
+ * If nothing has been selected for a while, try the oldest dirty
+ * because that's gumming up the works.
+ */
+
+ if (!selected && dev->param.is_yaffs2 &&
+ dev->gc_not_done >= (background ? 10 : 20)) {
+ yaffs2_find_oldest_dirty_seq(dev);
+ if (dev->oldest_dirty_block > 0) {
+ selected = dev->oldest_dirty_block;
+ dev->gc_dirtiest = selected;
+ dev->oldest_dirty_gc_count++;
+ bi = yaffs_get_block_info(dev, selected);
+ dev->gc_pages_in_use =
+ bi->pages_in_use - bi->soft_del_pages;
+ } else {
+ dev->gc_not_done = 0;
+ }
+ }
+
+ if (selected) {
+ yaffs_trace(YAFFS_TRACE_GC,
+ "GC Selected block %d with %d free, prioritised:%d",
+ selected,
+ dev->param.chunks_per_block - dev->gc_pages_in_use,
+ prioritised);
+
+ dev->n_gc_blocks++;
+ if (background)
+ dev->bg_gcs++;
+
+ dev->gc_dirtiest = 0;
+ dev->gc_pages_in_use = 0;
+ dev->gc_not_done = 0;
+ if (dev->refresh_skip > 0)
+ dev->refresh_skip--;
+ } else {
+ dev->gc_not_done++;
+ yaffs_trace(YAFFS_TRACE_GC,
+ "GC none: finder %d skip %d threshold %d dirtiest %d using %d oldest %d%s",
+ dev->gc_block_finder, dev->gc_not_done, threshold,
+ dev->gc_dirtiest, dev->gc_pages_in_use,
+ dev->oldest_dirty_block, background ? " bg" : "");
+ }
+
+ return selected;
+}
+
+/* New garbage collector
+ * If we're very low on erased blocks then we do aggressive garbage collection
+ * otherwise we do "leasurely" garbage collection.
+ * Aggressive gc looks further (whole array) and will accept less dirty blocks.
+ * Passive gc only inspects smaller areas and only accepts more dirty blocks.
+ *
+ * The idea is to help clear out space in a more spread-out manner.
+ * Dunno if it really does anything useful.
+ */
+static int yaffs_check_gc(struct yaffs_dev *dev, int background)
+{
+ int aggressive = 0;
+ int gc_ok = YAFFS_OK;
+ int max_tries = 0;
+ int min_erased;
+ int erased_chunks;
+ int checkpt_block_adjust;
+
+ if (dev->param.gc_control_fn &&
+ (dev->param.gc_control_fn(dev) & 1) == 0)
+ return YAFFS_OK;
+
+ if (dev->gc_disable)
+ /* Bail out so we don't get recursive gc */
+ return YAFFS_OK;
+
+ /* This loop should pass the first time.
+ * Only loops here if the collection does not increase space.
+ */
+
+ do {
+ max_tries++;
+
+ checkpt_block_adjust = yaffs_calc_checkpt_blocks_required(dev);
+
+ min_erased =
+ dev->param.n_reserved_blocks + checkpt_block_adjust + 1;
+ erased_chunks =
+ dev->n_erased_blocks * dev->param.chunks_per_block;
+
+ /* If we need a block soon then do aggressive gc. */
+ if (dev->n_erased_blocks < min_erased)
+ aggressive = 1;
+ else {
+ if (!background
+ && erased_chunks > (dev->n_free_chunks / 4))
+ break;
+
+ if (dev->gc_skip > 20)
+ dev->gc_skip = 20;
+ if (erased_chunks < dev->n_free_chunks / 2 ||
+ dev->gc_skip < 1 || background)
+ aggressive = 0;
+ else {
+ dev->gc_skip--;
+ break;
+ }
+ }
+
+ dev->gc_skip = 5;
+
+ /* If we don't already have a block being gc'd then see if we
+ * should start another */
+
+ if (dev->gc_block < 1 && !aggressive) {
+ dev->gc_block = yaffs2_find_refresh_block(dev);
+ dev->gc_chunk = 0;
+ dev->n_clean_ups = 0;
+ }
+ if (dev->gc_block < 1) {
+ dev->gc_block =
+ yaffs_find_gc_block(dev, aggressive, background);
+ dev->gc_chunk = 0;
+ dev->n_clean_ups = 0;
+ }
+
+ if (dev->gc_block > 0) {
+ dev->all_gcs++;
+ if (!aggressive)
+ dev->passive_gc_count++;
+
+ yaffs_trace(YAFFS_TRACE_GC,
+ "yaffs: GC n_erased_blocks %d aggressive %d",
+ dev->n_erased_blocks, aggressive);
+
+ gc_ok = yaffs_gc_block(dev, dev->gc_block, aggressive);
+ }
+
+ if (dev->n_erased_blocks < (int)dev->param.n_reserved_blocks &&
+ dev->gc_block > 0) {
+ yaffs_trace(YAFFS_TRACE_GC,
+ "yaffs: GC !!!no reclaim!!! n_erased_blocks %d after try %d block %d",
+ dev->n_erased_blocks, max_tries,
+ dev->gc_block);
+ }
+ } while ((dev->n_erased_blocks < (int)dev->param.n_reserved_blocks) &&
+ (dev->gc_block > 0) && (max_tries < 2));
+
+ return aggressive ? gc_ok : YAFFS_OK;
+}
+
+/*
+ * yaffs_bg_gc()
+ * Garbage collects. Intended to be called from a background thread.
+ * Returns non-zero if at least half the free chunks are erased.
+ */
+int yaffs_bg_gc(struct yaffs_dev *dev, unsigned urgency)
+{
+ int erased_chunks = dev->n_erased_blocks * dev->param.chunks_per_block;
+
+ yaffs_trace(YAFFS_TRACE_BACKGROUND, "Background gc %u", urgency);
+
+ yaffs_check_gc(dev, 1);
+ return erased_chunks > dev->n_free_chunks / 2;
+}
+
+/*-------------------- Data file manipulation -----------------*/
+
+static int yaffs_rd_data_obj(struct yaffs_obj *in, int inode_chunk, u8 * buffer)
+{
+ int nand_chunk = yaffs_find_chunk_in_file(in, inode_chunk, NULL);
+
+ if (nand_chunk >= 0)
+ return yaffs_rd_chunk_tags_nand(in->my_dev, nand_chunk,
+ buffer, NULL);
+ else {
+ yaffs_trace(YAFFS_TRACE_NANDACCESS,
+ "Chunk %d not found zero instead",
+ nand_chunk);
+ /* get sane (zero) data if you read a hole */
+ memset(buffer, 0, in->my_dev->data_bytes_per_chunk);
+ return 0;
+ }
+
+}
+
+void yaffs_chunk_del(struct yaffs_dev *dev, int chunk_id, int mark_flash,
+ int lyn)
+{
+ int block;
+ int page;
+ struct yaffs_ext_tags tags;
+ struct yaffs_block_info *bi;
+
+ if (chunk_id <= 0)
+ return;
+
+ dev->n_deletions++;
+ block = chunk_id / dev->param.chunks_per_block;
+ page = chunk_id % dev->param.chunks_per_block;
+
+ if (!yaffs_check_chunk_bit(dev, block, page))
+ yaffs_trace(YAFFS_TRACE_VERIFY,
+ "Deleting invalid chunk %d", chunk_id);
+
+ bi = yaffs_get_block_info(dev, block);
+
+ yaffs2_update_oldest_dirty_seq(dev, block, bi);
+
+ yaffs_trace(YAFFS_TRACE_DELETION,
+ "line %d delete of chunk %d",
+ lyn, chunk_id);
+
+ if (!dev->param.is_yaffs2 && mark_flash &&
+ bi->block_state != YAFFS_BLOCK_STATE_COLLECTING) {
+
+ memset(&tags, 0, sizeof(tags));
+ tags.is_deleted = 1;
+ yaffs_wr_chunk_tags_nand(dev, chunk_id, NULL, &tags);
+ yaffs_handle_chunk_update(dev, chunk_id, &tags);
+ } else {
+ dev->n_unmarked_deletions++;
+ }
+
+ /* Pull out of the management area.
+ * If the whole block became dirty, this will kick off an erasure.
+ */
+ if (bi->block_state == YAFFS_BLOCK_STATE_ALLOCATING ||
+ bi->block_state == YAFFS_BLOCK_STATE_FULL ||
+ bi->block_state == YAFFS_BLOCK_STATE_NEEDS_SCAN ||
+ bi->block_state == YAFFS_BLOCK_STATE_COLLECTING) {
+ dev->n_free_chunks++;
+ yaffs_clear_chunk_bit(dev, block, page);
+ bi->pages_in_use--;
+
+ if (bi->pages_in_use == 0 &&
+ !bi->has_shrink_hdr &&
+ bi->block_state != YAFFS_BLOCK_STATE_ALLOCATING &&
+ bi->block_state != YAFFS_BLOCK_STATE_NEEDS_SCAN) {
+ yaffs_block_became_dirty(dev, block);
+ }
+ }
+}
+
+static int yaffs_wr_data_obj(struct yaffs_obj *in, int inode_chunk,
+ const u8 *buffer, int n_bytes, int use_reserve)
+{
+ /* Find old chunk Need to do this to get serial number
+ * Write new one and patch into tree.
+ * Invalidate old tags.
+ */
+
+ int prev_chunk_id;
+ struct yaffs_ext_tags prev_tags;
+ int new_chunk_id;
+ struct yaffs_ext_tags new_tags;
+ struct yaffs_dev *dev = in->my_dev;
+ loff_t endpos;
+
+ yaffs_check_gc(dev, 0);
+
+ /* Get the previous chunk at this location in the file if it exists.
+ * If it does not exist then put a zero into the tree. This creates
+ * the tnode now, rather than later when it is harder to clean up.
+ */
+ prev_chunk_id = yaffs_find_chunk_in_file(in, inode_chunk, &prev_tags);
+ if (prev_chunk_id < 1 &&
+ !yaffs_put_chunk_in_file(in, inode_chunk, 0, 0))
+ return 0;
+
+ /* Set up new tags */
+ memset(&new_tags, 0, sizeof(new_tags));
+
+ new_tags.chunk_id = inode_chunk;
+ new_tags.obj_id = in->obj_id;
+ new_tags.serial_number =
+ (prev_chunk_id > 0) ? prev_tags.serial_number + 1 : 1;
+ new_tags.n_bytes = n_bytes;
+
+ if (n_bytes < 1 || n_bytes > (int)dev->data_bytes_per_chunk) {
+ yaffs_trace(YAFFS_TRACE_ERROR,
+ "Writing %d bytes to chunk!!!!!!!!!",
+ n_bytes);
+ BUG();
+ }
+
+ /*
+ * If this is a data chunk and the write goes past the end of the stored
+ * size then update the stored_size.
+ */
+ if (inode_chunk > 0) {
+ endpos = (inode_chunk - 1) * dev->data_bytes_per_chunk +
+ n_bytes;
+ if (in->variant.file_variant.stored_size < endpos)
+ in->variant.file_variant.stored_size = endpos;
+ }
+
+ new_chunk_id =
+ yaffs_write_new_chunk(dev, buffer, &new_tags, use_reserve);
+
+ if (new_chunk_id > 0) {
+ yaffs_put_chunk_in_file(in, inode_chunk, new_chunk_id, 0);
+
+ if (prev_chunk_id > 0)
+ yaffs_chunk_del(dev, prev_chunk_id, 1, __LINE__);
+
+ yaffs_verify_file_sane(in);
+ }
+ return new_chunk_id;
+}
+
+
+
+static int yaffs_do_xattrib_mod(struct yaffs_obj *obj, int set,
+ const YCHAR *name, const void *value, int size,
+ int flags)
+{
+ struct yaffs_xattr_mod xmod;
+ int result;
+
+ xmod.set = set;
+ xmod.name = name;
+ xmod.data = value;
+ xmod.size = size;
+ xmod.flags = flags;
+ xmod.result = -ENOSPC;
+
+ result = yaffs_update_oh(obj, NULL, 0, 0, 0, &xmod);
+
+ if (result > 0)
+ return xmod.result;
+ else
+ return -ENOSPC;
+}
+
+static int yaffs_apply_xattrib_mod(struct yaffs_obj *obj, char *buffer,
+ struct yaffs_xattr_mod *xmod)
+{
+ int retval = 0;
+ int x_offs = sizeof(struct yaffs_obj_hdr);
+ struct yaffs_dev *dev = obj->my_dev;
+ int x_size = dev->data_bytes_per_chunk - sizeof(struct yaffs_obj_hdr);
+ char *x_buffer = buffer + x_offs;
+
+ if (xmod->set)
+ retval =
+ nval_set(dev, x_buffer, x_size, xmod->name, xmod->data,
+ xmod->size, xmod->flags);
+ else
+ retval = nval_del(dev, x_buffer, x_size, xmod->name);
+
+ obj->has_xattr = nval_hasvalues(dev, x_buffer, x_size);
+ obj->xattr_known = 1;
+ xmod->result = retval;
+
+ return retval;
+}
+
+static int yaffs_do_xattrib_fetch(struct yaffs_obj *obj, const YCHAR *name,
+ void *value, int size)
+{
+ char *buffer = NULL;
+ int result;
+ struct yaffs_ext_tags tags;
+ struct yaffs_dev *dev = obj->my_dev;
+ int x_offs = sizeof(struct yaffs_obj_hdr);
+ int x_size = dev->data_bytes_per_chunk - sizeof(struct yaffs_obj_hdr);
+ char *x_buffer;
+ int retval = 0;
+
+ if (obj->hdr_chunk < 1)
+ return -ENODATA;
+
+ /* If we know that the object has no xattribs then don't do all the
+ * reading and parsing.
+ */
+ if (obj->xattr_known && !obj->has_xattr) {
+ if (name)
+ return -ENODATA;
+ else
+ return 0;
+ }
+
+ buffer = (char *)yaffs_get_temp_buffer(dev);
+ if (!buffer)
+ return -ENOMEM;
+
+ result =
+ yaffs_rd_chunk_tags_nand(dev, obj->hdr_chunk, (u8 *) buffer, &tags);
+
+ if (result != YAFFS_OK)
+ retval = -ENOENT;
+ else {
+ x_buffer = buffer + x_offs;
+
+ if (!obj->xattr_known) {
+ obj->has_xattr = nval_hasvalues(dev, x_buffer, x_size);
+ obj->xattr_known = 1;
+ }
+
+ if (name)
+ retval = nval_get(dev, x_buffer, x_size,
+ name, value, size);
+ else
+ retval = nval_list(dev, x_buffer, x_size, value, size);
+ }
+ yaffs_release_temp_buffer(dev, (u8 *) buffer);
+ return retval;
+}
+
+int yaffs_set_xattrib(struct yaffs_obj *obj, const YCHAR * name,
+ const void *value, int size, int flags)
+{
+ return yaffs_do_xattrib_mod(obj, 1, name, value, size, flags);
+}
+
+int yaffs_remove_xattrib(struct yaffs_obj *obj, const YCHAR * name)
+{
+ return yaffs_do_xattrib_mod(obj, 0, name, NULL, 0, 0);
+}
+
+int yaffs_get_xattrib(struct yaffs_obj *obj, const YCHAR * name, void *value,
+ int size)
+{
+ return yaffs_do_xattrib_fetch(obj, name, value, size);
+}
+
+int yaffs_list_xattrib(struct yaffs_obj *obj, char *buffer, int size)
+{
+ return yaffs_do_xattrib_fetch(obj, NULL, buffer, size);
+}
+
+static void yaffs_check_obj_details_loaded(struct yaffs_obj *in)
+{
+ u8 *buf;
+ struct yaffs_obj_hdr *oh;
+ struct yaffs_dev *dev;
+ struct yaffs_ext_tags tags;
+ int result;
+
+ if (!in || !in->lazy_loaded || in->hdr_chunk < 1)
+ return;
+
+ dev = in->my_dev;
+ buf = yaffs_get_temp_buffer(dev);
+
+ result = yaffs_rd_chunk_tags_nand(dev, in->hdr_chunk, buf, &tags);
+
+ if (result == YAFFS_FAIL)
+ return;
+
+ oh = (struct yaffs_obj_hdr *)buf;
+
+ yaffs_do_endian_oh(dev, oh);
+
+ in->lazy_loaded = 0;
+ in->yst_mode = oh->yst_mode;
+ yaffs_load_attribs(in, oh);
+ yaffs_set_obj_name_from_oh(in, oh);
+
+ if (in->variant_type == YAFFS_OBJECT_TYPE_SYMLINK)
+ in->variant.symlink_variant.alias =
+ yaffs_clone_str(oh->alias);
+ yaffs_release_temp_buffer(dev, buf);
+}
+
+/* UpdateObjectHeader updates the header on NAND for an object.
+ * If name is not NULL, then that new name is used.
+ *
+ * We're always creating the obj header from scratch (except reading
+ * the old name) so first set up in cpu endianness then run it through
+ * endian fixing at the end.
+ *
+ * However, a twist: If there are xattribs we leave them as they were.
+ *
+ * Careful! The buffer holds the whole chunk. Part of the chunk holds the
+ * object header and the rest holds the xattribs, therefore we use a buffer
+ * pointer and an oh pointer to point to the same memory.
+ */
+
+int yaffs_update_oh(struct yaffs_obj *in, const YCHAR *name, int force,
+ int is_shrink, int shadows, struct yaffs_xattr_mod *xmod)
+{
+
+ struct yaffs_block_info *bi;
+ struct yaffs_dev *dev = in->my_dev;
+ int prev_chunk_id;
+ int ret_val = 0;
+ int result = 0;
+ int new_chunk_id;
+ struct yaffs_ext_tags new_tags;
+ struct yaffs_ext_tags old_tags;
+ const YCHAR *alias = NULL;
+ u8 *buffer = NULL;
+ YCHAR old_name[YAFFS_MAX_NAME_LENGTH + 1];
+ struct yaffs_obj_hdr *oh = NULL;
+ loff_t file_size = 0;
+
+ strcpy(old_name, _Y("silly old name"));
+
+ if (in->fake && in != dev->root_dir && !force && !xmod)
+ return ret_val;
+
+ yaffs_check_gc(dev, 0);
+ yaffs_check_obj_details_loaded(in);
+
+ buffer = yaffs_get_temp_buffer(in->my_dev);
+ oh = (struct yaffs_obj_hdr *)buffer;
+
+ prev_chunk_id = in->hdr_chunk;
+
+ if (prev_chunk_id > 0) {
+ /* Access the old obj header just to read the name. */
+ result = yaffs_rd_chunk_tags_nand(dev, prev_chunk_id,
+ buffer, &old_tags);
+ if (result == YAFFS_OK) {
+ yaffs_verify_oh(in, oh, &old_tags, 0);
+ memcpy(old_name, oh->name, sizeof(oh->name));
+
+ /*
+ * NB We only wipe the object header area because the rest of
+ * the buffer might contain xattribs.
+ */
+ memset(oh, 0xff, sizeof(*oh));
+ }
+ } else {
+ memset(buffer, 0xff, dev->data_bytes_per_chunk);
+ }
+
+ oh->type = in->variant_type;
+ oh->yst_mode = in->yst_mode;
+ oh->shadows_obj = oh->inband_shadowed_obj_id = shadows;
+
+ yaffs_load_attribs_oh(oh, in);
+
+ if (in->parent)
+ oh->parent_obj_id = in->parent->obj_id;
+ else
+ oh->parent_obj_id = 0;
+
+ if (name && *name) {
+ memset(oh->name, 0, sizeof(oh->name));
+ yaffs_load_oh_from_name(dev, oh->name, name);
+ } else if (prev_chunk_id > 0) {
+ memcpy(oh->name, old_name, sizeof(oh->name));
+ } else {
+ memset(oh->name, 0, sizeof(oh->name));
+ }
+
+ oh->is_shrink = is_shrink;
+
+ switch (in->variant_type) {
+ case YAFFS_OBJECT_TYPE_UNKNOWN:
+ /* Should not happen */
+ break;
+ case YAFFS_OBJECT_TYPE_FILE:
+ if (oh->parent_obj_id != YAFFS_OBJECTID_DELETED &&
+ oh->parent_obj_id != YAFFS_OBJECTID_UNLINKED)
+ file_size = in->variant.file_variant.stored_size;
+ yaffs_oh_size_load(dev, oh, file_size, 0);
+ break;
+ case YAFFS_OBJECT_TYPE_HARDLINK:
+ oh->equiv_id = in->variant.hardlink_variant.equiv_id;
+ break;
+ case YAFFS_OBJECT_TYPE_SPECIAL:
+ /* Do nothing */
+ break;
+ case YAFFS_OBJECT_TYPE_DIRECTORY:
+ /* Do nothing */
+ break;
+ case YAFFS_OBJECT_TYPE_SYMLINK:
+ alias = in->variant.symlink_variant.alias;
+ if (!alias)
+ alias = _Y("no alias");
+ strncpy(oh->alias, alias, YAFFS_MAX_ALIAS_LENGTH);
+ oh->alias[YAFFS_MAX_ALIAS_LENGTH] = 0;
+ break;
+ }
+
+ /* process any xattrib modifications */
+ if (xmod)
+ yaffs_apply_xattrib_mod(in, (char *)buffer, xmod);
+
+ /* Tags */
+ memset(&new_tags, 0, sizeof(new_tags));
+ in->serial++;
+ new_tags.chunk_id = 0;
+ new_tags.obj_id = in->obj_id;
+ new_tags.serial_number = in->serial;
+
+ /* Add extra info for file header */
+ new_tags.extra_available = 1;
+ new_tags.extra_parent_id = oh->parent_obj_id;
+ new_tags.extra_file_size = file_size;
+ new_tags.extra_is_shrink = oh->is_shrink;
+ new_tags.extra_equiv_id = oh->equiv_id;
+ new_tags.extra_shadows = (oh->shadows_obj > 0) ? 1 : 0;
+ new_tags.extra_obj_type = in->variant_type;
+
+ /* Now endian swizzle the oh if needed. */
+ yaffs_do_endian_oh(dev, oh);
+
+ yaffs_verify_oh(in, oh, &new_tags, 1);
+
+ /* Create new chunk in NAND */
+ new_chunk_id =
+ yaffs_write_new_chunk(dev, buffer, &new_tags,
+ (prev_chunk_id > 0) ? 1 : 0);
+
+ if (buffer)
+ yaffs_release_temp_buffer(dev, buffer);
+
+ if (new_chunk_id < 0)
+ return new_chunk_id;
+
+ in->hdr_chunk = new_chunk_id;
+
+ if (prev_chunk_id > 0)
+ yaffs_chunk_del(dev, prev_chunk_id, 1, __LINE__);
+
+ if (!yaffs_obj_cache_dirty(in))
+ in->dirty = 0;
+
+ /* If this was a shrink, then mark the block
+ * that the chunk lives on */
+ if (is_shrink) {
+ bi = yaffs_get_block_info(in->my_dev,
+ new_chunk_id /
+ in->my_dev->param.chunks_per_block);
+ bi->has_shrink_hdr = 1;
+ }
+
+
+ return new_chunk_id;
+}
+
+/*--------------------- File read/write ------------------------
+ * Read and write have very similar structures.
+ * In general the read/write has three parts to it
+ * An incomplete chunk to start with (if the read/write is not chunk-aligned)
+ * Some complete chunks
+ * An incomplete chunk to end off with
+ *
+ * Curve-balls: the first chunk might also be the last chunk.
+ */
+
+int yaffs_file_rd(struct yaffs_obj *in, u8 * buffer, loff_t offset, int n_bytes)
+{
+ int chunk;
+ u32 start;
+ int n_copy;
+ int n = n_bytes;
+ int n_done = 0;
+ struct yaffs_cache *cache;
+ struct yaffs_dev *dev;
+
+ dev = in->my_dev;
+
+ while (n > 0) {
+ yaffs_addr_to_chunk(dev, offset, &chunk, &start);
+ chunk++;
+
+ /* OK now check for the curveball where the start and end are in
+ * the same chunk.
+ */
+ if ((start + n) < dev->data_bytes_per_chunk)
+ n_copy = n;
+ else
+ n_copy = dev->data_bytes_per_chunk - start;
+
+ cache = yaffs_find_chunk_cache(in, chunk);
+
+ /* If the chunk is already in the cache or it is less than
+ * a whole chunk or we're using inband tags then use the cache
+ * (if there is caching) else bypass the cache.
+ */
+ if (cache || n_copy != (int)dev->data_bytes_per_chunk ||
+ dev->param.inband_tags) {
+ if (dev->param.n_caches > 0) {
+
+ /* If we can't find the data in the cache,
+ * then load it up. */
+
+ if (!cache) {
+ cache =
+ yaffs_grab_chunk_cache(in->my_dev);
+ cache->object = in;
+ cache->chunk_id = chunk;
+ cache->dirty = 0;
+ cache->locked = 0;
+ yaffs_rd_data_obj(in, chunk,
+ cache->data);
+ cache->n_bytes = 0;
+ }
+
+ yaffs_use_cache(dev, cache, 0);
+
+ cache->locked = 1;
+
+ memcpy(buffer, &cache->data[start], n_copy);
+
+ cache->locked = 0;
+ } else {
+ /* Read into the local buffer then copy.. */
+
+ u8 *local_buffer =
+ yaffs_get_temp_buffer(dev);
+ yaffs_rd_data_obj(in, chunk, local_buffer);
+
+ memcpy(buffer, &local_buffer[start], n_copy);
+
+ yaffs_release_temp_buffer(dev, local_buffer);
+ }
+ } else {
+ /* A full chunk. Read directly into the buffer. */
+ yaffs_rd_data_obj(in, chunk, buffer);
+ }
+ n -= n_copy;
+ offset += n_copy;
+ buffer += n_copy;
+ n_done += n_copy;
+ }
+ return n_done;
+}
+
+int yaffs_do_file_wr(struct yaffs_obj *in, const u8 *buffer, loff_t offset,
+ int n_bytes, int write_through)
+{
+
+ int chunk;
+ u32 start;
+ int n_copy;
+ int n = n_bytes;
+ int n_done = 0;
+ int n_writeback;
+ loff_t start_write = offset;
+ int chunk_written = 0;
+ u32 n_bytes_read;
+ loff_t chunk_start;
+ struct yaffs_dev *dev;
+
+ dev = in->my_dev;
+
+ while (n > 0 && chunk_written >= 0) {
+ yaffs_addr_to_chunk(dev, offset, &chunk, &start);
+
+ if (((loff_t)chunk) *
+ dev->data_bytes_per_chunk + start != offset ||
+ start >= dev->data_bytes_per_chunk) {
+ yaffs_trace(YAFFS_TRACE_ERROR,
+ "AddrToChunk of offset %lld gives chunk %d start %d",
+ (long long)offset, chunk, start);
+ }
+ chunk++; /* File pos to chunk in file offset */
+
+ /* OK now check for the curveball where the start and end are in
+ * the same chunk.
+ */
+
+ if ((start + n) < dev->data_bytes_per_chunk) {
+ n_copy = n;
+
+ /* Now calculate how many bytes to write back....
+ * If we're overwriting and not writing to then end of
+ * file then we need to write back as much as was there
+ * before.
+ */
+
+ chunk_start = (((loff_t)(chunk - 1)) *
+ dev->data_bytes_per_chunk);
+
+ if (chunk_start > in->variant.file_variant.file_size)
+ n_bytes_read = 0; /* Past end of file */
+ else
+ n_bytes_read =
+ in->variant.file_variant.file_size -
+ chunk_start;
+
+ if (n_bytes_read > dev->data_bytes_per_chunk)
+ n_bytes_read = dev->data_bytes_per_chunk;
+
+ n_writeback =
+ (n_bytes_read >
+ (start + n)) ? n_bytes_read : (start + n);
+
+ if (n_writeback < 0 ||
+ n_writeback > (int)dev->data_bytes_per_chunk)
+ BUG();
+
+ } else {
+ n_copy = dev->data_bytes_per_chunk - start;
+ n_writeback = dev->data_bytes_per_chunk;
+ }
+
+ if (n_copy != (int)dev->data_bytes_per_chunk ||
+ !dev->param.cache_bypass_aligned ||
+ dev->param.inband_tags) {
+ /* An incomplete start or end chunk (or maybe both
+ * start and end chunk), or we're using inband tags,
+ * or we're forcing writes through the cache,
+ * so we want to use the cache buffers.
+ */
+ if (dev->param.n_caches > 0) {
+ struct yaffs_cache *cache;
+
+ /* If we can't find the data in the cache, then
+ * load the cache */
+ cache = yaffs_find_chunk_cache(in, chunk);
+
+ if (!cache &&
+ yaffs_check_alloc_available(dev, 1)) {
+ cache = yaffs_grab_chunk_cache(dev);
+ cache->object = in;
+ cache->chunk_id = chunk;
+ cache->dirty = 0;
+ cache->locked = 0;
+ yaffs_rd_data_obj(in, chunk,
+ cache->data);
+ } else if (cache &&
+ !cache->dirty &&
+ !yaffs_check_alloc_available(dev,
+ 1)) {
+ /* Drop the cache if it was a read cache
+ * item and no space check has been made
+ * for it.
+ */
+ cache = NULL;
+ }
+
+ if (cache) {
+ yaffs_use_cache(dev, cache, 1);
+ cache->locked = 1;
+
+ memcpy(&cache->data[start], buffer,
+ n_copy);
+
+ cache->locked = 0;
+ cache->n_bytes = n_writeback;
+
+ if (write_through) {
+ chunk_written =
+ yaffs_wr_data_obj
+ (cache->object,
+ cache->chunk_id,
+ cache->data,
+ cache->n_bytes, 1);
+ cache->dirty = 0;
+ }
+ } else {
+ chunk_written = -1; /* fail write */
+ }
+ } else {
+ /* An incomplete start or end chunk (or maybe
+ * both start and end chunk). Read into the
+ * local buffer then copy over and write back.
+ */
+
+ u8 *local_buffer = yaffs_get_temp_buffer(dev);
+
+ yaffs_rd_data_obj(in, chunk, local_buffer);
+ memcpy(&local_buffer[start], buffer, n_copy);
+
+ chunk_written =
+ yaffs_wr_data_obj(in, chunk,
+ local_buffer,
+ n_writeback, 0);
+
+ yaffs_release_temp_buffer(dev, local_buffer);
+ }
+ } else {
+ /* A full chunk. Write directly from the buffer. */
+
+ chunk_written =
+ yaffs_wr_data_obj(in, chunk, buffer,
+ dev->data_bytes_per_chunk, 0);
+
+ /* Since we've overwritten the cached data,
+ * we better invalidate it. */
+ yaffs_invalidate_chunk_cache(in, chunk);
+ }
+
+ if (chunk_written >= 0) {
+ n -= n_copy;
+ offset += n_copy;
+ buffer += n_copy;
+ n_done += n_copy;
+ }
+ }
+
+ /* Update file object */
+
+ if ((start_write + n_done) > in->variant.file_variant.file_size)
+ in->variant.file_variant.file_size = (start_write + n_done);
+
+ in->dirty = 1;
+ return n_done;
+}
+
+int yaffs_wr_file(struct yaffs_obj *in, const u8 *buffer, loff_t offset,
+ int n_bytes, int write_through)
+{
+ yaffs2_handle_hole(in, offset);
+ return yaffs_do_file_wr(in, buffer, offset, n_bytes, write_through);
+}
+
+/* ---------------------- File resizing stuff ------------------ */
+
+static void yaffs_prune_chunks(struct yaffs_obj *in, loff_t new_size)
+{
+
+ struct yaffs_dev *dev = in->my_dev;
+ loff_t old_size = in->variant.file_variant.file_size;
+ int i;
+ int chunk_id;
+ u32 dummy;
+ int last_del;
+ int start_del;
+
+ if (old_size > 0)
+ yaffs_addr_to_chunk(dev, old_size - 1, &last_del, &dummy);
+ else
+ last_del = 0;
+
+ yaffs_addr_to_chunk(dev, new_size + dev->data_bytes_per_chunk - 1,
+ &start_del, &dummy);
+ last_del++;
+ start_del++;
+
+ /* Delete backwards so that we don't end up with holes if
+ * power is lost part-way through the operation.
+ */
+ for (i = last_del; i >= start_del; i--) {
+ /* NB this could be optimised somewhat,
+ * eg. could retrieve the tags and write them without
+ * using yaffs_chunk_del
+ */
+
+ chunk_id = yaffs_find_del_file_chunk(in, i, NULL);
+
+ if (chunk_id < 1)
+ continue;
+
+ if ((u32)chunk_id <
+ (dev->internal_start_block * dev->param.chunks_per_block) ||
+ (u32)chunk_id >=
+ ((dev->internal_end_block + 1) *
+ dev->param.chunks_per_block)) {
+ yaffs_trace(YAFFS_TRACE_ALWAYS,
+ "Found daft chunk_id %d for %d",
+ chunk_id, i);
+ } else {
+ in->n_data_chunks--;
+ yaffs_chunk_del(dev, chunk_id, 1, __LINE__);
+ }
+ }
+}
+
+void yaffs_resize_file_down(struct yaffs_obj *obj, loff_t new_size)
+{
+ int new_full;
+ u32 new_partial;
+ struct yaffs_dev *dev = obj->my_dev;
+
+ yaffs_addr_to_chunk(dev, new_size, &new_full, &new_partial);
+
+ yaffs_prune_chunks(obj, new_size);
+
+ if (new_partial != 0) {
+ int last_chunk = 1 + new_full;
+ u8 *local_buffer = yaffs_get_temp_buffer(dev);
+
+ /* Rewrite the last chunk with its new size and zero pad */
+ yaffs_rd_data_obj(obj, last_chunk, local_buffer);
+ memset(local_buffer + new_partial, 0,
+ dev->data_bytes_per_chunk - new_partial);
+
+ yaffs_wr_data_obj(obj, last_chunk, local_buffer,
+ new_partial, 1);
+
+ yaffs_release_temp_buffer(dev, local_buffer);
+ }
+
+ obj->variant.file_variant.file_size = new_size;
+ obj->variant.file_variant.stored_size = new_size;
+
+ yaffs_prune_tree(dev, &obj->variant.file_variant);
+}
+
+int yaffs_resize_file(struct yaffs_obj *in, loff_t new_size)
+{
+ struct yaffs_dev *dev = in->my_dev;
+ loff_t old_size = in->variant.file_variant.file_size;
+
+ yaffs_flush_file_cache(in, 1);
+ yaffs_invalidate_whole_cache(in);
+
+ yaffs_check_gc(dev, 0);
+
+ if (in->variant_type != YAFFS_OBJECT_TYPE_FILE)
+ return YAFFS_FAIL;
+
+ if (new_size == old_size)
+ return YAFFS_OK;
+
+ if (new_size > old_size) {
+ yaffs2_handle_hole(in, new_size);
+ in->variant.file_variant.file_size = new_size;
+ } else {
+ /* new_size < old_size */
+ yaffs_resize_file_down(in, new_size);
+ }
+
+ /* Write a new object header to reflect the resize.
+ * show we've shrunk the file, if need be
+ * Do this only if the file is not in the deleted directories
+ * and is not shadowed.
+ */
+ if (in->parent &&
+ !in->is_shadowed &&
+ in->parent->obj_id != YAFFS_OBJECTID_UNLINKED &&
+ in->parent->obj_id != YAFFS_OBJECTID_DELETED)
+ yaffs_update_oh(in, NULL, 0, 0, 0, NULL);
+
+ return YAFFS_OK;
+}
+
+int yaffs_flush_file(struct yaffs_obj *in,
+ int update_time,
+ int data_sync,
+ int discard_cache)
+{
+ if (!in->dirty)
+ return YAFFS_OK;
+
+ yaffs_flush_file_cache(in, discard_cache);
+
+ if (data_sync)
+ return YAFFS_OK;
+
+ if (update_time)
+ yaffs_load_current_time(in, 0, 0);
+
+ return (yaffs_update_oh(in, NULL, 0, 0, 0, NULL) >= 0) ?
+ YAFFS_OK : YAFFS_FAIL;
+}
+
+
+/* yaffs_del_file deletes the whole file data
+ * and the inode associated with the file.
+ * It does not delete the links associated with the file.
+ */
+static int yaffs_unlink_file_if_needed(struct yaffs_obj *in)
+{
+ int ret_val;
+ int del_now = 0;
+ struct yaffs_dev *dev = in->my_dev;
+
+ if (!in->my_inode)
+ del_now = 1;
+
+ if (del_now) {
+ ret_val =
+ yaffs_change_obj_name(in, in->my_dev->del_dir,
+ _Y("deleted"), 0, 0);
+ yaffs_trace(YAFFS_TRACE_TRACING,
+ "yaffs: immediate deletion of file %d",
+ in->obj_id);
+ in->deleted = 1;
+ in->my_dev->n_deleted_files++;
+ if (dev->param.disable_soft_del || dev->param.is_yaffs2)
+ yaffs_resize_file(in, 0);
+ yaffs_soft_del_file(in);
+ } else {
+ ret_val =
+ yaffs_change_obj_name(in, in->my_dev->unlinked_dir,
+ _Y("unlinked"), 0, 0);
+ }
+ return ret_val;
+}
+
+static int yaffs_del_file(struct yaffs_obj *in)
+{
+ int ret_val = YAFFS_OK;
+ int deleted; /* Need to cache value on stack if in is freed */
+ struct yaffs_dev *dev = in->my_dev;
+
+ if (dev->param.disable_soft_del || dev->param.is_yaffs2)
+ yaffs_resize_file(in, 0);
+
+ if (in->n_data_chunks > 0) {
+ /* Use soft deletion if there is data in the file.
+ * That won't be the case if it has been resized to zero.
+ */
+ if (!in->unlinked)
+ ret_val = yaffs_unlink_file_if_needed(in);
+
+ deleted = in->deleted;
+
+ if (ret_val == YAFFS_OK && in->unlinked && !in->deleted) {
+ in->deleted = 1;
+ deleted = 1;
+ in->my_dev->n_deleted_files++;
+ yaffs_soft_del_file(in);
+ }
+ return deleted ? YAFFS_OK : YAFFS_FAIL;
+ } else {
+ /* The file has no data chunks so we toss it immediately */
+ yaffs_free_tnode(in->my_dev, in->variant.file_variant.top);
+ in->variant.file_variant.top = NULL;
+ yaffs_generic_obj_del(in);
+
+ return YAFFS_OK;
+ }
+}
+
+int yaffs_is_non_empty_dir(struct yaffs_obj *obj)
+{
+ return (obj &&
+ obj->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY) &&
+ !(list_empty(&obj->variant.dir_variant.children));
+}
+
+static int yaffs_del_dir(struct yaffs_obj *obj)
+{
+ /* First check that the directory is empty. */
+ if (yaffs_is_non_empty_dir(obj))
+ return YAFFS_FAIL;
+
+ return yaffs_generic_obj_del(obj);
+}
+
+static int yaffs_del_symlink(struct yaffs_obj *in)
+{
+ kfree(in->variant.symlink_variant.alias);
+ in->variant.symlink_variant.alias = NULL;
+
+ return yaffs_generic_obj_del(in);
+}
+
+static int yaffs_del_link(struct yaffs_obj *in)
+{
+ /* remove this hardlink from the list associated with the equivalent
+ * object
+ */
+ list_del_init(&in->hard_links);
+ return yaffs_generic_obj_del(in);
+}
+
+int yaffs_del_obj(struct yaffs_obj *obj)
+{
+ int ret_val = -1;
+
+ switch (obj->variant_type) {
+ case YAFFS_OBJECT_TYPE_FILE:
+ ret_val = yaffs_del_file(obj);
+ break;
+ case YAFFS_OBJECT_TYPE_DIRECTORY:
+ if (!list_empty(&obj->variant.dir_variant.dirty)) {
+ yaffs_trace(YAFFS_TRACE_BACKGROUND,
+ "Remove object %d from dirty directories",
+ obj->obj_id);
+ list_del_init(&obj->variant.dir_variant.dirty);
+ }
+ return yaffs_del_dir(obj);
+ break;
+ case YAFFS_OBJECT_TYPE_SYMLINK:
+ ret_val = yaffs_del_symlink(obj);
+ break;
+ case YAFFS_OBJECT_TYPE_HARDLINK:
+ ret_val = yaffs_del_link(obj);
+ break;
+ case YAFFS_OBJECT_TYPE_SPECIAL:
+ ret_val = yaffs_generic_obj_del(obj);
+ break;
+ case YAFFS_OBJECT_TYPE_UNKNOWN:
+ ret_val = 0;
+ break; /* should not happen. */
+ }
+ return ret_val;
+}
+
+
+static void yaffs_empty_dir_to_dir(struct yaffs_obj *from_dir,
+ struct yaffs_obj *to_dir)
+{
+ struct yaffs_obj *obj;
+ struct list_head *lh;
+ struct list_head *n;
+
+ list_for_each_safe(lh, n, &from_dir->variant.dir_variant.children) {
+ obj = list_entry(lh, struct yaffs_obj, siblings);
+ yaffs_add_obj_to_dir(to_dir, obj);
+ }
+}
+
+struct yaffs_obj *yaffs_retype_obj(struct yaffs_obj *obj,
+ enum yaffs_obj_type type)
+{
+ /* Tear down the old variant */
+ switch (obj->variant_type) {
+ case YAFFS_OBJECT_TYPE_FILE:
+ /* Nuke file data */
+ yaffs_resize_file(obj, 0);
+ yaffs_free_tnode(obj->my_dev, obj->variant.file_variant.top);
+ obj->variant.file_variant.top = NULL;
+ break;
+ case YAFFS_OBJECT_TYPE_DIRECTORY:
+ /* Put the children in lost and found. */
+ yaffs_empty_dir_to_dir(obj, obj->my_dev->lost_n_found);
+ if (!list_empty(&obj->variant.dir_variant.dirty))
+ list_del_init(&obj->variant.dir_variant.dirty);
+ break;
+ case YAFFS_OBJECT_TYPE_SYMLINK:
+ /* Nuke symplink data */
+ kfree(obj->variant.symlink_variant.alias);
+ obj->variant.symlink_variant.alias = NULL;
+ break;
+ case YAFFS_OBJECT_TYPE_HARDLINK:
+ list_del_init(&obj->hard_links);
+ break;
+ default:
+ break;
+ }
+
+ memset(&obj->variant, 0, sizeof(obj->variant));
+
+ /*Set up new variant if the memset is not enough. */
+ switch (type) {
+ case YAFFS_OBJECT_TYPE_DIRECTORY:
+ INIT_LIST_HEAD(&obj->variant.dir_variant.children);
+ INIT_LIST_HEAD(&obj->variant.dir_variant.dirty);
+ break;
+ case YAFFS_OBJECT_TYPE_FILE:
+ case YAFFS_OBJECT_TYPE_SYMLINK:
+ case YAFFS_OBJECT_TYPE_HARDLINK:
+ default:
+ break;
+ }
+
+ obj->variant_type = type;
+
+ return obj;
+
+}
+
+static int yaffs_unlink_worker(struct yaffs_obj *obj)
+{
+ int del_now = 0;
+
+ if (!obj)
+ return YAFFS_FAIL;
+
+ if (!obj->my_inode)
+ del_now = 1;
+
+ yaffs_update_parent(obj->parent);
+
+ if (obj->variant_type == YAFFS_OBJECT_TYPE_HARDLINK) {
+ return yaffs_del_link(obj);
+ } else if (!list_empty(&obj->hard_links)) {
+ /* Curve ball: We're unlinking an object that has a hardlink.
+ *
+ * This problem arises because we are not strictly following
+ * The Linux link/inode model.
+ *
+ * We can't really delete the object.
+ * Instead, we do the following:
+ * - Select a hardlink.
+ * - Unhook it from the hard links
+ * - Move it from its parent directory so that the rename works.
+ * - Rename the object to the hardlink's name.
+ * - Delete the hardlink
+ */
+
+ struct yaffs_obj *hl;
+ struct yaffs_obj *parent;
+ int ret_val;
+ YCHAR name[YAFFS_MAX_NAME_LENGTH + 1];
+
+ hl = list_entry(obj->hard_links.next, struct yaffs_obj,
+ hard_links);
+
+ yaffs_get_obj_name(hl, name, YAFFS_MAX_NAME_LENGTH + 1);
+ parent = hl->parent;
+
+ list_del_init(&hl->hard_links);
+
+ yaffs_add_obj_to_dir(obj->my_dev->unlinked_dir, hl);
+
+ ret_val = yaffs_change_obj_name(obj, parent, name, 0, 0);
+
+ if (ret_val == YAFFS_OK)
+ ret_val = yaffs_generic_obj_del(hl);
+
+ return ret_val;
+
+ } else if (del_now) {
+ switch (obj->variant_type) {
+ case YAFFS_OBJECT_TYPE_FILE:
+ return yaffs_del_file(obj);
+ break;
+ case YAFFS_OBJECT_TYPE_DIRECTORY:
+ list_del_init(&obj->variant.dir_variant.dirty);
+ return yaffs_del_dir(obj);
+ break;
+ case YAFFS_OBJECT_TYPE_SYMLINK:
+ return yaffs_del_symlink(obj);
+ break;
+ case YAFFS_OBJECT_TYPE_SPECIAL:
+ return yaffs_generic_obj_del(obj);
+ break;
+ case YAFFS_OBJECT_TYPE_HARDLINK:
+ case YAFFS_OBJECT_TYPE_UNKNOWN:
+ default:
+ return YAFFS_FAIL;
+ }
+ } else if (yaffs_is_non_empty_dir(obj)) {
+ return YAFFS_FAIL;
+ } else {
+ return yaffs_change_obj_name(obj, obj->my_dev->unlinked_dir,
+ _Y("unlinked"), 0, 0);
+ }
+}
+
+int yaffs_unlink_obj(struct yaffs_obj *obj)
+{
+ if (obj && obj->unlink_allowed)
+ return yaffs_unlink_worker(obj);
+
+ return YAFFS_FAIL;
+}
+
+int yaffs_unlinker(struct yaffs_obj *dir, const YCHAR *name)
+{
+ struct yaffs_obj *obj;
+
+ obj = yaffs_find_by_name(dir, name);
+ return yaffs_unlink_obj(obj);
+}
+
+/* Note:
+ * If old_name is NULL then we take old_dir as the object to be renamed.
+ */
+int yaffs_rename_obj(struct yaffs_obj *old_dir, const YCHAR *old_name,
+ struct yaffs_obj *new_dir, const YCHAR *new_name)
+{
+ struct yaffs_obj *obj = NULL;
+ struct yaffs_obj *existing_target = NULL;
+ int force = 0;
+ int result;
+ struct yaffs_dev *dev;
+
+ if (!old_dir || old_dir->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) {
+ BUG();
+ return YAFFS_FAIL;
+ }
+ if (!new_dir || new_dir->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) {
+ BUG();
+ return YAFFS_FAIL;
+ }
+
+ dev = old_dir->my_dev;
+
+#ifdef CONFIG_YAFFS_CASE_INSENSITIVE
+ /* Special case for case insemsitive systems.
+ * While look-up is case insensitive, the name isn't.
+ * Therefore we might want to change x.txt to X.txt
+ */
+ if (old_dir == new_dir &&
+ old_name && new_name &&
+ strcmp(old_name, new_name) == 0)
+ force = 1;
+#endif
+
+ if (strnlen(new_name, YAFFS_MAX_NAME_LENGTH + 1) >
+ YAFFS_MAX_NAME_LENGTH)
+ /* ENAMETOOLONG */
+ return YAFFS_FAIL;
+
+ if (old_name)
+ obj = yaffs_find_by_name(old_dir, old_name);
+ else{
+ obj = old_dir;
+ old_dir = obj->parent;
+ }
+
+ if (obj && obj->rename_allowed) {
+ /* Now handle an existing target, if there is one */
+ existing_target = yaffs_find_by_name(new_dir, new_name);
+ if (yaffs_is_non_empty_dir(existing_target)) {
+ return YAFFS_FAIL; /* ENOTEMPTY */
+ } else if (existing_target && existing_target != obj) {
+ /* Nuke the target first, using shadowing,
+ * but only if it isn't the same object.
+ *
+ * Note we must disable gc here otherwise it can mess
+ * up the shadowing.
+ *
+ */
+ dev->gc_disable = 1;
+ yaffs_change_obj_name(obj, new_dir, new_name, force,
+ existing_target->obj_id);
+ existing_target->is_shadowed = 1;
+ yaffs_unlink_obj(existing_target);
+ dev->gc_disable = 0;
+ }
+
+ result = yaffs_change_obj_name(obj, new_dir, new_name, 1, 0);
+
+ yaffs_update_parent(old_dir);
+ if (new_dir != old_dir)
+ yaffs_update_parent(new_dir);
+
+ return result;
+ }
+ return YAFFS_FAIL;
+}
+
+/*----------------------- Initialisation Scanning ---------------------- */
+
+void yaffs_handle_shadowed_obj(struct yaffs_dev *dev, int obj_id,
+ int backward_scanning)
+{
+ struct yaffs_obj *obj;
+
+ if (backward_scanning) {
+ /* Handle YAFFS2 case (backward scanning)
+ * If the shadowed object exists then ignore.
+ */
+ obj = yaffs_find_by_number(dev, obj_id);
+ if (obj)
+ return;
+ }
+
+ /* Let's create it (if it does not exist) assuming it is a file so that
+ * it can do shrinking etc.
+ * We put it in unlinked dir to be cleaned up after the scanning
+ */
+ obj =
+ yaffs_find_or_create_by_number(dev, obj_id, YAFFS_OBJECT_TYPE_FILE);
+ if (!obj)
+ return;
+ obj->is_shadowed = 1;
+ yaffs_add_obj_to_dir(dev->unlinked_dir, obj);
+ obj->variant.file_variant.shrink_size = 0;
+ obj->valid = 1; /* So that we don't read any other info. */
+}
+
+void yaffs_link_fixup(struct yaffs_dev *dev, struct list_head *hard_list)
+{
+ struct list_head *lh;
+ struct list_head *save;
+ struct yaffs_obj *hl;
+ struct yaffs_obj *in;
+
+ list_for_each_safe(lh, save, hard_list) {
+ hl = list_entry(lh, struct yaffs_obj, hard_links);
+ in = yaffs_find_by_number(dev,
+ hl->variant.hardlink_variant.equiv_id);
+
+ if (in) {
+ /* Add the hardlink pointers */
+ hl->variant.hardlink_variant.equiv_obj = in;
+ list_add(&hl->hard_links, &in->hard_links);
+ } else {
+ /* Todo Need to report/handle this better.
+ * Got a problem... hardlink to a non-existant object
+ */
+ hl->variant.hardlink_variant.equiv_obj = NULL;
+ INIT_LIST_HEAD(&hl->hard_links);
+ }
+ }
+}
+
+static void yaffs_strip_deleted_objs(struct yaffs_dev *dev)
+{
+ /*
+ * Sort out state of unlinked and deleted objects after scanning.
+ */
+ struct list_head *i;
+ struct list_head *n;
+ struct yaffs_obj *l;
+
+ if (dev->read_only)
+ return;
+
+ /* Soft delete all the unlinked files */
+ list_for_each_safe(i, n,
+ &dev->unlinked_dir->variant.dir_variant.children) {
+ l = list_entry(i, struct yaffs_obj, siblings);
+ yaffs_del_obj(l);
+ }
+
+ list_for_each_safe(i, n, &dev->del_dir->variant.dir_variant.children) {
+ l = list_entry(i, struct yaffs_obj, siblings);
+ yaffs_del_obj(l);
+ }
+}
+
+/*
+ * This code iterates through all the objects making sure that they are rooted.
+ * Any unrooted objects are re-rooted in lost+found.
+ * An object needs to be in one of:
+ * - Directly under deleted, unlinked
+ * - Directly or indirectly under root.
+ *
+ * Note:
+ * This code assumes that we don't ever change the current relationships
+ * between directories:
+ * root_dir->parent == unlinked_dir->parent == del_dir->parent == NULL
+ * lost-n-found->parent == root_dir
+ *
+ * This fixes the problem where directories might have inadvertently been
+ * deleted leaving the object "hanging" without being rooted in the
+ * directory tree.
+ */
+
+static int yaffs_has_null_parent(struct yaffs_dev *dev, struct yaffs_obj *obj)
+{
+ return (obj == dev->del_dir ||
+ obj == dev->unlinked_dir || obj == dev->root_dir);
+}
+
+static void yaffs_fix_hanging_objs(struct yaffs_dev *dev)
+{
+ struct yaffs_obj *obj;
+ struct yaffs_obj *parent;
+ int i;
+ struct list_head *lh;
+ struct list_head *n;
+ int depth_limit;
+ int hanging;
+
+ if (dev->read_only)
+ return;
+
+ /* Iterate through the objects in each hash entry,
+ * looking at each object.
+ * Make sure it is rooted.
+ */
+
+ for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) {
+ list_for_each_safe(lh, n, &dev->obj_bucket[i].list) {
+ obj = list_entry(lh, struct yaffs_obj, hash_link);
+ parent = obj->parent;
+
+ if (yaffs_has_null_parent(dev, obj)) {
+ /* These directories are not hanging */
+ hanging = 0;
+ } else if (!parent ||
+ parent->variant_type !=
+ YAFFS_OBJECT_TYPE_DIRECTORY) {
+ hanging = 1;
+ } else if (yaffs_has_null_parent(dev, parent)) {
+ hanging = 0;
+ } else {
+ /*
+ * Need to follow the parent chain to
+ * see if it is hanging.
+ */
+ hanging = 0;
+ depth_limit = 100;
+
+ while (parent != dev->root_dir &&
+ parent->parent &&
+ parent->parent->variant_type ==
+ YAFFS_OBJECT_TYPE_DIRECTORY &&
+ depth_limit > 0) {
+ parent = parent->parent;
+ depth_limit--;
+ }
+ if (parent != dev->root_dir)
+ hanging = 1;
+ }
+ if (hanging) {
+ yaffs_trace(YAFFS_TRACE_SCAN,
+ "Hanging object %d moved to lost and found",
+ obj->obj_id);
+ yaffs_add_obj_to_dir(dev->lost_n_found, obj);
+ }
+ }
+ }
+}
+
+/*
+ * Delete directory contents for cleaning up lost and found.
+ */
+static void yaffs_del_dir_contents(struct yaffs_obj *dir)
+{
+ struct yaffs_obj *obj;
+ struct list_head *lh;
+ struct list_head *n;
+
+ if (dir->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY)
+ BUG();
+
+ list_for_each_safe(lh, n, &dir->variant.dir_variant.children) {
+ obj = list_entry(lh, struct yaffs_obj, siblings);
+ if (obj->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY)
+ yaffs_del_dir_contents(obj);
+ yaffs_trace(YAFFS_TRACE_SCAN,
+ "Deleting lost_found object %d",
+ obj->obj_id);
+ yaffs_unlink_obj(obj);
+ }
+}
+
+static void yaffs_empty_l_n_f(struct yaffs_dev *dev)
+{
+ yaffs_del_dir_contents(dev->lost_n_found);
+}
+
+
+struct yaffs_obj *yaffs_find_by_name(struct yaffs_obj *directory,
+ const YCHAR *name)
+{
+ int sum;
+ struct list_head *i;
+ YCHAR buffer[YAFFS_MAX_NAME_LENGTH + 1];
+ struct yaffs_obj *l;
+
+ if (!name)
+ return NULL;
+
+ if (!directory) {
+ yaffs_trace(YAFFS_TRACE_ALWAYS,
+ "tragedy: yaffs_find_by_name: null pointer directory"
+ );
+ BUG();
+ return NULL;
+ }
+ if (directory->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) {
+ yaffs_trace(YAFFS_TRACE_ALWAYS,
+ "tragedy: yaffs_find_by_name: non-directory"
+ );
+ BUG();
+ }
+
+ sum = yaffs_calc_name_sum(name);
+
+ list_for_each(i, &directory->variant.dir_variant.children) {
+ l = list_entry(i, struct yaffs_obj, siblings);
+
+ if (l->parent != directory)
+ BUG();
+
+ yaffs_check_obj_details_loaded(l);
+
+ /* Special case for lost-n-found */
+ if (l->obj_id == YAFFS_OBJECTID_LOSTNFOUND) {
+ if (!strcmp(name, YAFFS_LOSTNFOUND_NAME))
+ return l;
+ } else if (l->sum == sum || l->hdr_chunk <= 0) {
+ /* LostnFound chunk called Objxxx
+ * Do a real check
+ */
+ yaffs_get_obj_name(l, buffer,
+ YAFFS_MAX_NAME_LENGTH + 1);
+ if (!strncmp(name, buffer, YAFFS_MAX_NAME_LENGTH))
+ return l;
+ }
+ }
+ return NULL;
+}
+
+/* GetEquivalentObject dereferences any hard links to get to the
+ * actual object.
+ */
+
+struct yaffs_obj *yaffs_get_equivalent_obj(struct yaffs_obj *obj)
+{
+ if (obj && obj->variant_type == YAFFS_OBJECT_TYPE_HARDLINK) {
+ obj = obj->variant.hardlink_variant.equiv_obj;
+ yaffs_check_obj_details_loaded(obj);
+ }
+ return obj;
+}
+
+/*
+ * A note or two on object names.
+ * * If the object name is missing, we then make one up in the form objnnn
+ *
+ * * ASCII names are stored in the object header's name field from byte zero
+ * * Unicode names are historically stored starting from byte zero.
+ *
+ * Then there are automatic Unicode names...
+ * The purpose of these is to save names in a way that can be read as
+ * ASCII or Unicode names as appropriate, thus allowing a Unicode and ASCII
+ * system to share files.
+ *
+ * These automatic unicode are stored slightly differently...
+ * - If the name can fit in the ASCII character space then they are saved as
+ * ascii names as per above.
+ * - If the name needs Unicode then the name is saved in Unicode
+ * starting at oh->name[1].
+
+ */
+static void yaffs_fix_null_name(struct yaffs_obj *obj, YCHAR *name,
+ int buffer_size)
+{
+ /* Create an object name if we could not find one. */
+ if (strnlen(name, YAFFS_MAX_NAME_LENGTH) == 0) {
+ YCHAR local_name[20];
+ YCHAR num_string[20];
+ YCHAR *x = &num_string[19];
+ unsigned v = obj->obj_id;
+ num_string[19] = 0;
+ while (v > 0) {
+ x--;
+ *x = '0' + (v % 10);
+ v /= 10;
+ }
+ /* make up a name */
+ strcpy(local_name, YAFFS_LOSTNFOUND_PREFIX);
+ strcat(local_name, x);
+ strncpy(name, local_name, buffer_size - 1);
+ }
+}
+
+int yaffs_get_obj_name(struct yaffs_obj *obj, YCHAR *name, int buffer_size)
+{
+ memset(name, 0, buffer_size * sizeof(YCHAR));
+ yaffs_check_obj_details_loaded(obj);
+ if (obj->obj_id == YAFFS_OBJECTID_LOSTNFOUND) {
+ strncpy(name, YAFFS_LOSTNFOUND_NAME, buffer_size - 1);
+ } else if (obj->short_name[0]) {
+ strcpy(name, obj->short_name);
+ } else if (obj->hdr_chunk > 0) {
+ int result = 0;
+ u8 *buffer = yaffs_get_temp_buffer(obj->my_dev);
+
+ struct yaffs_obj_hdr *oh = (struct yaffs_obj_hdr *)buffer;
+
+ memset(buffer, 0, obj->my_dev->data_bytes_per_chunk);
+
+ if (obj->hdr_chunk > 0) {
+ result = yaffs_rd_chunk_tags_nand(obj->my_dev,
+ obj->hdr_chunk,
+ buffer, NULL);
+ }
+ if (result == YAFFS_OK)
+ yaffs_load_name_from_oh(obj->my_dev, name, oh->name,
+ buffer_size);
+
+ yaffs_release_temp_buffer(obj->my_dev, buffer);
+ }
+
+ yaffs_fix_null_name(obj, name, buffer_size);
+
+ return strnlen(name, YAFFS_MAX_NAME_LENGTH);
+}
+
+loff_t yaffs_get_obj_length(struct yaffs_obj *obj)
+{
+ /* Dereference any hard linking */
+ obj = yaffs_get_equivalent_obj(obj);
+
+ if (obj->variant_type == YAFFS_OBJECT_TYPE_FILE)
+ return obj->variant.file_variant.file_size;
+ if (obj->variant_type == YAFFS_OBJECT_TYPE_SYMLINK) {
+ if (!obj->variant.symlink_variant.alias)
+ return 0;
+ return strnlen(obj->variant.symlink_variant.alias,
+ YAFFS_MAX_ALIAS_LENGTH);
+ } else {
+ /* Only a directory should drop through to here */
+ return obj->my_dev->data_bytes_per_chunk;
+ }
+}
+
+int yaffs_get_obj_link_count(struct yaffs_obj *obj)
+{
+ int count = 0;
+ struct list_head *i;
+
+ if (!obj->unlinked)
+ count++; /* the object itself */
+
+ list_for_each(i, &obj->hard_links)
+ count++; /* add the hard links; */
+
+ return count;
+}
+
+int yaffs_get_obj_inode(struct yaffs_obj *obj)
+{
+ obj = yaffs_get_equivalent_obj(obj);
+
+ return obj->obj_id;
+}
+
+unsigned yaffs_get_obj_type(struct yaffs_obj *obj)
+{
+ obj = yaffs_get_equivalent_obj(obj);
+
+ switch (obj->variant_type) {
+ case YAFFS_OBJECT_TYPE_FILE:
+ return DT_REG;
+ break;
+ case YAFFS_OBJECT_TYPE_DIRECTORY:
+ return DT_DIR;
+ break;
+ case YAFFS_OBJECT_TYPE_SYMLINK:
+ return DT_LNK;
+ break;
+ case YAFFS_OBJECT_TYPE_HARDLINK:
+ return DT_REG;
+ break;
+ case YAFFS_OBJECT_TYPE_SPECIAL:
+ if (S_ISFIFO(obj->yst_mode))
+ return DT_FIFO;
+ if (S_ISCHR(obj->yst_mode))
+ return DT_CHR;
+ if (S_ISBLK(obj->yst_mode))
+ return DT_BLK;
+ if (S_ISSOCK(obj->yst_mode))
+ return DT_SOCK;
+ return DT_REG;
+ break;
+ default:
+ return DT_REG;
+ break;
+ }
+}
+
+YCHAR *yaffs_get_symlink_alias(struct yaffs_obj *obj)
+{
+ obj = yaffs_get_equivalent_obj(obj);
+ if (obj->variant_type == YAFFS_OBJECT_TYPE_SYMLINK)
+ return yaffs_clone_str(obj->variant.symlink_variant.alias);
+ else
+ return yaffs_clone_str(_Y(""));
+}
+
+/*--------------------------- Initialisation code -------------------------- */
+
+static int yaffs_check_dev_fns(struct yaffs_dev *dev)
+{
+ struct yaffs_driver *drv = &dev->drv;
+ struct yaffs_tags_handler *tagger = &dev->tagger;
+
+ /* Common functions, gotta have */
+ if (!drv->drv_read_chunk_fn ||
+ !drv->drv_write_chunk_fn ||
+ !drv->drv_erase_fn)
+ return 0;
+
+ if (dev->param.is_yaffs2 &&
+ (!drv->drv_mark_bad_fn || !drv->drv_check_bad_fn))
+ return 0;
+
+ /* Install the default tags marshalling functions if needed. */
+ yaffs_tags_compat_install(dev);
+ yaffs_tags_marshall_install(dev);
+
+ /* Check we now have the marshalling functions required. */
+ if (!tagger->write_chunk_tags_fn ||
+ !tagger->read_chunk_tags_fn ||
+ !tagger->query_block_fn ||
+ !tagger->mark_bad_fn)
+ return 0;
+
+ return 1;
+}
+
+static int yaffs_create_initial_dir(struct yaffs_dev *dev)
+{
+ /* Initialise the unlinked, deleted, root and lost+found directories */
+ dev->lost_n_found = NULL;
+ dev->root_dir = NULL;
+ dev->unlinked_dir = NULL;
+ dev->del_dir = NULL;
+
+ dev->unlinked_dir =
+ yaffs_create_fake_dir(dev, YAFFS_OBJECTID_UNLINKED, S_IFDIR);
+ dev->del_dir =
+ yaffs_create_fake_dir(dev, YAFFS_OBJECTID_DELETED, S_IFDIR);
+ dev->root_dir =
+ yaffs_create_fake_dir(dev, YAFFS_OBJECTID_ROOT,
+ YAFFS_ROOT_MODE | S_IFDIR);
+ dev->lost_n_found =
+ yaffs_create_fake_dir(dev, YAFFS_OBJECTID_LOSTNFOUND,
+ YAFFS_LOSTNFOUND_MODE | S_IFDIR);
+
+ if (dev->lost_n_found &&
+ dev->root_dir &&
+ dev->unlinked_dir &&
+ dev->del_dir) {
+ /* If lost-n-found is hidden then yank it out of the directory tree. */
+ if (dev->param.hide_lost_n_found)
+ list_del_init(&dev->lost_n_found->siblings);
+ else
+ yaffs_add_obj_to_dir(dev->root_dir, dev->lost_n_found);
+ return YAFFS_OK;
+ }
+ return YAFFS_FAIL;
+}
+
+/* Low level init.
+ * Typically only used by yaffs_guts_initialise, but also used by the
+ * Low level yaffs driver tests.
+ */
+
+int yaffs_guts_ll_init(struct yaffs_dev *dev)
+{
+
+
+ yaffs_trace(YAFFS_TRACE_TRACING, "yaffs: yaffs_ll_init()");
+
+ if (!dev) {
+ yaffs_trace(YAFFS_TRACE_ALWAYS,
+ "yaffs: Need a device"
+ );
+ return YAFFS_FAIL;
+ }
+
+ if (dev->ll_init)
+ return YAFFS_OK;
+
+ dev->internal_start_block = dev->param.start_block;
+ dev->internal_end_block = dev->param.end_block;
+ dev->block_offset = 0;
+ dev->chunk_offset = 0;
+ dev->n_free_chunks = 0;
+
+ dev->gc_block = 0;
+
+ if (dev->param.start_block == 0) {
+ dev->internal_start_block = dev->param.start_block + 1;
+ dev->internal_end_block = dev->param.end_block + 1;
+ dev->block_offset = 1;
+ dev->chunk_offset = dev->param.chunks_per_block;
+ }
+
+ /* Check geometry parameters. */
+
+ if ((!dev->param.inband_tags && dev->param.is_yaffs2 &&
+ dev->param.total_bytes_per_chunk < 1024) ||
+ (!dev->param.is_yaffs2 &&
+ dev->param.total_bytes_per_chunk < 512) ||
+ (dev->param.inband_tags && !dev->param.is_yaffs2) ||
+ dev->param.chunks_per_block < 2 ||
+ dev->param.n_reserved_blocks < 2 ||
+ dev->internal_start_block <= 0 ||
+ dev->internal_end_block <= 0 ||
+ dev->internal_end_block <=
+ (dev->internal_start_block + dev->param.n_reserved_blocks + 2)
+ ) {
+ /* otherwise it is too small */
+ yaffs_trace(YAFFS_TRACE_ALWAYS,
+ "NAND geometry problems: chunk size %d, type is yaffs%s, inband_tags %d ",
+ dev->param.total_bytes_per_chunk,
+ dev->param.is_yaffs2 ? "2" : "",
+ dev->param.inband_tags);
+ return YAFFS_FAIL;
+ }
+
+ /* Sort out space for inband tags, if required */
+ if (dev->param.inband_tags)
+ dev->data_bytes_per_chunk =
+ dev->param.total_bytes_per_chunk -
+ sizeof(struct yaffs_packed_tags2_tags_only);
+ else
+ dev->data_bytes_per_chunk = dev->param.total_bytes_per_chunk;
+
+ /* Got the right mix of functions? */
+ if (!yaffs_check_dev_fns(dev)) {
+ /* Function missing */
+ yaffs_trace(YAFFS_TRACE_ALWAYS,
+ "device function(s) missing or wrong");
+
+ return YAFFS_FAIL;
+ }
+
+ if (yaffs_init_nand(dev) != YAFFS_OK) {
+ yaffs_trace(YAFFS_TRACE_ALWAYS, "InitialiseNAND failed");
+ return YAFFS_FAIL;
+ }
+
+ return YAFFS_OK;
+}
+
+
+int yaffs_guts_format_dev(struct yaffs_dev *dev)
+{
+ u32 i;
+ enum yaffs_block_state state;
+ u32 dummy;
+
+ if(yaffs_guts_ll_init(dev) != YAFFS_OK)
+ return YAFFS_FAIL;
+
+ if(dev->is_mounted)
+ return YAFFS_FAIL;
+
+ for (i = dev->internal_start_block; i <= dev->internal_end_block; i++) {
+ yaffs_query_init_block_state(dev, i, &state, &dummy);
+ if (state != YAFFS_BLOCK_STATE_DEAD)
+ yaffs_erase_block(dev, i);
+ }
+
+ return YAFFS_OK;
+}
+
+
+int yaffs_guts_initialise(struct yaffs_dev *dev)
+{
+ int init_failed = 0;
+ u32 x;
+ u32 bits;
+
+ if(yaffs_guts_ll_init(dev) != YAFFS_OK)
+ return YAFFS_FAIL;
+
+ if (dev->is_mounted) {
+ yaffs_trace(YAFFS_TRACE_ALWAYS, "device already mounted");
+ return YAFFS_FAIL;
+ }
+
+ dev->is_mounted = 1;
+
+ /* OK now calculate a few things for the device */
+
+ /*
+ * Calculate all the chunk size manipulation numbers:
+ */
+ x = dev->data_bytes_per_chunk;
+ /* We always use dev->chunk_shift and dev->chunk_div */
+ dev->chunk_shift = calc_shifts(x);
+ x >>= dev->chunk_shift;
+ dev->chunk_div = x;
+ /* We only use chunk mask if chunk_div is 1 */
+ dev->chunk_mask = (1 << dev->chunk_shift) - 1;
+
+ /*
+ * Calculate chunk_grp_bits.
+ * We need to find the next power of 2 > than internal_end_block
+ */
+
+ x = dev->param.chunks_per_block * (dev->internal_end_block + 1);
+
+ bits = calc_shifts_ceiling(x);
+
+ /* Set up tnode width if wide tnodes are enabled. */
+ if (!dev->param.wide_tnodes_disabled) {
+ /* bits must be even so that we end up with 32-bit words */
+ if (bits & 1)
+ bits++;
+ if (bits < 16)
+ dev->tnode_width = 16;
+ else
+ dev->tnode_width = bits;
+ } else {
+ dev->tnode_width = 16;
+ }
+
+ dev->tnode_mask = (1 << dev->tnode_width) - 1;
+
+ /* Level0 Tnodes are 16 bits or wider (if wide tnodes are enabled),
+ * so if the bitwidth of the
+ * chunk range we're using is greater than 16 we need
+ * to figure out chunk shift and chunk_grp_size
+ */
+
+ if (bits <= dev->tnode_width)
+ dev->chunk_grp_bits = 0;
+ else
+ dev->chunk_grp_bits = bits - dev->tnode_width;
+
+ dev->tnode_size = (dev->tnode_width * YAFFS_NTNODES_LEVEL0) / 8;
+ if (dev->tnode_size < sizeof(struct yaffs_tnode))
+ dev->tnode_size = sizeof(struct yaffs_tnode);
+
+ dev->chunk_grp_size = 1 << dev->chunk_grp_bits;
+
+ if (dev->param.chunks_per_block < dev->chunk_grp_size) {
+ /* We have a problem because the soft delete won't work if
+ * the chunk group size > chunks per block.
+ * This can be remedied by using larger "virtual blocks".
+ */
+ yaffs_trace(YAFFS_TRACE_ALWAYS, "chunk group too large");
+
+ return YAFFS_FAIL;
+ }
+
+ /* Finished verifying the device, continue with initialisation */
+
+ /* More device initialisation */
+ dev->all_gcs = 0;
+ dev->passive_gc_count = 0;
+ dev->oldest_dirty_gc_count = 0;
+ dev->bg_gcs = 0;
+ dev->gc_block_finder = 0;
+ dev->buffered_block = -1;
+ dev->doing_buffered_block_rewrite = 0;
+ dev->n_deleted_files = 0;
+ dev->n_bg_deletions = 0;
+ dev->n_unlinked_files = 0;
+ dev->n_ecc_fixed = 0;
+ dev->n_ecc_unfixed = 0;
+ dev->n_tags_ecc_fixed = 0;
+ dev->n_tags_ecc_unfixed = 0;
+ dev->n_erase_failures = 0;
+ dev->n_erased_blocks = 0;
+ dev->gc_disable = 0;
+ dev->has_pending_prioritised_gc = 1; /* Assume the worst for now,
+ * will get fixed on first GC */
+ INIT_LIST_HEAD(&dev->dirty_dirs);
+ dev->oldest_dirty_seq = 0;
+ dev->oldest_dirty_block = 0;
+
+ yaffs_endian_config(dev);
+
+ /* Initialise temporary buffers and caches. */
+ if (!yaffs_init_tmp_buffers(dev))
+ init_failed = 1;
+
+ dev->cache = NULL;
+ dev->gc_cleanup_list = NULL;
+
+ if (!init_failed && dev->param.n_caches > 0) {
+ u32 i;
+ void *buf;
+ u32 cache_bytes =
+ dev->param.n_caches * sizeof(struct yaffs_cache);
+
+ if (dev->param.n_caches > YAFFS_MAX_SHORT_OP_CACHES)
+ dev->param.n_caches = YAFFS_MAX_SHORT_OP_CACHES;
+
+ dev->cache = kmalloc(cache_bytes, GFP_NOFS);
+
+ buf = (u8 *) dev->cache;
+
+ if (dev->cache)
+ memset(dev->cache, 0, cache_bytes);
+
+ for (i = 0; i < dev->param.n_caches && buf; i++) {
+ dev->cache[i].object = NULL;
+ dev->cache[i].last_use = 0;
+ dev->cache[i].dirty = 0;
+ dev->cache[i].data = buf =
+ kmalloc(dev->param.total_bytes_per_chunk, GFP_NOFS);
+ }
+ if (!buf)
+ init_failed = 1;
+
+ dev->cache_last_use = 0;
+ }
+
+ dev->cache_hits = 0;
+
+ if (!init_failed) {
+ dev->gc_cleanup_list =
+ kmalloc(dev->param.chunks_per_block * sizeof(u32),
+ GFP_NOFS);
+ if (!dev->gc_cleanup_list)
+ init_failed = 1;
+ }
+
+ if (dev->param.is_yaffs2)
+ dev->param.use_header_file_size = 1;
+
+ if (!init_failed && !yaffs_init_blocks(dev))
+ init_failed = 1;
+
+ yaffs_init_tnodes_and_objs(dev);
+
+ if (!init_failed && !yaffs_create_initial_dir(dev))
+ init_failed = 1;
+
+ if (!init_failed && dev->param.is_yaffs2 &&
+ !dev->param.disable_summary &&
+ !yaffs_summary_init(dev))
+ init_failed = 1;
+
+ if (!init_failed) {
+ /* Now scan the flash. */
+ if (dev->param.is_yaffs2) {
+ if (yaffs2_checkpt_restore(dev)) {
+ yaffs_check_obj_details_loaded(dev->root_dir);
+ yaffs_trace(YAFFS_TRACE_CHECKPOINT |
+ YAFFS_TRACE_MOUNT,
+ "yaffs: restored from checkpoint"
+ );
+ } else {
+
+ /* Clean up the mess caused by an aborted
+ * checkpoint load then scan backwards.
+ */
+ yaffs_deinit_blocks(dev);
+
+ yaffs_deinit_tnodes_and_objs(dev);
+
+ dev->n_erased_blocks = 0;
+ dev->n_free_chunks = 0;
+ dev->alloc_block = -1;
+ dev->alloc_page = -1;
+ dev->n_deleted_files = 0;
+ dev->n_unlinked_files = 0;
+ dev->n_bg_deletions = 0;
+
+ if (!init_failed && !yaffs_init_blocks(dev))
+ init_failed = 1;
+
+ yaffs_init_tnodes_and_objs(dev);
+
+ if (!init_failed
+ && !yaffs_create_initial_dir(dev))
+ init_failed = 1;
+
+ if (!init_failed && !yaffs2_scan_backwards(dev))
+ init_failed = 1;
+ }
+ } else if (!yaffs1_scan(dev)) {
+ init_failed = 1;
+ }
+
+ yaffs_strip_deleted_objs(dev);
+ yaffs_fix_hanging_objs(dev);
+ if (dev->param.empty_lost_n_found)
+ yaffs_empty_l_n_f(dev);
+ }
+
+ if (init_failed) {
+ /* Clean up the mess */
+ yaffs_trace(YAFFS_TRACE_TRACING,
+ "yaffs: yaffs_guts_initialise() aborted.");
+
+ yaffs_deinitialise(dev);
+ return YAFFS_FAIL;
+ }
+
+ /* Zero out stats */
+ dev->n_page_reads = 0;
+ dev->n_page_writes = 0;
+ dev->n_erasures = 0;
+ dev->n_gc_copies = 0;
+ dev->n_retried_writes = 0;
+
+ dev->n_retired_blocks = 0;
+
+ yaffs_verify_free_chunks(dev);
+ yaffs_verify_blocks(dev);
+
+ /* Clean up any aborted checkpoint data */
+ if (!dev->is_checkpointed && dev->blocks_in_checkpt > 0)
+ yaffs2_checkpt_invalidate(dev);
+
+ yaffs_trace(YAFFS_TRACE_TRACING,
+ "yaffs: yaffs_guts_initialise() done.");
+ return YAFFS_OK;
+}
+
+void yaffs_deinitialise(struct yaffs_dev *dev)
+{
+ if (dev->is_mounted) {
+ u32 i;
+
+ yaffs_deinit_blocks(dev);
+ yaffs_deinit_tnodes_and_objs(dev);
+ yaffs_summary_deinit(dev);
+
+ if (dev->param.n_caches > 0 && dev->cache) {
+
+ for (i = 0; i < dev->param.n_caches; i++) {
+ kfree(dev->cache[i].data);
+ dev->cache[i].data = NULL;
+ }
+
+ kfree(dev->cache);
+ dev->cache = NULL;
+ }
+
+ kfree(dev->gc_cleanup_list);
+
+ for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
+ kfree(dev->temp_buffer[i].buffer);
+ dev->temp_buffer[i].buffer = NULL;
+ }
+
+ kfree(dev->checkpt_buffer);
+ dev->checkpt_buffer = NULL;
+ kfree(dev->checkpt_block_list);
+ dev->checkpt_block_list = NULL;
+
+ dev->is_mounted = 0;
+
+ yaffs_deinit_nand(dev);
+ }
+}
+
+int yaffs_count_free_chunks(struct yaffs_dev *dev)
+{
+ int n_free = 0;
+ u32 b;
+ struct yaffs_block_info *blk;
+
+ blk = dev->block_info;
+ for (b = dev->internal_start_block; b <= dev->internal_end_block; b++) {
+ switch (blk->block_state) {
+ case YAFFS_BLOCK_STATE_EMPTY:
+ case YAFFS_BLOCK_STATE_ALLOCATING:
+ case YAFFS_BLOCK_STATE_COLLECTING:
+ case YAFFS_BLOCK_STATE_FULL:
+ n_free +=
+ (dev->param.chunks_per_block - blk->pages_in_use +
+ blk->soft_del_pages);
+ break;
+ default:
+ break;
+ }
+ blk++;
+ }
+ return n_free;
+}
+
+int yaffs_get_n_free_chunks(struct yaffs_dev *dev)
+{
+ /* This is what we report to the outside world */
+ int n_free;
+ int n_dirty_caches;
+ int blocks_for_checkpt;
+ u32 i;
+
+ n_free = dev->n_free_chunks;
+ n_free += dev->n_deleted_files;
+
+ /* Now count and subtract the number of dirty chunks in the cache. */
+
+ for (n_dirty_caches = 0, i = 0; i < dev->param.n_caches; i++) {
+ if (dev->cache[i].dirty)
+ n_dirty_caches++;
+ }
+
+ n_free -= n_dirty_caches;
+
+ n_free -=
+ ((dev->param.n_reserved_blocks + 1) * dev->param.chunks_per_block);
+
+ /* Now figure checkpoint space and report that... */
+ blocks_for_checkpt = yaffs_calc_checkpt_blocks_required(dev);
+
+ n_free -= (blocks_for_checkpt * dev->param.chunks_per_block);
+
+ if (n_free < 0)
+ n_free = 0;
+
+ return n_free;
+}
+
+
+/*
+ * Marshalling functions to get loff_t file sizes into and out of
+ * object headers.
+ */
+void yaffs_oh_size_load(struct yaffs_dev *dev,
+ struct yaffs_obj_hdr *oh,
+ loff_t fsize,
+ int do_endian)
+{
+ oh->file_size_low = FSIZE_LOW(fsize);
+
+ oh->file_size_high = FSIZE_HIGH(fsize);
+
+ if (do_endian) {
+ yaffs_do_endian_u32(dev, &oh->file_size_low);
+ yaffs_do_endian_u32(dev, &oh->file_size_high);
+ }
+}
+
+loff_t yaffs_oh_to_size(struct yaffs_dev *dev, struct yaffs_obj_hdr *oh,
+ int do_endian)
+{
+ loff_t retval;
+
+
+ if (sizeof(loff_t) >= 8 && ~(oh->file_size_high)) {
+ u32 low = oh->file_size_low;
+ u32 high = oh->file_size_high;
+
+ if (do_endian) {
+ yaffs_do_endian_u32 (dev, &low);
+ yaffs_do_endian_u32 (dev, &high);
+ }
+ retval = FSIZE_COMBINE(high, low);
+ } else {
+ u32 low = oh->file_size_low;
+
+ if (do_endian)
+ yaffs_do_endian_u32(dev, &low);
+ retval = (loff_t)low;
+ }
+
+ return retval;
+}
+
+
+void yaffs_count_blocks_by_state(struct yaffs_dev *dev, int bs[10])
+{
+ u32 i;
+ struct yaffs_block_info *bi;
+ int s;
+
+ for(i = 0; i < 10; i++)
+ bs[i] = 0;
+
+ for(i = dev->internal_start_block; i <= dev->internal_end_block; i++) {
+ bi = yaffs_get_block_info(dev, i);
+ s = bi->block_state;
+ if(s > YAFFS_BLOCK_STATE_DEAD || s < YAFFS_BLOCK_STATE_UNKNOWN)
+ bs[0]++;
+ else
+ bs[s]++;
+ }
+}
diff -urN linux-4.9.37/fs/yaffs2/yaffs_guts.h linux-4.9.y/fs/yaffs2/yaffs_guts.h
--- linux-4.9.37/fs/yaffs2/yaffs_guts.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/yaffs_guts.h 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,1070 @@
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+#ifndef __YAFFS_GUTS_H__
+#define __YAFFS_GUTS_H__
+
+#include "yportenv.h"
+
+#define YAFFS_OK 1
+#define YAFFS_FAIL 0
+
+/* Give us a Y=0x59,
+ * Give us an A=0x41,
+ * Give us an FF=0xff
+ * Give us an S=0x53
+ * And what have we got...
+ */
+#define YAFFS_MAGIC 0x5941ff53
+
+/*
+ * Tnodes form a tree with the tnodes in "levels"
+ * Levels greater than 0 hold 8 slots which point to other tnodes.
+ * Those at level 0 hold 16 slots which point to chunks in NAND.
+ *
+ * A maximum level of 8 thust supports files of size up to:
+ *
+ * 2^(3*MAX_LEVEL+4)
+ *
+ * Thus a max level of 8 supports files with up to 2^^28 chunks which gives
+ * a maximum file size of around 512Gbytees with 2k chunks.
+ */
+#define YAFFS_NTNODES_LEVEL0 16
+#define YAFFS_TNODES_LEVEL0_BITS 4
+#define YAFFS_TNODES_LEVEL0_MASK 0xf
+
+#define YAFFS_NTNODES_INTERNAL (YAFFS_NTNODES_LEVEL0 / 2)
+#define YAFFS_TNODES_INTERNAL_BITS (YAFFS_TNODES_LEVEL0_BITS - 1)
+#define YAFFS_TNODES_INTERNAL_MASK 0x7
+#define YAFFS_TNODES_MAX_LEVEL 8
+#define YAFFS_TNODES_MAX_BITS (YAFFS_TNODES_LEVEL0_BITS + \
+ YAFFS_TNODES_INTERNAL_BITS * \
+ YAFFS_TNODES_MAX_LEVEL)
+#define YAFFS_MAX_CHUNK_ID ((1 << YAFFS_TNODES_MAX_BITS) - 1)
+
+#define YAFFS_MAX_FILE_SIZE_32 0x7fffffff
+
+/* Constants for YAFFS1 mode */
+#define YAFFS_BYTES_PER_SPARE 16
+#define YAFFS_BYTES_PER_CHUNK 512
+#define YAFFS_CHUNK_SIZE_SHIFT 9
+#define YAFFS_CHUNKS_PER_BLOCK 32
+#define YAFFS_BYTES_PER_BLOCK (YAFFS_CHUNKS_PER_BLOCK*YAFFS_BYTES_PER_CHUNK)
+
+#define YAFFS_MIN_YAFFS2_CHUNK_SIZE 1024
+#define YAFFS_MIN_YAFFS2_SPARE_SIZE 32
+
+
+
+#define YAFFS_ALLOCATION_NOBJECTS 100
+#define YAFFS_ALLOCATION_NTNODES 100
+#define YAFFS_ALLOCATION_NLINKS 100
+
+#define YAFFS_NOBJECT_BUCKETS 256
+
+#define YAFFS_OBJECT_SPACE 0x40000
+#define YAFFS_MAX_OBJECT_ID (YAFFS_OBJECT_SPACE - 1)
+
+/* Binary data version stamps */
+#define YAFFS_SUMMARY_VERSION 1
+
+#ifdef CONFIG_YAFFS_UNICODE
+#define YAFFS_MAX_NAME_LENGTH 127
+#define YAFFS_MAX_ALIAS_LENGTH 79
+#else
+#define YAFFS_MAX_NAME_LENGTH 255
+#define YAFFS_MAX_ALIAS_LENGTH 159
+#endif
+
+#define YAFFS_SHORT_NAME_LENGTH 15
+
+/* Some special object ids for pseudo objects */
+#define YAFFS_OBJECTID_ROOT 1
+#define YAFFS_OBJECTID_LOSTNFOUND 2
+#define YAFFS_OBJECTID_UNLINKED 3
+#define YAFFS_OBJECTID_DELETED 4
+
+/* Fake object Id for summary data */
+#define YAFFS_OBJECTID_SUMMARY 0x10
+
+/* Pseudo object ids for checkpointing */
+#define YAFFS_OBJECTID_CHECKPOINT_DATA 0x20
+#define YAFFS_SEQUENCE_CHECKPOINT_DATA 0x21
+
+#define YAFFS_MAX_SHORT_OP_CACHES 20
+
+#define YAFFS_N_TEMP_BUFFERS 6
+
+/* We limit the number attempts at sucessfully saving a chunk of data.
+ * Small-page devices have 32 pages per block; large-page devices have 64.
+ * Default to something in the order of 5 to 10 blocks worth of chunks.
+ */
+#define YAFFS_WR_ATTEMPTS (5*64)
+
+/* Sequence numbers are used in YAFFS2 to determine block allocation order.
+ * The range is limited slightly to help distinguish bad numbers from good.
+ * This also allows us to perhaps in the future use special numbers for
+ * special purposes.
+ * EFFFFF00 allows the allocation of 8 blocks/second (~1Mbytes) for 15 years,
+ * and is a larger number than the lifetime of a 2GB device.
+ */
+#define YAFFS_LOWEST_SEQUENCE_NUMBER 0x00001000
+#define YAFFS_HIGHEST_SEQUENCE_NUMBER 0xefffff00
+
+/* Special sequence number for bad block that failed to be marked bad */
+#define YAFFS_SEQUENCE_BAD_BLOCK 0xffff0000
+
+/* ChunkCache is used for short read/write operations.*/
+struct yaffs_cache {
+ struct yaffs_obj *object;
+ int chunk_id;
+ int last_use;
+ int dirty;
+ int n_bytes; /* Only valid if the cache is dirty */
+ int locked; /* Can't push out or flush while locked. */
+ u8 *data;
+};
+
+/* yaffs1 tags structures in RAM
+ * NB This uses bitfield. Bitfields should not straddle a u32 boundary
+ * otherwise the structure size will get blown out.
+ */
+
+struct yaffs_tags {
+ u32 chunk_id:20;
+ u32 serial_number:2;
+ u32 n_bytes_lsb:10;
+ u32 obj_id:18;
+ u32 ecc:12;
+ u32 n_bytes_msb:2;
+};
+
+union yaffs_tags_union {
+ struct yaffs_tags as_tags;
+ u8 as_bytes[8];
+ u32 as_u32[2];
+};
+
+
+/* Stuff used for extended tags in YAFFS2 */
+
+enum yaffs_ecc_result {
+ YAFFS_ECC_RESULT_UNKNOWN,
+ YAFFS_ECC_RESULT_NO_ERROR,
+ YAFFS_ECC_RESULT_FIXED,
+ YAFFS_ECC_RESULT_UNFIXED
+};
+
+/*
+ * Object type enum:
+ * When this is stored in flash we store it as a u32 instead
+ * to prevent any alignment change issues as compiler variants change.
+ */
+
+enum yaffs_obj_type {
+ YAFFS_OBJECT_TYPE_UNKNOWN,
+ YAFFS_OBJECT_TYPE_FILE,
+ YAFFS_OBJECT_TYPE_SYMLINK,
+ YAFFS_OBJECT_TYPE_DIRECTORY,
+ YAFFS_OBJECT_TYPE_HARDLINK,
+ YAFFS_OBJECT_TYPE_SPECIAL
+};
+
+#define YAFFS_OBJECT_TYPE_MAX YAFFS_OBJECT_TYPE_SPECIAL
+
+struct yaffs_ext_tags {
+ unsigned chunk_used; /* Status of the chunk: used or unused */
+ unsigned obj_id; /* If 0 this is not used */
+ unsigned chunk_id; /* If 0 this is a header, else a data chunk */
+ unsigned n_bytes; /* Only valid for data chunks */
+
+ /* The following stuff only has meaning when we read */
+ enum yaffs_ecc_result ecc_result;
+ unsigned block_bad;
+
+ /* YAFFS 1 stuff */
+ unsigned is_deleted; /* The chunk is marked deleted */
+ unsigned serial_number; /* Yaffs1 2-bit serial number */
+
+ /* YAFFS2 stuff */
+ unsigned seq_number; /* The sequence number of this block */
+
+ /* Extra info if this is an object header (YAFFS2 only) */
+
+ unsigned extra_available; /* Extra info available if not zero */
+ unsigned extra_parent_id; /* The parent object */
+ unsigned extra_is_shrink; /* Is it a shrink header? */
+ unsigned extra_shadows; /* Does this shadow another object? */
+
+ enum yaffs_obj_type extra_obj_type; /* What object type? */
+
+ loff_t extra_file_size; /* Length if it is a file */
+ unsigned extra_equiv_id; /* Equivalent object for a hard link */
+};
+
+/* Spare structure for YAFFS1 */
+struct yaffs_spare {
+ u8 tb0;
+ u8 tb1;
+ u8 tb2;
+ u8 tb3;
+ u8 page_status; /* set to 0 to delete the chunk */
+ u8 block_status;
+ u8 tb4;
+ u8 tb5;
+ u8 ecc1[3];
+ u8 tb6;
+ u8 tb7;
+ u8 ecc2[3];
+};
+
+/*Special structure for passing through to mtd */
+struct yaffs_nand_spare {
+ struct yaffs_spare spare;
+ int eccres1;
+ int eccres2;
+};
+
+/* Block data in RAM */
+
+enum yaffs_block_state {
+ YAFFS_BLOCK_STATE_UNKNOWN = 0,
+
+ YAFFS_BLOCK_STATE_SCANNING,
+ /* Being scanned */
+
+ YAFFS_BLOCK_STATE_NEEDS_SCAN,
+ /* The block might have something on it (ie it is allocating or full,
+ * perhaps empty) but it needs to be scanned to determine its true
+ * state.
+ * This state is only valid during scanning.
+ * NB We tolerate empty because the pre-scanner might be incapable of
+ * deciding
+ * However, if this state is returned on a YAFFS2 device,
+ * then we expect a sequence number
+ */
+
+ YAFFS_BLOCK_STATE_EMPTY,
+ /* This block is empty */
+
+ YAFFS_BLOCK_STATE_ALLOCATING,
+ /* This block is partially allocated.
+ * At least one page holds valid data.
+ * This is the one currently being used for page
+ * allocation. Should never be more than one of these.
+ * If a block is only partially allocated at mount it is treated as
+ * full.
+ */
+
+ YAFFS_BLOCK_STATE_FULL,
+ /* All the pages in this block have been allocated.
+ * If a block was only partially allocated when mounted we treat
+ * it as fully allocated.
+ */
+
+ YAFFS_BLOCK_STATE_DIRTY,
+ /* The block was full and now all chunks have been deleted.
+ * Erase me, reuse me.
+ */
+
+ YAFFS_BLOCK_STATE_CHECKPOINT,
+ /* This block is assigned to holding checkpoint data. */
+
+ YAFFS_BLOCK_STATE_COLLECTING,
+ /* This block is being garbage collected */
+
+ YAFFS_BLOCK_STATE_DEAD
+ /* This block has failed and is not in use */
+};
+
+#define YAFFS_NUMBER_OF_BLOCK_STATES (YAFFS_BLOCK_STATE_DEAD + 1)
+
+struct yaffs_block_info {
+
+ s32 soft_del_pages:10; /* number of soft deleted pages */
+ s32 pages_in_use:10; /* number of pages in use */
+ u32 block_state:4; /* One of the above block states. */
+ /* NB use unsigned because enum is sometimes
+ * an int */
+ u32 needs_retiring:1; /* Data has failed on this block, */
+ /*need to get valid data off and retire*/
+ u32 skip_erased_check:1;/* Skip the erased check on this block */
+ u32 gc_prioritise:1; /* An ECC check or blank check has failed.
+ Block should be prioritised for GC */
+ u32 chunk_error_strikes:3; /* How many times we've had ecc etc
+ failures on this block and tried to reuse it */
+ u32 has_summary:1; /* The block has a summary */
+
+ u32 has_shrink_hdr:1; /* This block has at least one shrink header */
+ u32 seq_number; /* block sequence number for yaffs2 */
+
+};
+
+union yaffs_block_info_union {
+ struct yaffs_block_info bi;
+ u32 as_u32[2];
+};
+
+/* -------------------------- Object structure -------------------------------*/
+/* This is the object structure as stored on NAND */
+
+struct yaffs_obj_hdr {
+ u32 type; /* enum yaffs_obj_type */
+
+ /* Apply to everything */
+ u32 parent_obj_id;
+ u16 sum_no_longer_used; /* checksum of name. No longer used */
+ YCHAR name[YAFFS_MAX_NAME_LENGTH + 1];
+
+ /* The following apply to all object types except for hard links */
+ u32 yst_mode; /* protection */
+
+ u32 yst_uid;
+ u32 yst_gid;
+ u32 yst_atime;
+ u32 yst_mtime;
+ u32 yst_ctime;
+
+ /* File size applies to files only */
+ u32 file_size_low;
+
+ /* Equivalent object id applies to hard links only. */
+ int equiv_id;
+
+ /* Alias is for symlinks only. */
+ YCHAR alias[YAFFS_MAX_ALIAS_LENGTH + 1];
+
+ u32 yst_rdev; /* stuff for block and char devices (major/min) */
+
+ u32 win_ctime[2];
+ u32 win_atime[2];
+ u32 win_mtime[2];
+
+ u32 inband_shadowed_obj_id;
+ u32 inband_is_shrink;
+
+ u32 file_size_high;
+ u32 reserved[1];
+ int shadows_obj; /* This object header shadows the
+ specified object if > 0 */
+
+ /* is_shrink applies to object headers written when wemake a hole. */
+ u32 is_shrink;
+
+};
+
+/*--------------------------- Tnode -------------------------- */
+
+struct yaffs_tnode {
+ struct yaffs_tnode *internal[YAFFS_NTNODES_INTERNAL];
+};
+
+/*------------------------ Object -----------------------------*/
+/* An object can be one of:
+ * - a directory (no data, has children links
+ * - a regular file (data.... not prunes :->).
+ * - a symlink [symbolic link] (the alias).
+ * - a hard link
+ */
+
+/* The file variant has three file sizes:
+ * - file_size : size of file as written into Yaffs - including data in cache.
+ * - stored_size - size of file as stored on media.
+ * - shrink_size - size of file that has been shrunk back to.
+ *
+ * The stored_size and file_size might be different because the data written
+ * into the cache will increase the file_size but the stored_size will only
+ * change when the data is actually stored.
+ *
+ */
+struct yaffs_file_var {
+ loff_t file_size;
+ loff_t stored_size;
+ loff_t shrink_size;
+ int top_level;
+ struct yaffs_tnode *top;
+};
+
+struct yaffs_dir_var {
+ struct list_head children; /* list of child links */
+ struct list_head dirty; /* Entry for list of dirty directories */
+};
+
+struct yaffs_symlink_var {
+ YCHAR *alias;
+};
+
+struct yaffs_hardlink_var {
+ struct yaffs_obj *equiv_obj;
+ u32 equiv_id;
+};
+
+union yaffs_obj_var {
+ struct yaffs_file_var file_variant;
+ struct yaffs_dir_var dir_variant;
+ struct yaffs_symlink_var symlink_variant;
+ struct yaffs_hardlink_var hardlink_variant;
+};
+
+struct yaffs_obj {
+ u8 deleted:1; /* This should only apply to unlinked files. */
+ u8 soft_del:1; /* it has also been soft deleted */
+ u8 unlinked:1; /* An unlinked file.*/
+ u8 fake:1; /* A fake object has no presence on NAND. */
+ u8 rename_allowed:1; /* Some objects cannot be renamed. */
+ u8 unlink_allowed:1;
+ u8 dirty:1; /* the object needs to be written to flash */
+ u8 valid:1; /* When the file system is being loaded up, this
+ * object might be created before the data
+ * is available
+ * ie. file data chunks encountered before
+ * the header.
+ */
+ u8 lazy_loaded:1; /* This object has been lazy loaded and
+ * is missing some detail */
+
+ u8 defered_free:1; /* Object is removed from NAND, but is
+ * still in the inode cache.
+ * Free of object is defered.
+ * until the inode is released.
+ */
+ u8 being_created:1; /* This object is still being created
+ * so skip some verification checks. */
+ u8 is_shadowed:1; /* This object is shadowed on the way
+ * to being renamed. */
+
+ u8 xattr_known:1; /* We know if this has object has xattribs
+ * or not. */
+ u8 has_xattr:1; /* This object has xattribs.
+ * Only valid if xattr_known. */
+
+ u8 serial; /* serial number of chunk in NAND.*/
+ u16 sum; /* sum of the name to speed searching */
+
+ struct yaffs_dev *my_dev; /* The device I'm on */
+
+ struct list_head hash_link; /* list of objects in hash bucket */
+
+ struct list_head hard_links; /* hard linked object chain*/
+
+ /* directory structure stuff */
+ /* also used for linking up the free list */
+ struct yaffs_obj *parent;
+ struct list_head siblings;
+
+ /* Where's my object header in NAND? */
+ int hdr_chunk;
+
+ int n_data_chunks; /* Number of data chunks for this file. */
+
+ u32 obj_id; /* the object id value */
+
+ u32 yst_mode;
+
+ YCHAR short_name[YAFFS_SHORT_NAME_LENGTH + 1];
+
+#ifdef CONFIG_YAFFS_WINCE
+ u32 win_ctime[2];
+ u32 win_mtime[2];
+ u32 win_atime[2];
+#else
+ u32 yst_uid;
+ u32 yst_gid;
+ u32 yst_atime;
+ u32 yst_mtime;
+ u32 yst_ctime;
+#endif
+
+ u32 yst_rdev;
+
+ void *my_inode;
+
+ u32 variant_type; /* enum yaffs_object_type */
+
+ union yaffs_obj_var variant;
+
+};
+
+struct yaffs_obj_bucket {
+ struct list_head list;
+ int count;
+};
+
+
+/*--------------------- Temporary buffers ----------------
+ *
+ * These are chunk-sized working buffers. Each device has a few.
+ */
+
+struct yaffs_buffer {
+ u8 *buffer;
+ int in_use;
+};
+
+/*----------------- Device ---------------------------------*/
+
+struct yaffs_param {
+ const YCHAR *name;
+
+ /*
+ * Entry parameters set up way early. Yaffs sets up the rest.
+ * The structure should be zeroed out before use so that unused
+ * and default values are zero.
+ */
+
+ int inband_tags; /* Use unband tags */
+ u32 total_bytes_per_chunk; /* Should be >= 512, does not need to
+ be a power of 2 */
+ u32 chunks_per_block; /* does not need to be a power of 2 */
+ u32 spare_bytes_per_chunk; /* spare area size */
+ u32 start_block; /* Start block we're allowed to use */
+ u32 end_block; /* End block we're allowed to use */
+ u32 n_reserved_blocks; /* Tuneable so that we can reduce
+ * reserved blocks on NOR and RAM. */
+
+ u32 n_caches; /* If == 0, then short op caching is disabled,
+ * else the number of short op caches.
+ */
+ int cache_bypass_aligned; /* If non-zero then bypass the cache for
+ * aligned writes.
+ */
+
+ int use_nand_ecc; /* Flag to decide whether or not to use
+ * NAND driver ECC on data (yaffs1) */
+ int tags_9bytes; /* Use 9 byte tags */
+ int no_tags_ecc; /* Flag to decide whether or not to do ECC
+ * on packed tags (yaffs2) */
+
+ int is_yaffs2; /* Use yaffs2 mode on this device */
+
+ int empty_lost_n_found; /* Auto-empty lost+found directory on mount */
+
+ int refresh_period; /* How often to check for a block refresh */
+
+ /* Checkpoint control. Can be set before or after initialisation */
+ u8 skip_checkpt_rd;
+ u8 skip_checkpt_wr;
+
+ int enable_xattr; /* Enable xattribs */
+
+ int max_objects; /*
+ * Set to limit the number of objects created.
+ * 0 = no limit.
+ */
+
+ int hide_lost_n_found; /* Set non-zero to hide the lost-n-found dir. */
+
+ int stored_endian; /* 0=cpu endian, 1=little endian, 2=big endian */
+
+ /* The remove_obj_fn function must be supplied by OS flavours that
+ * need it.
+ * yaffs direct uses it to implement the faster readdir.
+ * Linux uses it to protect the directory during unlocking.
+ */
+ void (*remove_obj_fn) (struct yaffs_obj *obj);
+
+ /* Callback to mark the superblock dirty */
+ void (*sb_dirty_fn) (struct yaffs_dev *dev);
+
+ /* Callback to control garbage collection. */
+ unsigned (*gc_control_fn) (struct yaffs_dev *dev);
+
+ /* Debug control flags. Don't use unless you know what you're doing */
+ int use_header_file_size; /* Flag to determine if we should use
+ * file sizes from the header */
+ int disable_lazy_load; /* Disable lazy loading on this device */
+ int wide_tnodes_disabled; /* Set to disable wide tnodes */
+ int disable_soft_del; /* yaffs 1 only: Set to disable the use of
+ * softdeletion. */
+
+ int defered_dir_update; /* Set to defer directory updates */
+
+#ifdef CONFIG_YAFFS_AUTO_UNICODE
+ int auto_unicode;
+#endif
+ int always_check_erased; /* Force chunk erased check always on */
+
+ int disable_summary;
+ int disable_bad_block_marking;
+
+};
+
+struct yaffs_driver {
+ int (*drv_write_chunk_fn) (struct yaffs_dev *dev, int nand_chunk,
+ const u8 *data, int data_len,
+ const u8 *oob, int oob_len);
+ int (*drv_read_chunk_fn) (struct yaffs_dev *dev, int nand_chunk,
+ u8 *data, int data_len,
+ u8 *oob, int oob_len,
+ enum yaffs_ecc_result *ecc_result);
+ int (*drv_erase_fn) (struct yaffs_dev *dev, int block_no);
+ int (*drv_mark_bad_fn) (struct yaffs_dev *dev, int block_no);
+ int (*drv_check_bad_fn) (struct yaffs_dev *dev, int block_no);
+ int (*drv_initialise_fn) (struct yaffs_dev *dev);
+ int (*drv_deinitialise_fn) (struct yaffs_dev *dev);
+};
+
+struct yaffs_tags_handler {
+ int (*write_chunk_tags_fn) (struct yaffs_dev *dev,
+ int nand_chunk, const u8 *data,
+ const struct yaffs_ext_tags *tags);
+ int (*read_chunk_tags_fn) (struct yaffs_dev *dev,
+ int nand_chunk, u8 *data,
+ struct yaffs_ext_tags *tags);
+
+ int (*query_block_fn) (struct yaffs_dev *dev, int block_no,
+ enum yaffs_block_state *state,
+ u32 *seq_number);
+ int (*mark_bad_fn) (struct yaffs_dev *dev, int block_no);
+};
+
+struct yaffs_dev {
+ struct yaffs_param param;
+ struct yaffs_driver drv;
+ struct yaffs_tags_handler tagger;
+
+ /* Context storage. Holds extra OS specific data for this device */
+
+ void *os_context;
+ void *driver_context;
+
+ struct list_head dev_list;
+
+ int ll_init;
+ /* Runtime parameters. Set up by YAFFS. */
+ u32 data_bytes_per_chunk;
+
+ /* Non-wide tnode stuff */
+ u16 chunk_grp_bits; /* Number of bits that need to be resolved if
+ * the tnodes are not wide enough.
+ */
+ u16 chunk_grp_size; /* == 2^^chunk_grp_bits */
+
+ struct yaffs_tnode *tn_swap_buffer;
+
+ /* Stuff to support wide tnodes */
+ u32 tnode_width;
+ u32 tnode_mask;
+ u32 tnode_size;
+
+ /* Stuff for figuring out file offset to chunk conversions */
+ u32 chunk_shift; /* Shift value */
+ u32 chunk_div; /* Divisor after shifting: 1 for 2^n sizes */
+ u32 chunk_mask; /* Mask to use for power-of-2 case */
+
+ int is_mounted;
+ int read_only;
+ int is_checkpointed;
+ int swap_endian; /* Stored endian needs endian swap. */
+
+ /* Stuff to support block offsetting to support start block zero */
+ u32 internal_start_block;
+ u32 internal_end_block;
+ int block_offset;
+ int chunk_offset;
+
+ /* Runtime checkpointing stuff */
+ int checkpt_page_seq; /* running sequence number of checkpt pages */
+ int checkpt_byte_count;
+ int checkpt_byte_offs;
+ u8 *checkpt_buffer;
+ int checkpt_open_write;
+ u32 blocks_in_checkpt;
+ int checkpt_cur_chunk;
+ int checkpt_cur_block;
+ int checkpt_next_block;
+ int *checkpt_block_list;
+ u32 checkpt_max_blocks;
+ u32 checkpt_sum;
+ u32 checkpt_xor;
+
+ int checkpoint_blocks_required; /* Number of blocks needed to store
+ * current checkpoint set */
+
+ /* Block Info */
+ struct yaffs_block_info *block_info;
+ u8 *chunk_bits; /* bitmap of chunks in use */
+ u8 block_info_alt:1; /* allocated using alternative alloc */
+ u8 chunk_bits_alt:1; /* allocated using alternative alloc */
+ int chunk_bit_stride; /* Number of bytes of chunk_bits per block.
+ * Must be consistent with chunks_per_block.
+ */
+
+ int n_erased_blocks;
+ int alloc_block; /* Current block being allocated off */
+ u32 alloc_page;
+ int alloc_block_finder; /* Used to search for next allocation block */
+
+ /* Object and Tnode memory management */
+ void *allocator;
+ int n_obj;
+ int n_tnodes;
+
+ int n_hardlinks;
+
+ struct yaffs_obj_bucket obj_bucket[YAFFS_NOBJECT_BUCKETS];
+ u32 bucket_finder;
+
+ int n_free_chunks;
+
+ /* Garbage collection control */
+ u32 *gc_cleanup_list; /* objects to delete at the end of a GC. */
+ u32 n_clean_ups;
+
+ unsigned has_pending_prioritised_gc; /* We think this device might
+ have pending prioritised gcs */
+ unsigned gc_disable;
+ unsigned gc_block_finder;
+ unsigned gc_dirtiest;
+ unsigned gc_pages_in_use;
+ unsigned gc_not_done;
+ unsigned gc_block;
+ unsigned gc_chunk;
+ unsigned gc_skip;
+ struct yaffs_summary_tags *gc_sum_tags;
+
+ /* Special directories */
+ struct yaffs_obj *root_dir;
+ struct yaffs_obj *lost_n_found;
+
+ int buffered_block; /* Which block is buffered here? */
+ int doing_buffered_block_rewrite;
+
+ struct yaffs_cache *cache;
+ int cache_last_use;
+
+ /* Stuff for background deletion and unlinked files. */
+ struct yaffs_obj *unlinked_dir; /* Directory where unlinked and deleted
+ files live. */
+ struct yaffs_obj *del_dir; /* Directory where deleted objects are
+ sent to disappear. */
+ struct yaffs_obj *unlinked_deletion; /* Current file being
+ background deleted. */
+ int n_deleted_files; /* Count of files awaiting deletion; */
+ int n_unlinked_files; /* Count of unlinked files. */
+ int n_bg_deletions; /* Count of background deletions. */
+
+ /* Temporary buffer management */
+ struct yaffs_buffer temp_buffer[YAFFS_N_TEMP_BUFFERS];
+ int max_temp;
+ int temp_in_use;
+ int unmanaged_buffer_allocs;
+ int unmanaged_buffer_deallocs;
+
+ /* yaffs2 runtime stuff */
+ unsigned seq_number; /* Sequence number of currently
+ allocating block */
+ unsigned oldest_dirty_seq;
+ unsigned oldest_dirty_block;
+
+ /* Block refreshing */
+ int refresh_skip; /* A skip down counter.
+ * Refresh happens when this gets to zero. */
+
+ /* Dirty directory handling */
+ struct list_head dirty_dirs; /* List of dirty directories */
+
+ /* Summary */
+ int chunks_per_summary;
+ struct yaffs_summary_tags *sum_tags;
+
+ /* Statistics */
+ u32 n_page_writes;
+ u32 n_page_reads;
+ u32 n_erasures;
+ u32 n_bad_queries;
+ u32 n_bad_markings;
+ u32 n_erase_failures;
+ u32 n_gc_copies;
+ u32 all_gcs;
+ u32 passive_gc_count;
+ u32 oldest_dirty_gc_count;
+ u32 n_gc_blocks;
+ u32 bg_gcs;
+ u32 n_retried_writes;
+ u32 n_retired_blocks;
+ u32 n_ecc_fixed;
+ u32 n_ecc_unfixed;
+ u32 n_tags_ecc_fixed;
+ u32 n_tags_ecc_unfixed;
+ u32 n_deletions;
+ u32 n_unmarked_deletions;
+ u32 refresh_count;
+ u32 cache_hits;
+ u32 tags_used;
+ u32 summary_used;
+
+};
+
+/*
+ * Checkpointing definitions.
+ */
+
+#define YAFFS_CHECKPOINT_VERSION 8
+
+/* yaffs_checkpt_obj holds the definition of an object as dumped
+ * by checkpointing.
+ */
+
+
+/* Checkpint object bits in bitfield: offset, length */
+#define CHECKPOINT_VARIANT_BITS 0, 3
+#define CHECKPOINT_DELETED_BITS 3, 1
+#define CHECKPOINT_SOFT_DEL_BITS 4, 1
+#define CHECKPOINT_UNLINKED_BITS 5, 1
+#define CHECKPOINT_FAKE_BITS 6, 1
+#define CHECKPOINT_RENAME_ALLOWED_BITS 7, 1
+#define CHECKPOINT_UNLINK_ALLOWED_BITS 8, 1
+#define CHECKPOINT_SERIAL_BITS 9, 8
+
+struct yaffs_checkpt_obj {
+ int struct_type;
+ u32 obj_id;
+ u32 parent_id;
+ int hdr_chunk;
+ u32 bit_field;
+ int n_data_chunks;
+ loff_t size_or_equiv_obj;
+};
+
+/* The CheckpointDevice structure holds the device information that changes
+ *at runtime and must be preserved over unmount/mount cycles.
+ */
+struct yaffs_checkpt_dev {
+ int struct_type;
+ int n_erased_blocks;
+ int alloc_block; /* Current block being allocated off */
+ u32 alloc_page;
+ int n_free_chunks;
+
+ int n_deleted_files; /* Count of files awaiting deletion; */
+ int n_unlinked_files; /* Count of unlinked files. */
+ int n_bg_deletions; /* Count of background deletions. */
+
+ /* yaffs2 runtime stuff */
+ unsigned seq_number; /* Sequence number of currently
+ * allocating block */
+
+};
+
+struct yaffs_checkpt_validity {
+ int struct_type;
+ u32 magic;
+ u32 version;
+ u32 head;
+};
+
+struct yaffs_shadow_fixer {
+ int obj_id;
+ int shadowed_id;
+ struct yaffs_shadow_fixer *next;
+};
+
+/* Structure for doing xattr modifications */
+struct yaffs_xattr_mod {
+ int set; /* If 0 then this is a deletion */
+ const YCHAR *name;
+ const void *data;
+ int size;
+ int flags;
+ int result;
+};
+
+/*----------------------- YAFFS Functions -----------------------*/
+
+int yaffs_guts_initialise(struct yaffs_dev *dev);
+void yaffs_deinitialise(struct yaffs_dev *dev);
+
+int yaffs_get_n_free_chunks(struct yaffs_dev *dev);
+
+int yaffs_rename_obj(struct yaffs_obj *old_dir, const YCHAR * old_name,
+ struct yaffs_obj *new_dir, const YCHAR * new_name);
+
+int yaffs_unlink_obj(struct yaffs_obj *obj);
+
+int yaffs_unlinker(struct yaffs_obj *dir, const YCHAR * name);
+int yaffs_del_obj(struct yaffs_obj *obj);
+struct yaffs_obj *yaffs_retype_obj(struct yaffs_obj *obj,
+ enum yaffs_obj_type type);
+
+
+int yaffs_get_obj_name(struct yaffs_obj *obj, YCHAR * name, int buffer_size);
+loff_t yaffs_get_obj_length(struct yaffs_obj *obj);
+int yaffs_get_obj_inode(struct yaffs_obj *obj);
+unsigned yaffs_get_obj_type(struct yaffs_obj *obj);
+int yaffs_get_obj_link_count(struct yaffs_obj *obj);
+
+/* File operations */
+int yaffs_file_rd(struct yaffs_obj *obj, u8 * buffer, loff_t offset,
+ int n_bytes);
+int yaffs_wr_file(struct yaffs_obj *obj, const u8 * buffer, loff_t offset,
+ int n_bytes, int write_trhrough);
+int yaffs_resize_file(struct yaffs_obj *obj, loff_t new_size);
+
+struct yaffs_obj *yaffs_create_file(struct yaffs_obj *parent,
+ const YCHAR *name, u32 mode, u32 uid,
+ u32 gid);
+
+int yaffs_flush_file(struct yaffs_obj *in,
+ int update_time,
+ int data_sync,
+ int discard_cache);
+
+/* Flushing and checkpointing */
+void yaffs_flush_whole_cache(struct yaffs_dev *dev, int discard);
+
+int yaffs_checkpoint_save(struct yaffs_dev *dev);
+int yaffs_checkpoint_restore(struct yaffs_dev *dev);
+
+/* Directory operations */
+struct yaffs_obj *yaffs_create_dir(struct yaffs_obj *parent, const YCHAR *name,
+ u32 mode, u32 uid, u32 gid);
+struct yaffs_obj *yaffs_find_by_name(struct yaffs_obj *the_dir,
+ const YCHAR *name);
+struct yaffs_obj *yaffs_find_by_number(struct yaffs_dev *dev, u32 number);
+
+/* Link operations */
+struct yaffs_obj *yaffs_link_obj(struct yaffs_obj *parent, const YCHAR *name,
+ struct yaffs_obj *equiv_obj);
+
+struct yaffs_obj *yaffs_get_equivalent_obj(struct yaffs_obj *obj);
+
+/* Symlink operations */
+struct yaffs_obj *yaffs_create_symlink(struct yaffs_obj *parent,
+ const YCHAR *name, u32 mode, u32 uid,
+ u32 gid, const YCHAR *alias);
+YCHAR *yaffs_get_symlink_alias(struct yaffs_obj *obj);
+
+/* Special inodes (fifos, sockets and devices) */
+struct yaffs_obj *yaffs_create_special(struct yaffs_obj *parent,
+ const YCHAR *name, u32 mode, u32 uid,
+ u32 gid, u32 rdev);
+
+int yaffs_set_xattrib(struct yaffs_obj *obj, const YCHAR *name,
+ const void *value, int size, int flags);
+int yaffs_get_xattrib(struct yaffs_obj *obj, const YCHAR *name, void *value,
+ int size);
+int yaffs_list_xattrib(struct yaffs_obj *obj, char *buffer, int size);
+int yaffs_remove_xattrib(struct yaffs_obj *obj, const YCHAR *name);
+
+/* Special directories */
+struct yaffs_obj *yaffs_root(struct yaffs_dev *dev);
+struct yaffs_obj *yaffs_lost_n_found(struct yaffs_dev *dev);
+
+void yaffs_handle_defered_free(struct yaffs_obj *obj);
+
+void yaffs_update_dirty_dirs(struct yaffs_dev *dev);
+
+int yaffs_bg_gc(struct yaffs_dev *dev, unsigned urgency);
+
+/* Debug dump */
+int yaffs_dump_obj(struct yaffs_obj *obj);
+
+void yaffs_guts_test(struct yaffs_dev *dev);
+int yaffs_guts_ll_init(struct yaffs_dev *dev);
+
+
+/* A few useful functions to be used within the core files*/
+void yaffs_chunk_del(struct yaffs_dev *dev, int chunk_id, int mark_flash,
+ int lyn);
+int yaffs_check_ff(u8 *buffer, int n_bytes);
+void yaffs_handle_chunk_error(struct yaffs_dev *dev,
+ struct yaffs_block_info *bi);
+
+u8 *yaffs_get_temp_buffer(struct yaffs_dev *dev);
+void yaffs_release_temp_buffer(struct yaffs_dev *dev, u8 *buffer);
+
+struct yaffs_obj *yaffs_find_or_create_by_number(struct yaffs_dev *dev,
+ int number,
+ enum yaffs_obj_type type);
+int yaffs_put_chunk_in_file(struct yaffs_obj *in, int inode_chunk,
+ int nand_chunk, int in_scan);
+void yaffs_set_obj_name(struct yaffs_obj *obj, const YCHAR *name);
+void yaffs_set_obj_name_from_oh(struct yaffs_obj *obj,
+ const struct yaffs_obj_hdr *oh);
+void yaffs_add_obj_to_dir(struct yaffs_obj *directory, struct yaffs_obj *obj);
+YCHAR *yaffs_clone_str(const YCHAR *str);
+void yaffs_link_fixup(struct yaffs_dev *dev, struct list_head *hard_list);
+void yaffs_block_became_dirty(struct yaffs_dev *dev, int block_no);
+int yaffs_update_oh(struct yaffs_obj *in, const YCHAR *name,
+ int force, int is_shrink, int shadows,
+ struct yaffs_xattr_mod *xop);
+void yaffs_handle_shadowed_obj(struct yaffs_dev *dev, int obj_id,
+ int backward_scanning);
+int yaffs_check_alloc_available(struct yaffs_dev *dev, int n_chunks);
+struct yaffs_tnode *yaffs_get_tnode(struct yaffs_dev *dev);
+struct yaffs_tnode *yaffs_add_find_tnode_0(struct yaffs_dev *dev,
+ struct yaffs_file_var *file_struct,
+ u32 chunk_id,
+ struct yaffs_tnode *passed_tn);
+
+int yaffs_do_file_wr(struct yaffs_obj *in, const u8 *buffer, loff_t offset,
+ int n_bytes, int write_trhrough);
+void yaffs_resize_file_down(struct yaffs_obj *obj, loff_t new_size);
+void yaffs_skip_rest_of_block(struct yaffs_dev *dev);
+
+int yaffs_count_free_chunks(struct yaffs_dev *dev);
+
+struct yaffs_tnode *yaffs_find_tnode_0(struct yaffs_dev *dev,
+ struct yaffs_file_var *file_struct,
+ u32 chunk_id);
+
+u32 yaffs_get_group_base(struct yaffs_dev *dev, struct yaffs_tnode *tn,
+ unsigned pos);
+
+int yaffs_is_non_empty_dir(struct yaffs_obj *obj);
+
+int yaffs_guts_format_dev(struct yaffs_dev *dev);
+
+void yaffs_addr_to_chunk(struct yaffs_dev *dev, loff_t addr,
+ int *chunk_out, u32 *offset_out);
+/*
+ * Marshalling functions to get loff_t file sizes into and out of
+ * object headers.
+ */
+void yaffs_oh_size_load(struct yaffs_dev *dev, struct yaffs_obj_hdr *oh,
+ loff_t fsize, int do_endian);
+loff_t yaffs_oh_to_size(struct yaffs_dev *dev, struct yaffs_obj_hdr *oh,
+ int do_endian);
+loff_t yaffs_max_file_size(struct yaffs_dev *dev);
+
+/*
+ * Debug function to count number of blocks in each state
+ * NB Needs to be called with correct number of integers
+ */
+
+void yaffs_count_blocks_by_state(struct yaffs_dev *dev, int bs[10]);
+
+int yaffs_find_chunk_in_file(struct yaffs_obj *in, int inode_chunk,
+ struct yaffs_ext_tags *tags);
+
+/*
+ * Define LOFF_T_32_BIT if a 32-bit LOFF_T is being used.
+ * Not serious if you get this wrong - you might just get some warnings.
+*/
+
+#ifdef LOFF_T_32_BIT
+#define FSIZE_LOW(fsize) (fsize)
+#define FSIZE_HIGH(fsize) 0
+#define FSIZE_COMBINE(high, low) (low)
+#else
+#define FSIZE_LOW(fsize) ((fsize) & 0xffffffff)
+#define FSIZE_HIGH(fsize)(((fsize) >> 32) & 0xffffffff)
+#define FSIZE_COMBINE(high, low) ((((loff_t) (high)) << 32) | \
+ (((loff_t) (low)) & 0xFFFFFFFF))
+#endif
+
+
+#endif
diff -urN linux-4.9.37/fs/yaffs2/yaffs_linux.h linux-4.9.y/fs/yaffs2/yaffs_linux.h
--- linux-4.9.37/fs/yaffs2/yaffs_linux.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/yaffs_linux.h 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,48 @@
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+#ifndef __YAFFS_LINUX_H__
+#define __YAFFS_LINUX_H__
+
+#include "yportenv.h"
+
+struct yaffs_linux_context {
+ struct list_head context_list; /* List of these we have mounted */
+ struct yaffs_dev *dev;
+ struct super_block *super;
+ struct task_struct *bg_thread; /* Background thread for this device */
+ int bg_running;
+ struct mutex gross_lock; /* Gross locking mutex*/
+ u8 *spare_buffer; /* For mtdif2 use. Don't know the buffer size
+ * at compile time so we have to allocate it.
+ */
+ struct list_head search_contexts;
+ struct task_struct *readdir_process;
+ unsigned mount_id;
+ int dirty;
+};
+
+#define yaffs_dev_to_lc(dev) ((struct yaffs_linux_context *)((dev)->os_context))
+#define yaffs_dev_to_mtd(dev) ((struct mtd_info *)((dev)->driver_context))
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
+#define WRITE_SIZE_STR "writesize"
+#define WRITE_SIZE(mtd) ((mtd)->writesize)
+#else
+#define WRITE_SIZE_STR "oobblock"
+#define WRITE_SIZE(mtd) ((mtd)->oobblock)
+#endif
+
+#endif
diff -urN linux-4.9.37/fs/yaffs2/yaffs_mtdif.c linux-4.9.y/fs/yaffs2/yaffs_mtdif.c
--- linux-4.9.37/fs/yaffs2/yaffs_mtdif.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/yaffs_mtdif.c 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,310 @@
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * 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 "yportenv.h"
+
+#include "yaffs_mtdif.h"
+
+#include "linux/mtd/mtd.h"
+#include "linux/types.h"
+#include "linux/time.h"
+#include "linux/mtd/nand.h"
+#include "linux/kernel.h"
+#include "linux/version.h"
+#include "linux/types.h"
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
+#include "uapi/linux/major.h"
+#endif
+
+#include "yaffs_trace.h"
+#include "yaffs_guts.h"
+#include "yaffs_linux.h"
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0))
+#define MTD_OPS_AUTO_OOB MTD_OOB_AUTO
+#endif
+
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0))
+#define mtd_erase(m, ei) (m)->erase(m, ei)
+#define mtd_write_oob(m, addr, pops) (m)->write_oob(m, addr, pops)
+#define mtd_read_oob(m, addr, pops) (m)->read_oob(m, addr, pops)
+#define mtd_block_isbad(m, offs) (m)->block_isbad(m, offs)
+#define mtd_block_markbad(m, offs) (m)->block_markbad(m, offs)
+#endif
+
+
+
+int nandmtd_erase_block(struct yaffs_dev *dev, int block_no)
+{
+ struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
+ u32 addr =
+ ((loff_t) block_no) * dev->param.total_bytes_per_chunk *
+ dev->param.chunks_per_block;
+ struct erase_info ei;
+ int retval = 0;
+
+ ei.mtd = mtd;
+ ei.addr = addr;
+ ei.len = dev->param.total_bytes_per_chunk * dev->param.chunks_per_block;
+ ei.time = 1000;
+ ei.retries = 2;
+ ei.callback = NULL;
+ ei.priv = (u_long) dev;
+
+ retval = mtd_erase(mtd, &ei);
+
+ if (retval == 0)
+ return YAFFS_OK;
+
+ return YAFFS_FAIL;
+}
+
+
+static int yaffs_mtd_write(struct yaffs_dev *dev, int nand_chunk,
+ const u8 *data, int data_len,
+ const u8 *oob, int oob_len)
+{
+ struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
+ loff_t addr;
+ struct mtd_oob_ops ops;
+ int retval;
+
+ yaffs_trace(YAFFS_TRACE_MTD,
+ "yaffs_mtd_write(%p, %d, %p, %d, %p, %d)\n",
+ dev, nand_chunk, data, data_len, oob, oob_len);
+
+ if (!data || !data_len) {
+ data = NULL;
+ data_len = 0;
+ }
+
+ if (!oob || !oob_len) {
+ oob = NULL;
+ oob_len = 0;
+ }
+
+ addr = ((loff_t) nand_chunk) * dev->param.total_bytes_per_chunk;
+ memset(&ops, 0, sizeof(ops));
+ ops.mode = MTD_OPS_AUTO_OOB;
+ ops.len = (data) ? data_len : 0;
+ ops.ooblen = oob_len;
+ ops.datbuf = (u8 *)data;
+ ops.oobbuf = (u8 *)oob;
+
+ retval = mtd_write_oob(mtd, addr, &ops);
+ if (retval) {
+ yaffs_trace(YAFFS_TRACE_MTD,
+ "write_oob failed, chunk %d, mtd error %d",
+ nand_chunk, retval);
+ }
+ return retval ? YAFFS_FAIL : YAFFS_OK;
+}
+
+static int yaffs_mtd_read(struct yaffs_dev *dev, int nand_chunk,
+ u8 *data, int data_len,
+ u8 *oob, int oob_len,
+ enum yaffs_ecc_result *ecc_result)
+{
+ struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
+ loff_t addr;
+ struct mtd_oob_ops ops;
+ int retval;
+
+ addr = ((loff_t) nand_chunk) * dev->param.total_bytes_per_chunk;
+ memset(&ops, 0, sizeof(ops));
+ ops.mode = MTD_OPS_AUTO_OOB;
+ ops.len = (data) ? data_len : 0;
+ ops.ooblen = oob_len;
+ ops.datbuf = data;
+ ops.oobbuf = oob;
+
+#if (MTD_VERSION_CODE < MTD_VERSION(2, 6, 20))
+ /* In MTD 2.6.18 to 2.6.19 nand_base.c:nand_do_read_oob() has a bug;
+ * help it out with ops.len = ops.ooblen when ops.datbuf == NULL.
+ */
+ ops.len = (ops.datbuf) ? ops.len : ops.ooblen;
+#endif
+ /* Read page and oob using MTD.
+ * Check status and determine ECC result.
+ */
+ retval = mtd_read_oob(mtd, addr, &ops);
+ if (retval)
+ yaffs_trace(YAFFS_TRACE_MTD,
+ "read_oob failed, chunk %d, mtd error %d",
+ nand_chunk, retval);
+
+ switch (retval) {
+ case 0:
+ /* no error */
+ if(ecc_result)
+ *ecc_result = YAFFS_ECC_RESULT_NO_ERROR;
+ break;
+
+ case -EUCLEAN:
+ /* MTD's ECC fixed the data */
+ if(ecc_result)
+ *ecc_result = YAFFS_ECC_RESULT_FIXED;
+ dev->n_ecc_fixed++;
+ break;
+
+ case -EBADMSG:
+ default:
+ /* MTD's ECC could not fix the data */
+ dev->n_ecc_unfixed++;
+ if(ecc_result)
+ *ecc_result = YAFFS_ECC_RESULT_UNFIXED;
+ return YAFFS_FAIL;
+ }
+
+ return YAFFS_OK;
+}
+
+static int yaffs_mtd_erase(struct yaffs_dev *dev, int block_no)
+{
+ struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
+
+ loff_t addr;
+ struct erase_info ei;
+ int retval = 0;
+ u32 block_size;
+
+ block_size = dev->param.total_bytes_per_chunk *
+ dev->param.chunks_per_block;
+ addr = ((loff_t) block_no) * block_size;
+
+ ei.mtd = mtd;
+ ei.addr = addr;
+ ei.len = block_size;
+ ei.time = 1000;
+ ei.retries = 2;
+ ei.callback = NULL;
+ ei.priv = (u_long) dev;
+
+ retval = mtd_erase(mtd, &ei);
+
+ if (retval == 0)
+ return YAFFS_OK;
+
+ return YAFFS_FAIL;
+}
+
+static int yaffs_mtd_mark_bad(struct yaffs_dev *dev, int block_no)
+{
+ struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
+ int blocksize = dev->param.chunks_per_block * dev->param.total_bytes_per_chunk;
+ int retval;
+
+ yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, "marking block %d bad", block_no);
+
+ retval = mtd_block_markbad(mtd, (loff_t) blocksize * block_no);
+ return (retval) ? YAFFS_FAIL : YAFFS_OK;
+}
+
+static int yaffs_mtd_check_bad(struct yaffs_dev *dev, int block_no)
+{
+ struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
+ int blocksize = dev->param.chunks_per_block * dev->param.total_bytes_per_chunk;
+ int retval;
+
+ yaffs_trace(YAFFS_TRACE_MTD, "checking block %d bad", block_no);
+
+ retval = mtd_block_isbad(mtd, (loff_t) blocksize * block_no);
+ return (retval) ? YAFFS_FAIL : YAFFS_OK;
+}
+
+static int yaffs_mtd_initialise(struct yaffs_dev *dev)
+{
+ return YAFFS_OK;
+}
+
+static int yaffs_mtd_deinitialise(struct yaffs_dev *dev)
+{
+ return YAFFS_OK;
+}
+
+
+void yaffs_mtd_drv_install(struct yaffs_dev *dev)
+{
+ struct yaffs_driver *drv = &dev->drv;
+
+ drv->drv_write_chunk_fn = yaffs_mtd_write;
+ drv->drv_read_chunk_fn = yaffs_mtd_read;
+ drv->drv_erase_fn = yaffs_mtd_erase;
+ drv->drv_mark_bad_fn = yaffs_mtd_mark_bad;
+ drv->drv_check_bad_fn = yaffs_mtd_check_bad;
+ drv->drv_initialise_fn = yaffs_mtd_initialise;
+ drv->drv_deinitialise_fn = yaffs_mtd_deinitialise;
+}
+
+
+struct mtd_info * yaffs_get_mtd_device(dev_t sdev)
+{
+ struct mtd_info *mtd;
+
+ mtd = yaffs_get_mtd_device(sdev);
+
+ /* Check it's an mtd device..... */
+ if (MAJOR(sdev) != MTD_BLOCK_MAJOR)
+ return NULL; /* This isn't an mtd device */
+
+ /* Check it's NAND */
+ if (mtd->type != MTD_NANDFLASH) {
+ yaffs_trace(YAFFS_TRACE_ALWAYS,
+ "yaffs: MTD device is not NAND it's type %d",
+ mtd->type);
+ return NULL;
+ }
+
+ yaffs_trace(YAFFS_TRACE_OS, " %s %d", WRITE_SIZE_STR, WRITE_SIZE(mtd));
+ yaffs_trace(YAFFS_TRACE_OS, " oobsize %d", mtd->oobsize);
+ yaffs_trace(YAFFS_TRACE_OS, " erasesize %d", mtd->erasesize);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
+ yaffs_trace(YAFFS_TRACE_OS, " size %u", mtd->size);
+#else
+ yaffs_trace(YAFFS_TRACE_OS, " size %lld", mtd->size);
+#endif
+
+ return mtd;
+}
+
+int yaffs_verify_mtd(struct mtd_info *mtd, int yaffs_version, int inband_tags)
+{
+ if (yaffs_version == 2) {
+ if ((WRITE_SIZE(mtd) < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
+ mtd->oobsize < YAFFS_MIN_YAFFS2_SPARE_SIZE) &&
+ !inband_tags) {
+ yaffs_trace(YAFFS_TRACE_ALWAYS,
+ "MTD device does not have the right page sizes"
+ );
+ return -1;
+ }
+ } else {
+ if (WRITE_SIZE(mtd) < YAFFS_BYTES_PER_CHUNK ||
+ mtd->oobsize != YAFFS_BYTES_PER_SPARE) {
+ yaffs_trace(YAFFS_TRACE_ALWAYS,
+ "MTD device does not support have the right page sizes"
+ );
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+
+void yaffs_put_mtd_device(struct mtd_info *mtd)
+{
+ if(mtd)
+ put_mtd_device(mtd);
+}
diff -urN linux-4.9.37/fs/yaffs2/yaffs_mtdif.h linux-4.9.y/fs/yaffs2/yaffs_mtdif.h
--- linux-4.9.37/fs/yaffs2/yaffs_mtdif.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/yaffs_mtdif.h 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,25 @@
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+#ifndef __YAFFS_MTDIF_H__
+#define __YAFFS_MTDIF_H__
+
+#include "yaffs_guts.h"
+
+void yaffs_mtd_drv_install(struct yaffs_dev *dev);
+struct mtd_info * yaffs_get_mtd_device(dev_t sdev);
+void yaffs_put_mtd_device(struct mtd_info *mtd);
+int yaffs_verify_mtd(struct mtd_info *mtd, int yaffs_version, int inband_tags);
+#endif
diff -urN linux-4.9.37/fs/yaffs2/yaffs_nameval.c linux-4.9.y/fs/yaffs2/yaffs_nameval.c
--- linux-4.9.37/fs/yaffs2/yaffs_nameval.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/yaffs_nameval.c 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,230 @@
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * 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.
+ */
+
+/*
+ * This simple implementation of a name-value store assumes a small number of
+* values and fits into a small finite buffer.
+ *
+ * Each attribute is stored as a record:
+ * sizeof(size) bytes record size.
+ * strnlen+1 bytes name null terminated.
+ * nbytes value.
+ * ----------
+ * total size stored in record size
+ *
+ * This code has not been tested with unicode yet.
+ */
+
+#include "yaffs_nameval.h"
+#include "yaffs_guts.h"
+#include "yportenv.h"
+#include "yaffs_endian.h"
+
+static int nval_find(struct yaffs_dev *dev,
+ const char *xb, int xb_size, const YCHAR *name,
+ int *exist_size)
+{
+ int pos = 0;
+ s32 size;
+
+ memcpy(&size, xb, sizeof(size));
+ yaffs_do_endian_s32(dev, &size);
+
+ while (size > 0 && (size < xb_size) && (pos + size < xb_size)) {
+ if (!strncmp((YCHAR *) (xb + pos + sizeof(size)),
+ name, size)) {
+ if (exist_size)
+ *exist_size = size;
+ return pos;
+ }
+ pos += size;
+ if (pos < (int)(xb_size - sizeof(size))) {
+ memcpy(&size, xb + pos, sizeof(size));
+ yaffs_do_endian_s32(dev, &size);
+
+ } else
+ size = 0;
+ }
+ if (exist_size)
+ *exist_size = 0;
+ return -ENODATA;
+}
+
+static int nval_used(struct yaffs_dev *dev, const char *xb, int xb_size)
+{
+ int pos = 0;
+ s32 size;
+
+ memcpy(&size, xb + pos, sizeof(size));
+ yaffs_do_endian_s32(dev, &size);
+
+ while (size > 0 && (size < xb_size) && (pos + size < xb_size)) {
+ pos += size;
+ if (pos < (int)(xb_size - sizeof(size))) {
+ memcpy(&size, xb + pos, sizeof(size));
+ yaffs_do_endian_s32(dev, &size);
+ } else
+ size = 0;
+ }
+ return pos;
+}
+
+int nval_del(struct yaffs_dev *dev, char *xb, int xb_size, const YCHAR *name)
+{
+ int pos = nval_find(dev, xb, xb_size, name, NULL);
+ s32 size;
+
+ if (pos < 0 || pos >= xb_size)
+ return -ENODATA;
+
+ /* Find size, shift rest over this record,
+ * then zero out the rest of buffer */
+ memcpy(&size, xb + pos, sizeof(size));
+ yaffs_do_endian_s32(dev, &size);
+
+ memcpy(xb + pos, xb + pos + size, xb_size - (pos + size));
+ memset(xb + (xb_size - size), 0, size);
+ return 0;
+}
+
+int nval_set(struct yaffs_dev *dev,
+ char *xb, int xb_size, const YCHAR *name, const char *buf,
+ int bsize, int flags)
+{
+ int pos;
+ int namelen = strnlen(name, xb_size);
+ int size_exist = 0;
+ int space;
+ int start;
+ s32 reclen;
+ s32 reclen_endianised;
+
+ pos = nval_find(dev, xb, xb_size, name, &size_exist);
+
+ if (flags & XATTR_CREATE && pos >= 0)
+ return -EEXIST;
+ if (flags & XATTR_REPLACE && pos < 0)
+ return -ENODATA;
+
+ start = nval_used(dev, xb, xb_size);
+ space = xb_size - start + size_exist;
+
+ reclen = (sizeof(reclen) + namelen + 1 + bsize);
+
+ if (reclen > space)
+ return -ENOSPC;
+
+ if (pos >= 0) {
+ /* Exists, so delete it. */
+ nval_del(dev, xb, xb_size, name);
+ start = nval_used(dev, xb, xb_size);
+ }
+
+ pos = start;
+
+ reclen_endianised = reclen;
+ yaffs_do_endian_s32(dev, &reclen_endianised);
+ memcpy(xb + pos, &reclen_endianised, sizeof(reclen_endianised));
+ pos += sizeof(reclen_endianised);
+ strncpy((YCHAR *) (xb + pos), name, reclen);
+ pos += (namelen + 1);
+ memcpy(xb + pos, buf, bsize);
+ return 0;
+}
+
+int nval_get(struct yaffs_dev *dev,
+ const char *xb, int xb_size, const YCHAR * name, char *buf,
+ int bsize)
+{
+ int pos = nval_find(dev, xb, xb_size, name, NULL);
+ s32 size;
+
+ if (pos >= 0 && pos < xb_size) {
+
+ memcpy(&size, xb + pos, sizeof(size));
+ yaffs_do_endian_s32(dev, &size);
+ pos += sizeof(size); /* advance past record length */
+ size -= sizeof(size);
+
+ /* Advance over name string */
+ while (xb[pos] && size > 0 && pos < xb_size) {
+ pos++;
+ size--;
+ }
+ /*Advance over NUL */
+ pos++;
+ size--;
+
+ /* If bsize is zero then this is a size query.
+ * Return the size, but don't copy.
+ */
+ if (!bsize)
+ return size;
+
+ if (size <= bsize) {
+ memcpy(buf, xb + pos, size);
+ return size;
+ }
+ }
+ if (pos >= 0)
+ return -ERANGE;
+
+ return -ENODATA;
+}
+
+int nval_list(struct yaffs_dev *dev, const char *xb, int xb_size, char *buf, int bsize)
+{
+ int pos = 0;
+ s32 size;
+ int name_len;
+ int ncopied = 0;
+ int filled = 0;
+
+ memcpy(&size, xb + pos, sizeof(size));
+ yaffs_do_endian_s32(dev, &size);
+
+ while (size > (int)(sizeof(size)) &&
+ size <= xb_size &&
+ (pos + size) < xb_size &&
+ !filled) {
+ pos += sizeof(size);
+ size -= sizeof(size);
+ name_len = strnlen((YCHAR *) (xb + pos), size);
+ if (ncopied + name_len + 1 < bsize) {
+ memcpy(buf, xb + pos, name_len * sizeof(YCHAR));
+ buf += name_len;
+ *buf = '\0';
+ buf++;
+ if (sizeof(YCHAR) > 1) {
+ *buf = '\0';
+ buf++;
+ }
+ ncopied += (name_len + 1);
+ } else {
+ filled = 1;
+ }
+ pos += size;
+ if (pos < (int)(xb_size - sizeof(size))) {
+ memcpy(&size, xb + pos, sizeof(size));
+ yaffs_do_endian_s32(dev, &size);
+ }
+ else
+ size = 0;
+ }
+ return ncopied;
+}
+
+int nval_hasvalues(struct yaffs_dev *dev, const char *xb, int xb_size)
+{
+ return nval_used(dev, xb, xb_size) > 0;
+}
diff -urN linux-4.9.37/fs/yaffs2/yaffs_nameval.h linux-4.9.y/fs/yaffs2/yaffs_nameval.h
--- linux-4.9.37/fs/yaffs2/yaffs_nameval.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/yaffs_nameval.h 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,33 @@
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+#ifndef __NAMEVAL_H__
+#define __NAMEVAL_H__
+
+#include "yportenv.h"
+
+struct yaffs_dev;
+
+int nval_del(struct yaffs_dev *dev, char *xb, int xb_size, const YCHAR * name);
+int nval_set(struct yaffs_dev *dev,
+ char *xb, int xb_size, const YCHAR * name, const char *buf,
+ int bsize, int flags);
+int nval_get(struct yaffs_dev *dev,
+ const char *xb, int xb_size, const YCHAR * name, char *buf,
+ int bsize);
+int nval_list(struct yaffs_dev *dev,
+ const char *xb, int xb_size, char *buf, int bsize);
+int nval_hasvalues(struct yaffs_dev *dev, const char *xb, int xb_size);
+#endif
diff -urN linux-4.9.37/fs/yaffs2/yaffs_nand.c linux-4.9.y/fs/yaffs2/yaffs_nand.c
--- linux-4.9.37/fs/yaffs2/yaffs_nand.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/yaffs_nand.c 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,122 @@
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * 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 "yaffs_nand.h"
+#include "yaffs_tagscompat.h"
+
+#include "yaffs_getblockinfo.h"
+#include "yaffs_summary.h"
+
+static int apply_chunk_offset(struct yaffs_dev *dev, int chunk)
+{
+ return chunk - dev->chunk_offset;
+}
+
+int yaffs_rd_chunk_tags_nand(struct yaffs_dev *dev, int nand_chunk,
+ u8 *buffer, struct yaffs_ext_tags *tags)
+{
+ int result;
+ struct yaffs_ext_tags local_tags;
+ int flash_chunk = apply_chunk_offset(dev, nand_chunk);
+
+ dev->n_page_reads++;
+
+ /* If there are no tags provided use local tags. */
+ if (!tags)
+ tags = &local_tags;
+
+ result = dev->tagger.read_chunk_tags_fn(dev, flash_chunk, buffer, tags);
+ if (tags && tags->ecc_result > YAFFS_ECC_RESULT_NO_ERROR) {
+
+ struct yaffs_block_info *bi;
+ bi = yaffs_get_block_info(dev,
+ nand_chunk /
+ dev->param.chunks_per_block);
+ yaffs_handle_chunk_error(dev, bi);
+ }
+ return result;
+}
+
+int yaffs_wr_chunk_tags_nand(struct yaffs_dev *dev,
+ int nand_chunk,
+ const u8 *buffer, struct yaffs_ext_tags *tags)
+{
+ int result;
+ int flash_chunk = apply_chunk_offset(dev, nand_chunk);
+
+ dev->n_page_writes++;
+
+ if (!tags) {
+ yaffs_trace(YAFFS_TRACE_ERROR, "Writing with no tags");
+ BUG();
+ return YAFFS_FAIL;
+ }
+
+ tags->seq_number = dev->seq_number;
+ tags->chunk_used = 1;
+ yaffs_trace(YAFFS_TRACE_WRITE,
+ "Writing chunk %d tags %d %d",
+ nand_chunk, tags->obj_id, tags->chunk_id);
+
+ result = dev->tagger.write_chunk_tags_fn(dev, flash_chunk,
+ buffer, tags);
+
+ yaffs_summary_add(dev, tags, nand_chunk);
+
+ return result;
+}
+
+int yaffs_mark_bad(struct yaffs_dev *dev, int block_no)
+{
+ block_no -= dev->block_offset;
+ dev->n_bad_markings++;
+
+ if (dev->param.disable_bad_block_marking)
+ return YAFFS_OK;
+
+ return dev->tagger.mark_bad_fn(dev, block_no);
+}
+
+
+int yaffs_query_init_block_state(struct yaffs_dev *dev,
+ int block_no,
+ enum yaffs_block_state *state,
+ u32 *seq_number)
+{
+ block_no -= dev->block_offset;
+ return dev->tagger.query_block_fn(dev, block_no, state, seq_number);
+}
+
+int yaffs_erase_block(struct yaffs_dev *dev, int block_no)
+{
+ int result;
+
+ block_no -= dev->block_offset;
+ dev->n_erasures++;
+ result = dev->drv.drv_erase_fn(dev, block_no);
+ return result;
+}
+
+int yaffs_init_nand(struct yaffs_dev *dev)
+{
+ if (dev->drv.drv_initialise_fn)
+ return dev->drv.drv_initialise_fn(dev);
+ return YAFFS_OK;
+}
+
+int yaffs_deinit_nand(struct yaffs_dev *dev)
+{
+ if (dev->drv.drv_deinitialise_fn)
+ return dev->drv.drv_deinitialise_fn(dev);
+ return YAFFS_OK;
+}
diff -urN linux-4.9.37/fs/yaffs2/yaffs_nand.h linux-4.9.y/fs/yaffs2/yaffs_nand.h
--- linux-4.9.37/fs/yaffs2/yaffs_nand.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/yaffs_nand.h 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,39 @@
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+#ifndef __YAFFS_NAND_H__
+#define __YAFFS_NAND_H__
+#include "yaffs_guts.h"
+
+int yaffs_rd_chunk_tags_nand(struct yaffs_dev *dev, int nand_chunk,
+ u8 *buffer, struct yaffs_ext_tags *tags);
+
+int yaffs_wr_chunk_tags_nand(struct yaffs_dev *dev,
+ int nand_chunk,
+ const u8 *buffer, struct yaffs_ext_tags *tags);
+
+int yaffs_mark_bad(struct yaffs_dev *dev, int block_no);
+
+int yaffs_query_init_block_state(struct yaffs_dev *dev,
+ int block_no,
+ enum yaffs_block_state *state,
+ unsigned *seq_number);
+
+int yaffs_erase_block(struct yaffs_dev *dev, int flash_block);
+
+int yaffs_init_nand(struct yaffs_dev *dev);
+int yaffs_deinit_nand(struct yaffs_dev *dev);
+
+#endif
diff -urN linux-4.9.37/fs/yaffs2/yaffs_packedtags1.c linux-4.9.y/fs/yaffs2/yaffs_packedtags1.c
--- linux-4.9.37/fs/yaffs2/yaffs_packedtags1.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/yaffs_packedtags1.c 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,55 @@
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * 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 "yaffs_packedtags1.h"
+#include "yportenv.h"
+
+static const u8 all_ff[20] = {
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff
+};
+
+void yaffs_pack_tags1(struct yaffs_packed_tags1 *pt,
+ const struct yaffs_ext_tags *t)
+{
+ pt->chunk_id = t->chunk_id;
+ pt->serial_number = t->serial_number;
+ pt->n_bytes = t->n_bytes;
+ pt->obj_id = t->obj_id;
+ pt->ecc = 0;
+ pt->deleted = (t->is_deleted) ? 0 : 1;
+ pt->unused_stuff = 0;
+ pt->should_be_ff = 0xffffffff;
+}
+
+void yaffs_unpack_tags1(struct yaffs_ext_tags *t,
+ const struct yaffs_packed_tags1 *pt)
+{
+ if (memcmp(all_ff, pt, sizeof(struct yaffs_packed_tags1))) {
+ t->block_bad = 0;
+ if (pt->should_be_ff != 0xffffffff)
+ t->block_bad = 1;
+ t->chunk_used = 1;
+ t->obj_id = pt->obj_id;
+ t->chunk_id = pt->chunk_id;
+ t->n_bytes = pt->n_bytes;
+ t->ecc_result = YAFFS_ECC_RESULT_NO_ERROR;
+ t->is_deleted = (pt->deleted) ? 0 : 1;
+ t->serial_number = pt->serial_number;
+ } else {
+ memset(t, 0, sizeof(struct yaffs_ext_tags));
+ }
+}
diff -urN linux-4.9.37/fs/yaffs2/yaffs_packedtags1.h linux-4.9.y/fs/yaffs2/yaffs_packedtags1.h
--- linux-4.9.37/fs/yaffs2/yaffs_packedtags1.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/yaffs_packedtags1.h 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,39 @@
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+/* This is used to pack YAFFS1 tags, not YAFFS2 tags. */
+
+#ifndef __YAFFS_PACKEDTAGS1_H__
+#define __YAFFS_PACKEDTAGS1_H__
+
+#include "yaffs_guts.h"
+
+struct yaffs_packed_tags1 {
+ u32 chunk_id:20;
+ u32 serial_number:2;
+ u32 n_bytes:10;
+ u32 obj_id:18;
+ u32 ecc:12;
+ u32 deleted:1;
+ u32 unused_stuff:1;
+ unsigned should_be_ff;
+
+};
+
+void yaffs_pack_tags1(struct yaffs_packed_tags1 *pt,
+ const struct yaffs_ext_tags *t);
+void yaffs_unpack_tags1(struct yaffs_ext_tags *t,
+ const struct yaffs_packed_tags1 *pt);
+#endif
diff -urN linux-4.9.37/fs/yaffs2/yaffs_packedtags2.c linux-4.9.y/fs/yaffs2/yaffs_packedtags2.c
--- linux-4.9.37/fs/yaffs2/yaffs_packedtags2.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/yaffs_packedtags2.c 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,208 @@
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * 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 "yaffs_packedtags2.h"
+#include "yportenv.h"
+#include "yaffs_trace.h"
+#include "yaffs_endian.h"
+
+/* This code packs a set of extended tags into a binary structure for
+ * NAND storage
+ */
+
+/* Some of the information is "extra" struff which can be packed in to
+ * speed scanning
+ * This is defined by having the EXTRA_HEADER_INFO_FLAG set.
+ */
+
+/* Extra flags applied to chunk_id */
+
+#define EXTRA_HEADER_INFO_FLAG 0x80000000
+#define EXTRA_SHRINK_FLAG 0x40000000
+#define EXTRA_SHADOWS_FLAG 0x20000000
+#define EXTRA_SPARE_FLAGS 0x10000000
+
+#define ALL_EXTRA_FLAGS 0xf0000000
+
+/* Also, the top 4 bits of the object Id are set to the object type. */
+#define EXTRA_OBJECT_TYPE_SHIFT (28)
+#define EXTRA_OBJECT_TYPE_MASK ((0x0f) << EXTRA_OBJECT_TYPE_SHIFT)
+
+static void yaffs_dump_packed_tags2_tags_only(
+ const struct yaffs_packed_tags2_tags_only *ptt)
+{
+ yaffs_trace(YAFFS_TRACE_MTD,
+ "packed tags obj %d chunk %d byte %d seq %d",
+ ptt->obj_id, ptt->chunk_id, ptt->n_bytes, ptt->seq_number);
+}
+
+static void yaffs_dump_packed_tags2(const struct yaffs_packed_tags2 *pt)
+{
+ yaffs_dump_packed_tags2_tags_only(&pt->t);
+}
+
+static void yaffs_dump_tags2(const struct yaffs_ext_tags *t)
+{
+ yaffs_trace(YAFFS_TRACE_MTD,
+ "ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte %d del %d ser %d seq %d",
+ t->ecc_result, t->block_bad, t->chunk_used, t->obj_id,
+ t->chunk_id, t->n_bytes, t->is_deleted, t->serial_number,
+ t->seq_number);
+
+}
+
+static int yaffs_check_tags_extra_packable(const struct yaffs_ext_tags *t)
+{
+ if (t->chunk_id != 0 || !t->extra_available)
+ return 0;
+
+ /* Check if the file size is too long to store */
+ if (t->extra_obj_type == YAFFS_OBJECT_TYPE_FILE &&
+ (t->extra_file_size >> 31) != 0)
+ return 0;
+ return 1;
+}
+
+void yaffs_pack_tags2_tags_only(struct yaffs_dev *dev,
+ struct yaffs_packed_tags2_tags_only *ptt,
+ const struct yaffs_ext_tags *t)
+{
+ ptt->chunk_id = t->chunk_id;
+ ptt->seq_number = t->seq_number;
+ ptt->n_bytes = t->n_bytes;
+ ptt->obj_id = t->obj_id;
+
+ /* Only store extra tags for object headers.
+ * If it is a file then only store if the file size is short\
+ * enough to fit.
+ */
+ if (yaffs_check_tags_extra_packable(t)) {
+ /* Store the extra header info instead */
+ /* We save the parent object in the chunk_id */
+ ptt->chunk_id = EXTRA_HEADER_INFO_FLAG | t->extra_parent_id;
+ if (t->extra_is_shrink)
+ ptt->chunk_id |= EXTRA_SHRINK_FLAG;
+ if (t->extra_shadows)
+ ptt->chunk_id |= EXTRA_SHADOWS_FLAG;
+
+ ptt->obj_id &= ~EXTRA_OBJECT_TYPE_MASK;
+ ptt->obj_id |= (t->extra_obj_type << EXTRA_OBJECT_TYPE_SHIFT);
+
+ if (t->extra_obj_type == YAFFS_OBJECT_TYPE_HARDLINK)
+ ptt->n_bytes = t->extra_equiv_id;
+ else if (t->extra_obj_type == YAFFS_OBJECT_TYPE_FILE)
+ ptt->n_bytes = (unsigned) t->extra_file_size;
+ else
+ ptt->n_bytes = 0;
+ }
+
+ yaffs_dump_packed_tags2_tags_only(ptt);
+ yaffs_dump_tags2(t);
+ yaffs_do_endian_packed_tags2(dev, ptt);
+}
+
+void yaffs_pack_tags2(struct yaffs_dev *dev,
+ struct yaffs_packed_tags2 *pt,
+ const struct yaffs_ext_tags *t, int tags_ecc)
+{
+ yaffs_pack_tags2_tags_only(dev, &pt->t, t);
+
+ if (tags_ecc)
+ yaffs_ecc_calc_other((unsigned char *)&pt->t,
+ sizeof(struct yaffs_packed_tags2_tags_only),
+ &pt->ecc);
+}
+
+void yaffs_unpack_tags2_tags_only(struct yaffs_dev *dev,
+ struct yaffs_ext_tags *t,
+ struct yaffs_packed_tags2_tags_only *ptt_ptr)
+{
+ struct yaffs_packed_tags2_tags_only ptt_copy = *ptt_ptr;
+
+ memset(t, 0, sizeof(struct yaffs_ext_tags));
+
+ if (ptt_copy.seq_number == 0xffffffff)
+ return;
+
+ yaffs_do_endian_packed_tags2(dev, &ptt_copy);
+
+ t->block_bad = 0;
+ t->chunk_used = 1;
+ t->obj_id = ptt_copy.obj_id;
+ t->chunk_id = ptt_copy.chunk_id;
+ t->n_bytes = ptt_copy.n_bytes;
+ t->is_deleted = 0;
+ t->serial_number = 0;
+ t->seq_number = ptt_copy.seq_number;
+
+ /* Do extra header info stuff */
+ if (ptt_copy.chunk_id & EXTRA_HEADER_INFO_FLAG) {
+ t->chunk_id = 0;
+ t->n_bytes = 0;
+
+ t->extra_available = 1;
+ t->extra_parent_id = ptt_copy.chunk_id & (~(ALL_EXTRA_FLAGS));
+ t->extra_is_shrink = ptt_copy.chunk_id & EXTRA_SHRINK_FLAG ? 1 : 0;
+ t->extra_shadows = ptt_copy.chunk_id & EXTRA_SHADOWS_FLAG ? 1 : 0;
+ t->extra_obj_type = ptt_copy.obj_id >> EXTRA_OBJECT_TYPE_SHIFT;
+ t->obj_id &= ~EXTRA_OBJECT_TYPE_MASK;
+
+ if (t->extra_obj_type == YAFFS_OBJECT_TYPE_HARDLINK)
+ t->extra_equiv_id = ptt_copy.n_bytes;
+ else
+ t->extra_file_size = ptt_copy.n_bytes;
+ }
+ yaffs_dump_packed_tags2_tags_only(ptt_ptr);
+ yaffs_dump_tags2(t);
+}
+
+void yaffs_unpack_tags2(struct yaffs_dev *dev,
+ struct yaffs_ext_tags *t,
+ struct yaffs_packed_tags2 *pt,
+ int tags_ecc)
+{
+ enum yaffs_ecc_result ecc_result = YAFFS_ECC_RESULT_NO_ERROR;
+
+ if (pt->t.seq_number != 0xffffffff && tags_ecc) {
+ /* Chunk is in use and we need to do ECC */
+
+ struct yaffs_ecc_other ecc;
+ int result;
+ yaffs_ecc_calc_other((unsigned char *)&pt->t,
+ sizeof(struct yaffs_packed_tags2_tags_only),
+ &ecc);
+ result =
+ yaffs_ecc_correct_other((unsigned char *)&pt->t,
+ sizeof(struct yaffs_packed_tags2_tags_only),
+ &pt->ecc, &ecc);
+ switch (result) {
+ case 0:
+ ecc_result = YAFFS_ECC_RESULT_NO_ERROR;
+ break;
+ case 1:
+ ecc_result = YAFFS_ECC_RESULT_FIXED;
+ break;
+ case -1:
+ ecc_result = YAFFS_ECC_RESULT_UNFIXED;
+ break;
+ default:
+ ecc_result = YAFFS_ECC_RESULT_UNKNOWN;
+ }
+ }
+ yaffs_unpack_tags2_tags_only(dev, t, &pt->t);
+
+ t->ecc_result = ecc_result;
+
+ yaffs_dump_packed_tags2(pt);
+ yaffs_dump_tags2(t);
+}
diff -urN linux-4.9.37/fs/yaffs2/yaffs_packedtags2.h linux-4.9.y/fs/yaffs2/yaffs_packedtags2.h
--- linux-4.9.37/fs/yaffs2/yaffs_packedtags2.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/yaffs_packedtags2.h 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,51 @@
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+/* This is used to pack YAFFS2 tags, not YAFFS1tags. */
+
+#ifndef __YAFFS_PACKEDTAGS2_H__
+#define __YAFFS_PACKEDTAGS2_H__
+
+#include "yaffs_guts.h"
+#include "yaffs_ecc.h"
+
+struct yaffs_packed_tags2_tags_only {
+ unsigned seq_number;
+ unsigned obj_id;
+ unsigned chunk_id;
+ unsigned n_bytes;
+};
+
+struct yaffs_packed_tags2 {
+ struct yaffs_packed_tags2_tags_only t;
+ struct yaffs_ecc_other ecc;
+};
+
+/* Full packed tags with ECC, used for oob tags */
+void yaffs_pack_tags2(struct yaffs_dev *dev,
+ struct yaffs_packed_tags2 *pt,
+ const struct yaffs_ext_tags *t, int tags_ecc);
+void yaffs_unpack_tags2(struct yaffs_dev *dev,
+ struct yaffs_ext_tags *t, struct yaffs_packed_tags2 *pt,
+ int tags_ecc);
+
+/* Only the tags part (no ECC for use with inband tags */
+void yaffs_pack_tags2_tags_only(struct yaffs_dev *dev,
+ struct yaffs_packed_tags2_tags_only *pt,
+ const struct yaffs_ext_tags *t);
+void yaffs_unpack_tags2_tags_only(struct yaffs_dev *dev,
+ struct yaffs_ext_tags *t,
+ struct yaffs_packed_tags2_tags_only *pt);
+#endif
diff -urN linux-4.9.37/fs/yaffs2/yaffs_summary.c linux-4.9.y/fs/yaffs2/yaffs_summary.c
--- linux-4.9.37/fs/yaffs2/yaffs_summary.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/yaffs_summary.c 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,310 @@
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * 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.
+ */
+
+/* Summaries write the useful part of the tags for the chunks in a block into an
+ * an array which is written to the last n chunks of the block.
+ * Reading the summaries gives all the tags for the block in one read. Much
+ * faster.
+ *
+ * Chunks holding summaries are marked with tags making it look like
+ * they are part of a fake file.
+ *
+ * The summary could also be used during gc.
+ *
+ */
+
+#include "yaffs_summary.h"
+#include "yaffs_packedtags2.h"
+#include "yaffs_nand.h"
+#include "yaffs_getblockinfo.h"
+#include "yaffs_bitmap.h"
+
+/*
+ * The summary is built up in an array of summary tags.
+ * This gets written to the last one or two (maybe more) chunks in a block.
+ * A summary header is written as the first part of each chunk of summary data.
+ * The summary header must match or the summary is rejected.
+ */
+
+/* Summary tags don't need the sequence number because that is redundant. */
+struct yaffs_summary_tags {
+ unsigned obj_id;
+ unsigned chunk_id;
+ unsigned n_bytes;
+};
+
+/* Summary header */
+struct yaffs_summary_header {
+ unsigned version; /* Must match current version */
+ unsigned block; /* Must be this block */
+ unsigned seq; /* Must be this sequence number */
+ unsigned sum; /* Just add up all the bytes in the tags */
+};
+
+
+static void yaffs_summary_clear(struct yaffs_dev *dev)
+{
+ if (!dev->sum_tags)
+ return;
+ memset(dev->sum_tags, 0, dev->chunks_per_summary *
+ sizeof(struct yaffs_summary_tags));
+}
+
+
+void yaffs_summary_deinit(struct yaffs_dev *dev)
+{
+ kfree(dev->sum_tags);
+ dev->sum_tags = NULL;
+ kfree(dev->gc_sum_tags);
+ dev->gc_sum_tags = NULL;
+ dev->chunks_per_summary = 0;
+}
+
+int yaffs_summary_init(struct yaffs_dev *dev)
+{
+ int sum_bytes;
+ int chunks_used; /* Number of chunks used by summary */
+ int sum_tags_bytes;
+
+ sum_bytes = dev->param.chunks_per_block *
+ sizeof(struct yaffs_summary_tags);
+
+ chunks_used = (sum_bytes + dev->data_bytes_per_chunk - 1)/
+ (dev->data_bytes_per_chunk -
+ sizeof(struct yaffs_summary_header));
+
+ dev->chunks_per_summary = dev->param.chunks_per_block - chunks_used;
+ sum_tags_bytes = sizeof(struct yaffs_summary_tags) *
+ dev->chunks_per_summary;
+ dev->sum_tags = kmalloc(sum_tags_bytes, GFP_NOFS);
+ dev->gc_sum_tags = kmalloc(sum_tags_bytes, GFP_NOFS);
+ if (!dev->sum_tags || !dev->gc_sum_tags) {
+ yaffs_summary_deinit(dev);
+ return YAFFS_FAIL;
+ }
+
+ yaffs_summary_clear(dev);
+
+ return YAFFS_OK;
+}
+
+static unsigned yaffs_summary_sum(struct yaffs_dev *dev)
+{
+ u8 *sum_buffer = (u8 *)dev->sum_tags;
+ int i;
+ unsigned sum = 0;
+
+ i = sizeof(struct yaffs_summary_tags) *
+ dev->chunks_per_summary;
+ while (i > 0) {
+ sum += *sum_buffer;
+ sum_buffer++;
+ i--;
+ }
+
+ return sum;
+}
+
+static int yaffs_summary_write(struct yaffs_dev *dev, int blk)
+{
+ struct yaffs_ext_tags tags;
+ u8 *buffer;
+ u8 *sum_buffer = (u8 *)dev->sum_tags;
+ int n_bytes;
+ int chunk_in_nand;
+ int chunk_in_block;
+ int result;
+ int this_tx;
+ struct yaffs_summary_header hdr;
+ int sum_bytes_per_chunk = dev->data_bytes_per_chunk - sizeof(hdr);
+ struct yaffs_block_info *bi = yaffs_get_block_info(dev, blk);
+
+ buffer = yaffs_get_temp_buffer(dev);
+ n_bytes = sizeof(struct yaffs_summary_tags) *
+ dev->chunks_per_summary;
+ memset(&tags, 0, sizeof(struct yaffs_ext_tags));
+ tags.obj_id = YAFFS_OBJECTID_SUMMARY;
+ tags.chunk_id = 1;
+ chunk_in_block = dev->chunks_per_summary;
+ chunk_in_nand = dev->alloc_block * dev->param.chunks_per_block +
+ dev->chunks_per_summary;
+ hdr.version = YAFFS_SUMMARY_VERSION;
+ hdr.block = blk;
+ hdr.seq = bi->seq_number;
+ hdr.sum = yaffs_summary_sum(dev);
+
+ do {
+ this_tx = n_bytes;
+ if (this_tx > sum_bytes_per_chunk)
+ this_tx = sum_bytes_per_chunk;
+ memcpy(buffer, &hdr, sizeof(hdr));
+ memcpy(buffer + sizeof(hdr), sum_buffer, this_tx);
+ tags.n_bytes = this_tx + sizeof(hdr);
+ result = yaffs_wr_chunk_tags_nand(dev, chunk_in_nand,
+ buffer, &tags);
+
+ if (result != YAFFS_OK)
+ break;
+ yaffs_set_chunk_bit(dev, blk, chunk_in_block);
+ bi->pages_in_use++;
+ dev->n_free_chunks--;
+
+ n_bytes -= this_tx;
+ sum_buffer += this_tx;
+ chunk_in_nand++;
+ chunk_in_block++;
+ tags.chunk_id++;
+ } while (result == YAFFS_OK && n_bytes > 0);
+ yaffs_release_temp_buffer(dev, buffer);
+
+
+ if (result == YAFFS_OK)
+ bi->has_summary = 1;
+
+
+ return result;
+}
+
+int yaffs_summary_read(struct yaffs_dev *dev,
+ struct yaffs_summary_tags *st,
+ int blk)
+{
+ struct yaffs_ext_tags tags;
+ u8 *buffer;
+ u8 *sum_buffer = (u8 *)st;
+ int n_bytes;
+ u32 chunk_id;
+ int chunk_in_nand;
+ int chunk_in_block;
+ int result;
+ int this_tx;
+ struct yaffs_summary_header hdr;
+ struct yaffs_block_info *bi = yaffs_get_block_info(dev, blk);
+ int sum_bytes_per_chunk = dev->data_bytes_per_chunk - sizeof(hdr);
+
+ buffer = yaffs_get_temp_buffer(dev);
+ n_bytes = sizeof(struct yaffs_summary_tags) * dev->chunks_per_summary;
+ chunk_in_block = dev->chunks_per_summary;
+ chunk_in_nand = blk * dev->param.chunks_per_block +
+ dev->chunks_per_summary;
+ chunk_id = 1;
+ do {
+ this_tx = n_bytes;
+ if (this_tx > sum_bytes_per_chunk)
+ this_tx = sum_bytes_per_chunk;
+ result = yaffs_rd_chunk_tags_nand(dev, chunk_in_nand,
+ buffer, &tags);
+
+ if (tags.chunk_id != chunk_id ||
+ tags.obj_id != YAFFS_OBJECTID_SUMMARY ||
+ tags.chunk_used == 0 ||
+ tags.ecc_result > YAFFS_ECC_RESULT_FIXED ||
+ tags.n_bytes != (this_tx + sizeof(hdr)))
+ result = YAFFS_FAIL;
+ if (result != YAFFS_OK)
+ break;
+
+ if (st == dev->sum_tags) {
+ /* If we're scanning then update the block info */
+ yaffs_set_chunk_bit(dev, blk, chunk_in_block);
+ bi->pages_in_use++;
+ }
+ memcpy(&hdr, buffer, sizeof(hdr));
+ memcpy(sum_buffer, buffer + sizeof(hdr), this_tx);
+ n_bytes -= this_tx;
+ sum_buffer += this_tx;
+ chunk_in_nand++;
+ chunk_in_block++;
+ chunk_id++;
+ } while (result == YAFFS_OK && n_bytes > 0);
+ yaffs_release_temp_buffer(dev, buffer);
+
+ if (result == YAFFS_OK) {
+ /* Verify header */
+ if (hdr.version != YAFFS_SUMMARY_VERSION ||
+ hdr.seq != bi->seq_number ||
+ hdr.sum != yaffs_summary_sum(dev))
+ result = YAFFS_FAIL;
+ }
+
+ if (st == dev->sum_tags && result == YAFFS_OK)
+ bi->has_summary = 1;
+
+ return result;
+}
+
+int yaffs_summary_add(struct yaffs_dev *dev,
+ struct yaffs_ext_tags *tags,
+ int chunk_in_nand)
+{
+ struct yaffs_packed_tags2_tags_only tags_only;
+ struct yaffs_summary_tags *sum_tags;
+ int block_in_nand = chunk_in_nand / dev->param.chunks_per_block;
+ int chunk_in_block = chunk_in_nand % dev->param.chunks_per_block;
+
+ if (!dev->sum_tags)
+ return YAFFS_OK;
+
+ if (chunk_in_block >= 0 && chunk_in_block < dev->chunks_per_summary) {
+ yaffs_pack_tags2_tags_only(dev, &tags_only, tags);
+ sum_tags = &dev->sum_tags[chunk_in_block];
+
+ sum_tags->chunk_id = tags_only.chunk_id;
+ sum_tags->n_bytes = tags_only.n_bytes;
+ sum_tags->obj_id = tags_only.obj_id;
+
+ if (chunk_in_block == dev->chunks_per_summary - 1) {
+ /* Time to write out the summary */
+ yaffs_summary_write(dev, block_in_nand);
+ yaffs_summary_clear(dev);
+ yaffs_skip_rest_of_block(dev);
+ }
+ }
+ return YAFFS_OK;
+}
+
+int yaffs_summary_fetch(struct yaffs_dev *dev,
+ struct yaffs_ext_tags *tags,
+ int chunk_in_block)
+{
+ struct yaffs_packed_tags2_tags_only tags_only;
+ struct yaffs_summary_tags *sum_tags;
+ if (chunk_in_block >= 0 && chunk_in_block < dev->chunks_per_summary) {
+ sum_tags = &dev->sum_tags[chunk_in_block];
+ tags_only.chunk_id = sum_tags->chunk_id;
+ tags_only.n_bytes = sum_tags->n_bytes;
+ tags_only.obj_id = sum_tags->obj_id;
+ yaffs_unpack_tags2_tags_only(dev, tags, &tags_only);
+ return YAFFS_OK;
+ }
+ return YAFFS_FAIL;
+}
+
+void yaffs_summary_gc(struct yaffs_dev *dev, int blk)
+{
+ struct yaffs_block_info *bi = yaffs_get_block_info(dev, blk);
+ u32 i;
+
+ if (!bi->has_summary)
+ return;
+
+ for (i = dev->chunks_per_summary;
+ i < dev->param.chunks_per_block;
+ i++) {
+ if (yaffs_check_chunk_bit(dev, blk, i)) {
+ yaffs_clear_chunk_bit(dev, blk, i);
+ bi->pages_in_use--;
+ dev->n_free_chunks++;
+ }
+ }
+}
diff -urN linux-4.9.37/fs/yaffs2/yaffs_summary.h linux-4.9.y/fs/yaffs2/yaffs_summary.h
--- linux-4.9.37/fs/yaffs2/yaffs_summary.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/yaffs_summary.h 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,37 @@
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+#ifndef __YAFFS_SUMMARY_H__
+#define __YAFFS_SUMMARY_H__
+
+#include "yaffs_packedtags2.h"
+
+
+int yaffs_summary_init(struct yaffs_dev *dev);
+void yaffs_summary_deinit(struct yaffs_dev *dev);
+
+int yaffs_summary_add(struct yaffs_dev *dev,
+ struct yaffs_ext_tags *tags,
+ int chunk_in_block);
+int yaffs_summary_fetch(struct yaffs_dev *dev,
+ struct yaffs_ext_tags *tags,
+ int chunk_in_block);
+int yaffs_summary_read(struct yaffs_dev *dev,
+ struct yaffs_summary_tags *st,
+ int blk);
+void yaffs_summary_gc(struct yaffs_dev *dev, int blk);
+
+
+#endif
diff -urN linux-4.9.37/fs/yaffs2/yaffs_tagscompat.c linux-4.9.y/fs/yaffs2/yaffs_tagscompat.c
--- linux-4.9.37/fs/yaffs2/yaffs_tagscompat.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/yaffs_tagscompat.c 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,400 @@
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * 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.
+ *
+ * This file handles yaffs1-style tags to allow compatibility with Yaffs1 style
+ * flash layouts.
+ */
+
+#include "yaffs_guts.h"
+#include "yaffs_tagscompat.h"
+#include "yaffs_ecc.h"
+#include "yaffs_getblockinfo.h"
+#include "yaffs_trace.h"
+#include "yaffs_endian.h"
+
+static void yaffs_handle_rd_data_error(struct yaffs_dev *dev, int nand_chunk);
+
+
+/********** Tags ECC calculations *********/
+
+void yaffs_calc_tags_ecc(struct yaffs_tags *tags)
+{
+ /* Calculate an ecc */
+ unsigned char *b = ((union yaffs_tags_union *)tags)->as_bytes;
+ unsigned i, j;
+ unsigned ecc = 0;
+ unsigned bit = 0;
+
+ tags->ecc = 0;
+
+ for (i = 0; i < 8; i++) {
+ for (j = 1; j & 0xff; j <<= 1) {
+ bit++;
+ if (b[i] & j)
+ ecc ^= bit;
+ }
+ }
+ tags->ecc = ecc;
+}
+
+int yaffs_check_tags_ecc(struct yaffs_tags *tags)
+{
+ unsigned ecc = tags->ecc;
+
+ yaffs_calc_tags_ecc(tags);
+
+ ecc ^= tags->ecc;
+
+ if (ecc && ecc <= 64) {
+ /* TODO: Handle the failure better. Retire? */
+ unsigned char *b = ((union yaffs_tags_union *)tags)->as_bytes;
+
+ ecc--;
+
+ b[ecc / 8] ^= (1 << (ecc & 7));
+
+ /* Now recvalc the ecc */
+ yaffs_calc_tags_ecc(tags);
+
+ return 1; /* recovered error */
+ } else if (ecc) {
+ /* Wierd ecc failure value */
+ /* TODO Need to do somethiong here */
+ return -1; /* unrecovered error */
+ }
+ return 0;
+}
+
+/********** Tags **********/
+
+/*
+ * During tags storing/retireval we use a copy of the tags so that
+ * we can modify the endian etc without damaging the previous structure.
+ */
+static void yaffs_load_tags_to_spare(struct yaffs_dev *dev,
+ struct yaffs_spare *spare_ptr,
+ struct yaffs_tags *tags_ptr)
+{
+ union yaffs_tags_union *tu_ptr = (union yaffs_tags_union *)tags_ptr;
+ union yaffs_tags_union tags_stored = *tu_ptr;
+
+ yaffs_calc_tags_ecc(&tags_stored.as_tags);
+
+ yaffs_do_endian_u32(dev, &tags_stored.as_u32[0]);
+ yaffs_do_endian_u32(dev, &tags_stored.as_u32[1]);
+
+ spare_ptr->tb0 = tags_stored.as_bytes[0];
+ spare_ptr->tb1 = tags_stored.as_bytes[1];
+ spare_ptr->tb2 = tags_stored.as_bytes[2];
+ spare_ptr->tb3 = tags_stored.as_bytes[3];
+ spare_ptr->tb4 = tags_stored.as_bytes[4];
+ spare_ptr->tb5 = tags_stored.as_bytes[5];
+ spare_ptr->tb6 = tags_stored.as_bytes[6];
+ spare_ptr->tb7 = tags_stored.as_bytes[7];
+}
+
+static void yaffs_get_tags_from_spare(struct yaffs_dev *dev,
+ struct yaffs_spare *spare_ptr,
+ struct yaffs_tags *tags_ptr)
+{
+ union yaffs_tags_union *tu = (union yaffs_tags_union *)tags_ptr;
+ union yaffs_tags_union tags_stored;
+ int result;
+
+ tags_stored.as_bytes[0] = spare_ptr->tb0;
+ tags_stored.as_bytes[1] = spare_ptr->tb1;
+ tags_stored.as_bytes[2] = spare_ptr->tb2;
+ tags_stored.as_bytes[3] = spare_ptr->tb3;
+ tags_stored.as_bytes[4] = spare_ptr->tb4;
+ tags_stored.as_bytes[5] = spare_ptr->tb5;
+ tags_stored.as_bytes[6] = spare_ptr->tb6;
+ tags_stored.as_bytes[7] = spare_ptr->tb7;
+
+ yaffs_do_endian_u32(dev, &tags_stored.as_u32[0]);
+ yaffs_do_endian_u32(dev, &tags_stored.as_u32[1]);
+
+ *tu = tags_stored;
+
+ result = yaffs_check_tags_ecc(tags_ptr);
+ if (result > 0)
+ dev->n_tags_ecc_fixed++;
+ else if (result < 0)
+ dev->n_tags_ecc_unfixed++;
+}
+
+static void yaffs_spare_init(struct yaffs_spare *spare)
+{
+ memset(spare, 0xff, sizeof(struct yaffs_spare));
+}
+
+static int yaffs_wr_nand(struct yaffs_dev *dev,
+ int nand_chunk, const u8 *data,
+ struct yaffs_spare *spare)
+{
+ int data_size = dev->data_bytes_per_chunk;
+
+ return dev->drv.drv_write_chunk_fn(dev, nand_chunk,
+ data, data_size,
+ (u8 *) spare, sizeof(*spare));
+}
+
+static int yaffs_rd_chunk_nand(struct yaffs_dev *dev,
+ int nand_chunk,
+ u8 *data,
+ struct yaffs_spare *spare,
+ enum yaffs_ecc_result *ecc_result,
+ int correct_errors)
+{
+ int ret_val;
+ struct yaffs_spare local_spare;
+ int data_size;
+ int spare_size;
+ int ecc_result1, ecc_result2;
+ u8 calc_ecc[3];
+
+ if (!spare) {
+ /* If we don't have a real spare, then we use a local one. */
+ /* Need this for the calculation of the ecc */
+ spare = &local_spare;
+ }
+ data_size = dev->data_bytes_per_chunk;
+ spare_size = sizeof(struct yaffs_spare);
+
+ if (dev->param.use_nand_ecc)
+ return dev->drv.drv_read_chunk_fn(dev, nand_chunk,
+ data, data_size,
+ (u8 *) spare, spare_size,
+ ecc_result);
+
+
+ /* Handle the ECC at this level. */
+
+ ret_val = dev->drv.drv_read_chunk_fn(dev, nand_chunk,
+ data, data_size,
+ (u8 *)spare, spare_size,
+ NULL);
+ if (!data || !correct_errors)
+ return ret_val;
+
+ /* Do ECC correction if needed. */
+ yaffs_ecc_calc(data, calc_ecc);
+ ecc_result1 = yaffs_ecc_correct(data, spare->ecc1, calc_ecc);
+ yaffs_ecc_calc(&data[256], calc_ecc);
+ ecc_result2 = yaffs_ecc_correct(&data[256], spare->ecc2, calc_ecc);
+
+ if (ecc_result1 > 0) {
+ yaffs_trace(YAFFS_TRACE_ERROR,
+ "**>>yaffs ecc error fix performed on chunk %d:0",
+ nand_chunk);
+ dev->n_ecc_fixed++;
+ } else if (ecc_result1 < 0) {
+ yaffs_trace(YAFFS_TRACE_ERROR,
+ "**>>yaffs ecc error unfixed on chunk %d:0",
+ nand_chunk);
+ dev->n_ecc_unfixed++;
+ }
+
+ if (ecc_result2 > 0) {
+ yaffs_trace(YAFFS_TRACE_ERROR,
+ "**>>yaffs ecc error fix performed on chunk %d:1",
+ nand_chunk);
+ dev->n_ecc_fixed++;
+ } else if (ecc_result2 < 0) {
+ yaffs_trace(YAFFS_TRACE_ERROR,
+ "**>>yaffs ecc error unfixed on chunk %d:1",
+ nand_chunk);
+ dev->n_ecc_unfixed++;
+ }
+
+ if (ecc_result1 || ecc_result2) {
+ /* We had a data problem on this page */
+ yaffs_handle_rd_data_error(dev, nand_chunk);
+ }
+
+ if (ecc_result1 < 0 || ecc_result2 < 0)
+ *ecc_result = YAFFS_ECC_RESULT_UNFIXED;
+ else if (ecc_result1 > 0 || ecc_result2 > 0)
+ *ecc_result = YAFFS_ECC_RESULT_FIXED;
+ else
+ *ecc_result = YAFFS_ECC_RESULT_NO_ERROR;
+
+ return ret_val;
+}
+
+/*
+ * Functions for robustisizing
+ */
+
+static void yaffs_handle_rd_data_error(struct yaffs_dev *dev, int nand_chunk)
+{
+ int flash_block = nand_chunk / dev->param.chunks_per_block;
+
+ /* Mark the block for retirement */
+ yaffs_get_block_info(dev, flash_block + dev->block_offset)->
+ needs_retiring = 1;
+ yaffs_trace(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,
+ "**>>Block %d marked for retirement",
+ flash_block);
+
+ /* TODO:
+ * Just do a garbage collection on the affected block
+ * then retire the block
+ * NB recursion
+ */
+}
+
+static int yaffs_tags_compat_wr(struct yaffs_dev *dev,
+ int nand_chunk,
+ const u8 *data, const struct yaffs_ext_tags *ext_tags)
+{
+ struct yaffs_spare spare;
+ struct yaffs_tags tags;
+
+ yaffs_spare_init(&spare);
+
+ if (ext_tags->is_deleted)
+ spare.page_status = 0;
+ else {
+ tags.obj_id = ext_tags->obj_id;
+ tags.chunk_id = ext_tags->chunk_id;
+
+ tags.n_bytes_lsb = ext_tags->n_bytes & (1024 - 1);
+
+ if (dev->data_bytes_per_chunk >= 1024)
+ tags.n_bytes_msb = (ext_tags->n_bytes >> 10) & 3;
+ else
+ tags.n_bytes_msb = 3;
+
+ tags.serial_number = ext_tags->serial_number;
+
+ if (!dev->param.use_nand_ecc && data) {
+ yaffs_ecc_calc(data, spare.ecc1);
+ yaffs_ecc_calc(&data[256], spare.ecc2);
+ }
+
+ yaffs_load_tags_to_spare(dev, &spare, &tags);
+ }
+ return yaffs_wr_nand(dev, nand_chunk, data, &spare);
+}
+
+static int yaffs_tags_compat_rd(struct yaffs_dev *dev,
+ int nand_chunk,
+ u8 *data, struct yaffs_ext_tags *ext_tags)
+{
+ struct yaffs_spare spare;
+ struct yaffs_tags tags;
+ enum yaffs_ecc_result ecc_result = YAFFS_ECC_RESULT_UNKNOWN;
+ static struct yaffs_spare spare_ff;
+ static int init;
+ int deleted;
+
+ if (!init) {
+ memset(&spare_ff, 0xff, sizeof(spare_ff));
+ init = 1;
+ }
+
+ if (!yaffs_rd_chunk_nand(dev, nand_chunk,
+ data, &spare, &ecc_result, 1))
+ return YAFFS_FAIL;
+
+ /* ext_tags may be NULL */
+ if (!ext_tags)
+ return YAFFS_OK;
+
+ deleted = (hweight8(spare.page_status) < 7) ? 1 : 0;
+
+ ext_tags->is_deleted = deleted;
+ ext_tags->ecc_result = ecc_result;
+ ext_tags->block_bad = 0; /* We're reading it */
+ /* therefore it is not a bad block */
+ ext_tags->chunk_used =
+ memcmp(&spare_ff, &spare, sizeof(spare_ff)) ? 1 : 0;
+
+ if (ext_tags->chunk_used) {
+ yaffs_get_tags_from_spare(dev, &spare, &tags);
+
+ ext_tags->obj_id = tags.obj_id;
+ ext_tags->chunk_id = tags.chunk_id;
+ ext_tags->n_bytes = tags.n_bytes_lsb;
+
+ if (dev->data_bytes_per_chunk >= 1024)
+ ext_tags->n_bytes |=
+ (((unsigned)tags.n_bytes_msb) << 10);
+
+ ext_tags->serial_number = tags.serial_number;
+ }
+
+ return YAFFS_OK;
+}
+
+static int yaffs_tags_compat_mark_bad(struct yaffs_dev *dev, int flash_block)
+{
+ struct yaffs_spare spare;
+
+ memset(&spare, 0xff, sizeof(struct yaffs_spare));
+
+ spare.block_status = 'Y';
+
+ yaffs_wr_nand(dev, flash_block * dev->param.chunks_per_block, NULL,
+ &spare);
+ yaffs_wr_nand(dev, flash_block * dev->param.chunks_per_block + 1,
+ NULL, &spare);
+
+ return YAFFS_OK;
+}
+
+static int yaffs_tags_compat_query_block(struct yaffs_dev *dev,
+ int block_no,
+ enum yaffs_block_state *state,
+ u32 *seq_number)
+{
+ struct yaffs_spare spare0, spare1;
+ static struct yaffs_spare spare_ff;
+ static int init;
+ enum yaffs_ecc_result dummy;
+
+ if (!init) {
+ memset(&spare_ff, 0xff, sizeof(spare_ff));
+ init = 1;
+ }
+
+ *seq_number = 0;
+
+ /* Look for bad block markers in the first two chunks */
+ yaffs_rd_chunk_nand(dev, block_no * dev->param.chunks_per_block,
+ NULL, &spare0, &dummy, 0);
+ yaffs_rd_chunk_nand(dev, block_no * dev->param.chunks_per_block + 1,
+ NULL, &spare1, &dummy, 0);
+
+ if (hweight8(spare0.block_status & spare1.block_status) < 7)
+ *state = YAFFS_BLOCK_STATE_DEAD;
+ else if (memcmp(&spare_ff, &spare0, sizeof(spare_ff)) == 0)
+ *state = YAFFS_BLOCK_STATE_EMPTY;
+ else
+ *state = YAFFS_BLOCK_STATE_NEEDS_SCAN;
+
+ return YAFFS_OK;
+}
+
+void yaffs_tags_compat_install(struct yaffs_dev *dev)
+{
+ if(dev->param.is_yaffs2)
+ return;
+ if(!dev->tagger.write_chunk_tags_fn)
+ dev->tagger.write_chunk_tags_fn = yaffs_tags_compat_wr;
+ if(!dev->tagger.read_chunk_tags_fn)
+ dev->tagger.read_chunk_tags_fn = yaffs_tags_compat_rd;
+ if(!dev->tagger.query_block_fn)
+ dev->tagger.query_block_fn = yaffs_tags_compat_query_block;
+ if(!dev->tagger.mark_bad_fn)
+ dev->tagger.mark_bad_fn = yaffs_tags_compat_mark_bad;
+}
diff -urN linux-4.9.37/fs/yaffs2/yaffs_tagscompat.h linux-4.9.y/fs/yaffs2/yaffs_tagscompat.h
--- linux-4.9.37/fs/yaffs2/yaffs_tagscompat.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/yaffs_tagscompat.h 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,44 @@
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+#ifndef __YAFFS_TAGSCOMPAT_H__
+#define __YAFFS_TAGSCOMPAT_H__
+
+
+#include "yaffs_guts.h"
+
+#if 0
+
+
+int yaffs_tags_compat_wr(struct yaffs_dev *dev,
+ int nand_chunk,
+ const u8 *data, const struct yaffs_ext_tags *tags);
+int yaffs_tags_compat_rd(struct yaffs_dev *dev,
+ int nand_chunk,
+ u8 *data, struct yaffs_ext_tags *tags);
+int yaffs_tags_compat_mark_bad(struct yaffs_dev *dev, int block_no);
+int yaffs_tags_compat_query_block(struct yaffs_dev *dev,
+ int block_no,
+ enum yaffs_block_state *state,
+ u32 *seq_number);
+
+#endif
+
+
+void yaffs_tags_compat_install(struct yaffs_dev *dev);
+void yaffs_calc_tags_ecc(struct yaffs_tags *tags);
+int yaffs_check_tags_ecc(struct yaffs_tags *tags);
+
+#endif
diff -urN linux-4.9.37/fs/yaffs2/yaffs_tagsmarshall.c linux-4.9.y/fs/yaffs2/yaffs_tagsmarshall.c
--- linux-4.9.37/fs/yaffs2/yaffs_tagsmarshall.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/yaffs_tagsmarshall.c 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,206 @@
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * 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.
+ *
+ * This file handles the marshalling (ie internal<-->external structure
+ * translation between the internal tags and the stored tags in Yaffs2-style
+ * tags storage.
+ */
+
+#include "yaffs_guts.h"
+#include "yaffs_trace.h"
+#include "yaffs_packedtags2.h"
+
+static int yaffs_tags_marshall_write(struct yaffs_dev *dev,
+ int nand_chunk, const u8 *data,
+ const struct yaffs_ext_tags *tags)
+{
+ struct yaffs_packed_tags2 pt;
+ int retval;
+
+ int packed_tags_size =
+ dev->param.no_tags_ecc ? sizeof(pt.t) : sizeof(pt);
+ void *packed_tags_ptr =
+ dev->param.no_tags_ecc ? (void *)&pt.t : (void *)&pt;
+
+ yaffs_trace(YAFFS_TRACE_MTD,
+ "yaffs_tags_marshall_write chunk %d data %p tags %p",
+ nand_chunk, data, tags);
+
+ /* For yaffs2 writing there must be both data and tags.
+ * If we're using inband tags, then the tags are stuffed into
+ * the end of the data buffer.
+ */
+ if (!data || !tags)
+ BUG();
+ else if (dev->param.inband_tags) {
+ struct yaffs_packed_tags2_tags_only *pt2tp;
+ pt2tp =
+ (struct yaffs_packed_tags2_tags_only *)(data +
+ dev->
+ data_bytes_per_chunk);
+ yaffs_pack_tags2_tags_only(dev, pt2tp, tags);
+ } else {
+ yaffs_pack_tags2(dev, &pt, tags, !dev->param.no_tags_ecc);
+ }
+
+ retval = dev->drv.drv_write_chunk_fn(dev, nand_chunk,
+ data, dev->param.total_bytes_per_chunk,
+ (dev->param.inband_tags) ? NULL : packed_tags_ptr,
+ (dev->param.inband_tags) ? 0 : packed_tags_size);
+
+ return retval;
+}
+
+static int yaffs_tags_marshall_read(struct yaffs_dev *dev,
+ int nand_chunk, u8 *data,
+ struct yaffs_ext_tags *tags)
+{
+ int retval = 0;
+ int local_data = 0;
+ u8 spare_buffer[100];
+ enum yaffs_ecc_result ecc_result;
+
+ struct yaffs_packed_tags2 pt;
+
+ int packed_tags_size =
+ dev->param.no_tags_ecc ? sizeof(pt.t) : sizeof(pt);
+ void *packed_tags_ptr =
+ dev->param.no_tags_ecc ? (void *)&pt.t : (void *)&pt;
+
+ yaffs_trace(YAFFS_TRACE_MTD,
+ "yaffs_tags_marshall_read chunk %d data %p tags %p",
+ nand_chunk, data, tags);
+
+ if (dev->param.inband_tags) {
+ if (!data) {
+ local_data = 1;
+ data = yaffs_get_temp_buffer(dev);
+ }
+ }
+
+ if (dev->param.inband_tags || (data && !tags))
+ retval = dev->drv.drv_read_chunk_fn(dev, nand_chunk,
+ data, dev->param.total_bytes_per_chunk,
+ NULL, 0,
+ &ecc_result);
+ else if (tags)
+ retval = dev->drv.drv_read_chunk_fn(dev, nand_chunk,
+ data, dev->param.total_bytes_per_chunk,
+ spare_buffer, packed_tags_size,
+ &ecc_result);
+ else
+ BUG();
+
+
+ if (retval == YAFFS_FAIL)
+ return YAFFS_FAIL;
+
+ if (dev->param.inband_tags) {
+ if (tags) {
+ struct yaffs_packed_tags2_tags_only *pt2tp;
+ pt2tp =
+ (struct yaffs_packed_tags2_tags_only *)
+ &data[dev->data_bytes_per_chunk];
+ yaffs_unpack_tags2_tags_only(dev, tags, pt2tp);
+ }
+ } else if (tags) {
+ memcpy(packed_tags_ptr, spare_buffer, packed_tags_size);
+ yaffs_unpack_tags2(dev, tags, &pt, !dev->param.no_tags_ecc);
+ }
+
+ if (local_data)
+ yaffs_release_temp_buffer(dev, data);
+
+ if (tags && ecc_result == YAFFS_ECC_RESULT_UNFIXED) {
+ tags->ecc_result = YAFFS_ECC_RESULT_UNFIXED;
+ dev->n_ecc_unfixed++;
+ }
+
+ if (tags && ecc_result == YAFFS_ECC_RESULT_FIXED) {
+ if (tags->ecc_result <= YAFFS_ECC_RESULT_NO_ERROR)
+ tags->ecc_result = YAFFS_ECC_RESULT_FIXED;
+ dev->n_ecc_fixed++;
+ }
+
+ if (ecc_result < YAFFS_ECC_RESULT_UNFIXED)
+ return YAFFS_OK;
+ else
+ return YAFFS_FAIL;
+}
+
+static int yaffs_tags_marshall_query_block(struct yaffs_dev *dev, int block_no,
+ enum yaffs_block_state *state,
+ u32 *seq_number)
+{
+ int retval;
+
+ yaffs_trace(YAFFS_TRACE_MTD, "yaffs_tags_marshall_query_block %d",
+ block_no);
+
+ retval = dev->drv.drv_check_bad_fn(dev, block_no);
+
+ if (retval== YAFFS_FAIL) {
+ yaffs_trace(YAFFS_TRACE_MTD, "block is bad");
+
+ *state = YAFFS_BLOCK_STATE_DEAD;
+ *seq_number = 0;
+ } else {
+ struct yaffs_ext_tags t;
+
+ yaffs_tags_marshall_read(dev,
+ block_no * dev->param.chunks_per_block,
+ NULL, &t);
+
+ if (t.chunk_used) {
+ *seq_number = t.seq_number;
+ *state = YAFFS_BLOCK_STATE_NEEDS_SCAN;
+ } else {
+ *seq_number = 0;
+ *state = YAFFS_BLOCK_STATE_EMPTY;
+ }
+ }
+
+ yaffs_trace(YAFFS_TRACE_MTD,
+ "block query returns seq %d state %d",
+ *seq_number, *state);
+
+ if (retval == 0)
+ return YAFFS_OK;
+ else
+ return YAFFS_FAIL;
+}
+
+static int yaffs_tags_marshall_mark_bad(struct yaffs_dev *dev, int block_no)
+{
+ return dev->drv.drv_mark_bad_fn(dev, block_no);
+
+}
+
+
+void yaffs_tags_marshall_install(struct yaffs_dev *dev)
+{
+ if (!dev->param.is_yaffs2)
+ return;
+
+ if (!dev->tagger.write_chunk_tags_fn)
+ dev->tagger.write_chunk_tags_fn = yaffs_tags_marshall_write;
+
+ if (!dev->tagger.read_chunk_tags_fn)
+ dev->tagger.read_chunk_tags_fn = yaffs_tags_marshall_read;
+
+ if (!dev->tagger.query_block_fn)
+ dev->tagger.query_block_fn = yaffs_tags_marshall_query_block;
+
+ if (!dev->tagger.mark_bad_fn)
+ dev->tagger.mark_bad_fn = yaffs_tags_marshall_mark_bad;
+
+}
diff -urN linux-4.9.37/fs/yaffs2/yaffs_tagsmarshall.h linux-4.9.y/fs/yaffs2/yaffs_tagsmarshall.h
--- linux-4.9.37/fs/yaffs2/yaffs_tagsmarshall.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/yaffs_tagsmarshall.h 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,22 @@
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+#ifndef __YAFFS_TAGSMARSHALL_H__
+#define __YAFFS_TAGSMARSHALL_H__
+
+#include "yaffs_guts.h"
+void yaffs_tags_marshall_install(struct yaffs_dev *dev);
+
+#endif
diff -urN linux-4.9.37/fs/yaffs2/yaffs_trace.h linux-4.9.y/fs/yaffs2/yaffs_trace.h
--- linux-4.9.37/fs/yaffs2/yaffs_trace.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/yaffs_trace.h 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,57 @@
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+#ifndef __YTRACE_H__
+#define __YTRACE_H__
+
+extern unsigned int yaffs_trace_mask;
+extern unsigned int yaffs_wr_attempts;
+
+/*
+ * Tracing flags.
+ * The flags masked in YAFFS_TRACE_ALWAYS are always traced.
+ */
+
+#define YAFFS_TRACE_OS 0x00000002
+#define YAFFS_TRACE_ALLOCATE 0x00000004
+#define YAFFS_TRACE_SCAN 0x00000008
+#define YAFFS_TRACE_BAD_BLOCKS 0x00000010
+#define YAFFS_TRACE_ERASE 0x00000020
+#define YAFFS_TRACE_GC 0x00000040
+#define YAFFS_TRACE_WRITE 0x00000080
+#define YAFFS_TRACE_TRACING 0x00000100
+#define YAFFS_TRACE_DELETION 0x00000200
+#define YAFFS_TRACE_BUFFERS 0x00000400
+#define YAFFS_TRACE_NANDACCESS 0x00000800
+#define YAFFS_TRACE_GC_DETAIL 0x00001000
+#define YAFFS_TRACE_SCAN_DEBUG 0x00002000
+#define YAFFS_TRACE_MTD 0x00004000
+#define YAFFS_TRACE_CHECKPOINT 0x00008000
+
+#define YAFFS_TRACE_VERIFY 0x00010000
+#define YAFFS_TRACE_VERIFY_NAND 0x00020000
+#define YAFFS_TRACE_VERIFY_FULL 0x00040000
+#define YAFFS_TRACE_VERIFY_ALL 0x000f0000
+
+#define YAFFS_TRACE_SYNC 0x00100000
+#define YAFFS_TRACE_BACKGROUND 0x00200000
+#define YAFFS_TRACE_LOCK 0x00400000
+#define YAFFS_TRACE_MOUNT 0x00800000
+
+#define YAFFS_TRACE_ERROR 0x40000000
+#define YAFFS_TRACE_BUG 0x80000000
+#define YAFFS_TRACE_ALWAYS 0xf0000000
+
+#endif
diff -urN linux-4.9.37/fs/yaffs2/yaffs_verify.c linux-4.9.y/fs/yaffs2/yaffs_verify.c
--- linux-4.9.37/fs/yaffs2/yaffs_verify.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/yaffs_verify.c 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,540 @@
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * 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 "yaffs_verify.h"
+#include "yaffs_trace.h"
+#include "yaffs_bitmap.h"
+#include "yaffs_getblockinfo.h"
+#include "yaffs_nand.h"
+
+int yaffs_skip_verification(struct yaffs_dev *dev)
+{
+ (void) dev;
+ return !(yaffs_trace_mask &
+ (YAFFS_TRACE_VERIFY | YAFFS_TRACE_VERIFY_FULL));
+}
+
+static int yaffs_skip_full_verification(struct yaffs_dev *dev)
+{
+ (void) dev;
+ return !(yaffs_trace_mask & (YAFFS_TRACE_VERIFY_FULL));
+}
+
+static int yaffs_skip_nand_verification(struct yaffs_dev *dev)
+{
+ (void) dev;
+ return !(yaffs_trace_mask & (YAFFS_TRACE_VERIFY_NAND));
+}
+
+static const char * const block_state_name[] = {
+ "Unknown",
+ "Needs scan",
+ "Scanning",
+ "Empty",
+ "Allocating",
+ "Full",
+ "Dirty",
+ "Checkpoint",
+ "Collecting",
+ "Dead"
+};
+
+void yaffs_verify_blk(struct yaffs_dev *dev, struct yaffs_block_info *bi, int n)
+{
+ int actually_used;
+ int in_use;
+
+ if (yaffs_skip_verification(dev))
+ return;
+
+ /* Report illegal runtime states */
+ if (bi->block_state >= YAFFS_NUMBER_OF_BLOCK_STATES)
+ yaffs_trace(YAFFS_TRACE_VERIFY,
+ "Block %d has undefined state %d",
+ n, bi->block_state);
+
+ switch (bi->block_state) {
+ case YAFFS_BLOCK_STATE_UNKNOWN:
+ case YAFFS_BLOCK_STATE_SCANNING:
+ case YAFFS_BLOCK_STATE_NEEDS_SCAN:
+ yaffs_trace(YAFFS_TRACE_VERIFY,
+ "Block %d has bad run-state %s",
+ n, block_state_name[bi->block_state]);
+ }
+
+ /* Check pages in use and soft deletions are legal */
+
+ actually_used = bi->pages_in_use - bi->soft_del_pages;
+
+ if (bi->pages_in_use < 0 ||
+ bi->pages_in_use > (int)dev->param.chunks_per_block ||
+ bi->soft_del_pages < 0 ||
+ bi->soft_del_pages > (int)dev->param.chunks_per_block ||
+ actually_used < 0 || actually_used > (int)dev->param.chunks_per_block)
+ yaffs_trace(YAFFS_TRACE_VERIFY,
+ "Block %d has illegal values pages_in_used %d soft_del_pages %d",
+ n, bi->pages_in_use, bi->soft_del_pages);
+
+ /* Check chunk bitmap legal */
+ in_use = yaffs_count_chunk_bits(dev, n);
+ if (in_use != bi->pages_in_use)
+ yaffs_trace(YAFFS_TRACE_VERIFY,
+ "Block %d has inconsistent values pages_in_use %d counted chunk bits %d",
+ n, bi->pages_in_use, in_use);
+}
+
+void yaffs_verify_collected_blk(struct yaffs_dev *dev,
+ struct yaffs_block_info *bi, int n)
+{
+ yaffs_verify_blk(dev, bi, n);
+
+ /* After collection the block should be in the erased state */
+
+ if (bi->block_state != YAFFS_BLOCK_STATE_COLLECTING &&
+ bi->block_state != YAFFS_BLOCK_STATE_EMPTY) {
+ yaffs_trace(YAFFS_TRACE_ERROR,
+ "Block %d is in state %d after gc, should be erased",
+ n, bi->block_state);
+ }
+}
+
+void yaffs_verify_blocks(struct yaffs_dev *dev)
+{
+ u32 i;
+ u32 state_count[YAFFS_NUMBER_OF_BLOCK_STATES];
+ int illegal_states = 0;
+
+ if (yaffs_skip_verification(dev))
+ return;
+
+ memset(state_count, 0, sizeof(state_count));
+
+ for (i = dev->internal_start_block; i <= dev->internal_end_block; i++) {
+ struct yaffs_block_info *bi = yaffs_get_block_info(dev, i);
+ yaffs_verify_blk(dev, bi, i);
+
+ if (bi->block_state < YAFFS_NUMBER_OF_BLOCK_STATES)
+ state_count[bi->block_state]++;
+ else
+ illegal_states++;
+ }
+
+ yaffs_trace(YAFFS_TRACE_VERIFY, "Block summary");
+
+ yaffs_trace(YAFFS_TRACE_VERIFY,
+ "%d blocks have illegal states",
+ illegal_states);
+ if (state_count[YAFFS_BLOCK_STATE_ALLOCATING] > 1)
+ yaffs_trace(YAFFS_TRACE_VERIFY,
+ "Too many allocating blocks");
+
+ for (i = 0; i < YAFFS_NUMBER_OF_BLOCK_STATES; i++)
+ yaffs_trace(YAFFS_TRACE_VERIFY,
+ "%s %d blocks",
+ block_state_name[i], state_count[i]);
+
+ if (dev->blocks_in_checkpt != state_count[YAFFS_BLOCK_STATE_CHECKPOINT])
+ yaffs_trace(YAFFS_TRACE_VERIFY,
+ "Checkpoint block count wrong dev %d count %d",
+ dev->blocks_in_checkpt,
+ state_count[YAFFS_BLOCK_STATE_CHECKPOINT]);
+
+ if (dev->n_erased_blocks != (int)state_count[YAFFS_BLOCK_STATE_EMPTY])
+ yaffs_trace(YAFFS_TRACE_VERIFY,
+ "Erased block count wrong dev %d count %d",
+ dev->n_erased_blocks,
+ state_count[YAFFS_BLOCK_STATE_EMPTY]);
+
+ if (state_count[YAFFS_BLOCK_STATE_COLLECTING] > 1)
+ yaffs_trace(YAFFS_TRACE_VERIFY,
+ "Too many collecting blocks %d (max is 1)",
+ state_count[YAFFS_BLOCK_STATE_COLLECTING]);
+}
+
+/*
+ * Verify the object header. oh must be valid, but obj and tags may be NULL in
+ * which case those tests will not be performed.
+ */
+void yaffs_verify_oh(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh,
+ struct yaffs_ext_tags *tags, int parent_check)
+{
+ if (obj && yaffs_skip_verification(obj->my_dev))
+ return;
+
+ if (!(tags && obj && oh)) {
+ yaffs_trace(YAFFS_TRACE_VERIFY,
+ "Verifying object header tags %p obj %p oh %p",
+ tags, obj, oh);
+ return;
+ }
+
+ if (oh->type <= YAFFS_OBJECT_TYPE_UNKNOWN ||
+ oh->type > YAFFS_OBJECT_TYPE_MAX)
+ yaffs_trace(YAFFS_TRACE_VERIFY,
+ "Obj %d header type is illegal value 0x%x",
+ tags->obj_id, oh->type);
+
+ if (tags->obj_id != obj->obj_id)
+ yaffs_trace(YAFFS_TRACE_VERIFY,
+ "Obj %d header mismatch obj_id %d",
+ tags->obj_id, obj->obj_id);
+
+ /*
+ * Check that the object's parent ids match if parent_check requested.
+ *
+ * Tests do not apply to the root object.
+ */
+
+ if (parent_check && tags->obj_id > 1 && !obj->parent)
+ yaffs_trace(YAFFS_TRACE_VERIFY,
+ "Obj %d header mismatch parent_id %d obj->parent is NULL",
+ tags->obj_id, oh->parent_obj_id);
+
+ if (parent_check && obj->parent &&
+ oh->parent_obj_id != obj->parent->obj_id &&
+ (oh->parent_obj_id != YAFFS_OBJECTID_UNLINKED ||
+ obj->parent->obj_id != YAFFS_OBJECTID_DELETED))
+ yaffs_trace(YAFFS_TRACE_VERIFY,
+ "Obj %d header mismatch parent_id %d parent_obj_id %d",
+ tags->obj_id, oh->parent_obj_id,
+ obj->parent->obj_id);
+
+ if (tags->obj_id > 1 && oh->name[0] == 0) /* Null name */
+ yaffs_trace(YAFFS_TRACE_VERIFY,
+ "Obj %d header name is NULL",
+ obj->obj_id);
+
+ if (tags->obj_id > 1 && ((u8) (oh->name[0])) == 0xff) /* Junk name */
+ yaffs_trace(YAFFS_TRACE_VERIFY,
+ "Obj %d header name is 0xff",
+ obj->obj_id);
+}
+
+void yaffs_verify_file(struct yaffs_obj *obj)
+{
+ u32 x;
+ int required_depth;
+ int last_chunk;
+ u32 offset_in_chunk;
+ u32 the_chunk;
+
+ int i;
+ struct yaffs_dev *dev;
+ struct yaffs_ext_tags tags;
+ struct yaffs_tnode *tn;
+ u32 obj_id;
+
+ if (!obj)
+ return;
+
+ if (yaffs_skip_verification(obj->my_dev))
+ return;
+
+ dev = obj->my_dev;
+ obj_id = obj->obj_id;
+
+
+ /* Check file size is consistent with tnode depth */
+ yaffs_addr_to_chunk(dev, obj->variant.file_variant.file_size,
+ &last_chunk, &offset_in_chunk);
+ last_chunk++;
+ x = last_chunk >> YAFFS_TNODES_LEVEL0_BITS;
+ required_depth = 0;
+ while (x > 0) {
+ x >>= YAFFS_TNODES_INTERNAL_BITS;
+ required_depth++;
+ }
+
+ /* Check that the chunks in the tnode tree are all correct.
+ * We do this by scanning through the tnode tree and
+ * checking the tags for every chunk match.
+ */
+
+ if (yaffs_skip_nand_verification(dev))
+ return;
+
+ for (i = 1; i <= last_chunk; i++) {
+ tn = yaffs_find_tnode_0(dev, &obj->variant.file_variant, i);
+
+ if (!tn)
+ continue;
+
+ the_chunk = yaffs_get_group_base(dev, tn, i);
+ if (the_chunk > 0) {
+ yaffs_rd_chunk_tags_nand(dev, the_chunk, NULL,
+ &tags);
+ if (tags.obj_id != obj_id || tags.chunk_id != (u32)i)
+ yaffs_trace(YAFFS_TRACE_VERIFY,
+ "Object %d chunk_id %d NAND mismatch chunk %d tags (%d:%d)",
+ obj_id, i, the_chunk,
+ tags.obj_id, tags.chunk_id);
+ }
+ }
+}
+
+void yaffs_verify_link(struct yaffs_obj *obj)
+{
+ if (obj && yaffs_skip_verification(obj->my_dev))
+ return;
+
+ /* Verify sane equivalent object */
+}
+
+void yaffs_verify_symlink(struct yaffs_obj *obj)
+{
+ if (obj && yaffs_skip_verification(obj->my_dev))
+ return;
+
+ /* Verify symlink string */
+}
+
+void yaffs_verify_special(struct yaffs_obj *obj)
+{
+ if (obj && yaffs_skip_verification(obj->my_dev))
+ return;
+}
+
+void yaffs_verify_obj(struct yaffs_obj *obj)
+{
+ struct yaffs_dev *dev;
+ u32 chunk_min;
+ u32 chunk_max;
+ u32 chunk_id_ok;
+ u32 chunk_in_range;
+ u32 chunk_wrongly_deleted;
+ u32 chunk_valid;
+
+ if (!obj)
+ return;
+
+ if (obj->being_created)
+ return;
+
+ dev = obj->my_dev;
+
+ if (yaffs_skip_verification(dev))
+ return;
+
+ /* Check sane object header chunk */
+
+ chunk_min = dev->internal_start_block * dev->param.chunks_per_block;
+ chunk_max =
+ (dev->internal_end_block + 1) * dev->param.chunks_per_block - 1;
+
+ chunk_in_range = (((unsigned)(obj->hdr_chunk)) >= chunk_min &&
+ ((unsigned)(obj->hdr_chunk)) <= chunk_max);
+ chunk_id_ok = chunk_in_range || (obj->hdr_chunk == 0);
+ chunk_valid = chunk_in_range &&
+ yaffs_check_chunk_bit(dev,
+ obj->hdr_chunk / dev->param.chunks_per_block,
+ obj->hdr_chunk % dev->param.chunks_per_block);
+ chunk_wrongly_deleted = chunk_in_range && !chunk_valid;
+
+ if (!obj->fake && (!chunk_id_ok || chunk_wrongly_deleted))
+ yaffs_trace(YAFFS_TRACE_VERIFY,
+ "Obj %d has chunk_id %d %s %s",
+ obj->obj_id, obj->hdr_chunk,
+ chunk_id_ok ? "" : ",out of range",
+ chunk_wrongly_deleted ? ",marked as deleted" : "");
+
+ if (chunk_valid && !yaffs_skip_nand_verification(dev)) {
+ struct yaffs_ext_tags tags;
+ struct yaffs_obj_hdr *oh;
+ u8 *buffer = yaffs_get_temp_buffer(dev);
+
+ oh = (struct yaffs_obj_hdr *)buffer;
+
+ yaffs_rd_chunk_tags_nand(dev, obj->hdr_chunk, buffer, &tags);
+
+ yaffs_verify_oh(obj, oh, &tags, 1);
+
+ yaffs_release_temp_buffer(dev, buffer);
+ }
+
+ /* Verify it has a parent */
+ if (obj && !obj->fake && (!obj->parent || obj->parent->my_dev != dev)) {
+ yaffs_trace(YAFFS_TRACE_VERIFY,
+ "Obj %d has parent pointer %p which does not look like an object",
+ obj->obj_id, obj->parent);
+ }
+
+ /* Verify parent is a directory */
+ if (obj->parent &&
+ obj->parent->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) {
+ yaffs_trace(YAFFS_TRACE_VERIFY,
+ "Obj %d's parent is not a directory (type %d)",
+ obj->obj_id, obj->parent->variant_type);
+ }
+
+ switch (obj->variant_type) {
+ case YAFFS_OBJECT_TYPE_FILE:
+ yaffs_verify_file(obj);
+ break;
+ case YAFFS_OBJECT_TYPE_SYMLINK:
+ yaffs_verify_symlink(obj);
+ break;
+ case YAFFS_OBJECT_TYPE_DIRECTORY:
+ yaffs_verify_dir(obj);
+ break;
+ case YAFFS_OBJECT_TYPE_HARDLINK:
+ yaffs_verify_link(obj);
+ break;
+ case YAFFS_OBJECT_TYPE_SPECIAL:
+ yaffs_verify_special(obj);
+ break;
+ case YAFFS_OBJECT_TYPE_UNKNOWN:
+ default:
+ yaffs_trace(YAFFS_TRACE_VERIFY,
+ "Obj %d has illegaltype %d",
+ obj->obj_id, obj->variant_type);
+ break;
+ }
+}
+
+void yaffs_verify_objects(struct yaffs_dev *dev)
+{
+ struct yaffs_obj *obj;
+ int i;
+ struct list_head *lh;
+
+ if (yaffs_skip_verification(dev))
+ return;
+
+ /* Iterate through the objects in each hash entry */
+
+ for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) {
+ list_for_each(lh, &dev->obj_bucket[i].list) {
+ obj = list_entry(lh, struct yaffs_obj, hash_link);
+ yaffs_verify_obj(obj);
+ }
+ }
+}
+
+void yaffs_verify_obj_in_dir(struct yaffs_obj *obj)
+{
+ struct list_head *lh;
+ struct yaffs_obj *list_obj;
+ int count = 0;
+
+ if (!obj) {
+ yaffs_trace(YAFFS_TRACE_ALWAYS, "No object to verify");
+ BUG();
+ return;
+ }
+
+ if (yaffs_skip_verification(obj->my_dev))
+ return;
+
+ if (!obj->parent) {
+ yaffs_trace(YAFFS_TRACE_ALWAYS, "Object does not have parent");
+ BUG();
+ return;
+ }
+
+ if (obj->parent->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) {
+ yaffs_trace(YAFFS_TRACE_ALWAYS, "Parent is not directory");
+ BUG();
+ }
+
+ /* Iterate through the objects in each hash entry */
+
+ list_for_each(lh, &obj->parent->variant.dir_variant.children) {
+ list_obj = list_entry(lh, struct yaffs_obj, siblings);
+ yaffs_verify_obj(list_obj);
+ if (obj == list_obj)
+ count++;
+ }
+
+ if (count != 1) {
+ yaffs_trace(YAFFS_TRACE_ALWAYS,
+ "Object in directory %d times",
+ count);
+ BUG();
+ }
+}
+
+void yaffs_verify_dir(struct yaffs_obj *directory)
+{
+ struct list_head *lh;
+ struct yaffs_obj *list_obj;
+ struct yaffs_dev *dev;
+
+ if (!directory) {
+ BUG();
+ return;
+ }
+
+ dev = directory->my_dev;
+
+ if (!dev) {
+ BUG();
+ return;
+ }
+
+ if (directory == dev->root_dir ||
+ directory == dev->lost_n_found ||
+ directory == dev->unlinked_dir ||
+ directory == dev->del_dir)
+ return;
+
+ if (yaffs_skip_full_verification(directory->my_dev))
+ return;
+
+ if (directory->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) {
+ yaffs_trace(YAFFS_TRACE_ALWAYS,
+ "Directory has wrong type: %d",
+ directory->variant_type);
+ BUG();
+ }
+
+ /* Iterate through the objects in each hash entry */
+
+ list_for_each(lh, &directory->variant.dir_variant.children) {
+ list_obj = list_entry(lh, struct yaffs_obj, siblings);
+ if (list_obj->parent != directory) {
+ yaffs_trace(YAFFS_TRACE_ALWAYS,
+ "Object in directory list has wrong parent %p",
+ list_obj->parent);
+ BUG();
+ }
+ yaffs_verify_obj_in_dir(list_obj);
+ }
+}
+
+static int yaffs_free_verification_failures;
+
+void yaffs_verify_free_chunks(struct yaffs_dev *dev)
+{
+ int counted;
+ int difference;
+
+ if (yaffs_skip_verification(dev))
+ return;
+
+ counted = yaffs_count_free_chunks(dev);
+
+ difference = dev->n_free_chunks - counted;
+
+ if (difference) {
+ yaffs_trace(YAFFS_TRACE_ALWAYS,
+ "Freechunks verification failure %d %d %d",
+ dev->n_free_chunks, counted, difference);
+ yaffs_free_verification_failures++;
+ }
+}
+
+int yaffs_verify_file_sane(struct yaffs_obj *in)
+{
+ (void) in;
+ return YAFFS_OK;
+}
diff -urN linux-4.9.37/fs/yaffs2/yaffs_verify.h linux-4.9.y/fs/yaffs2/yaffs_verify.h
--- linux-4.9.37/fs/yaffs2/yaffs_verify.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/yaffs_verify.h 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,43 @@
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+#ifndef __YAFFS_VERIFY_H__
+#define __YAFFS_VERIFY_H__
+
+#include "yaffs_guts.h"
+
+void yaffs_verify_blk(struct yaffs_dev *dev, struct yaffs_block_info *bi,
+ int n);
+void yaffs_verify_collected_blk(struct yaffs_dev *dev,
+ struct yaffs_block_info *bi, int n);
+void yaffs_verify_blocks(struct yaffs_dev *dev);
+
+void yaffs_verify_oh(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh,
+ struct yaffs_ext_tags *tags, int parent_check);
+void yaffs_verify_file(struct yaffs_obj *obj);
+void yaffs_verify_link(struct yaffs_obj *obj);
+void yaffs_verify_symlink(struct yaffs_obj *obj);
+void yaffs_verify_special(struct yaffs_obj *obj);
+void yaffs_verify_obj(struct yaffs_obj *obj);
+void yaffs_verify_objects(struct yaffs_dev *dev);
+void yaffs_verify_obj_in_dir(struct yaffs_obj *obj);
+void yaffs_verify_dir(struct yaffs_obj *directory);
+void yaffs_verify_free_chunks(struct yaffs_dev *dev);
+
+int yaffs_verify_file_sane(struct yaffs_obj *obj);
+
+int yaffs_skip_verification(struct yaffs_dev *dev);
+
+#endif
diff -urN linux-4.9.37/fs/yaffs2/yaffs_vfs.c linux-4.9.y/fs/yaffs2/yaffs_vfs.c
--- linux-4.9.37/fs/yaffs2/yaffs_vfs.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/yaffs_vfs.c 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,3751 @@
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ * Acknowledgements:
+ * Luc van OostenRyck for numerous patches.
+ * Nick Bane for numerous patches.
+ * Nick Bane for 2.5/2.6 integration.
+ * Andras Toth for mknod rdev issue.
+ * Michael Fischer for finding the problem with inode inconsistency.
+ * Some code bodily lifted from JFFS
+ *
+ * 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.
+ */
+
+/*
+ *
+ * This is the file system front-end to YAFFS that hooks it up to
+ * the VFS.
+ *
+ * Special notes:
+ * >> 2.4: sb->u.generic_sbp points to the struct yaffs_dev associated with
+ * this superblock
+ * >> 2.6: sb->s_fs_info points to the struct yaffs_dev associated with this
+ * superblock
+ * >> inode->u.generic_ip points to the associated struct yaffs_obj.
+ */
+
+/*
+ * There are two variants of the VFS glue code. This variant should compile
+ * for any version of Linux.
+ */
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10))
+#define YAFFS_COMPILE_BACKGROUND
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23))
+#define YAFFS_COMPILE_FREEZER
+#endif
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
+#define YAFFS_COMPILE_EXPORTFS
+#endif
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35))
+#define YAFFS_USE_SETATTR_COPY
+#define YAFFS_USE_TRUNCATE_SETSIZE
+#endif
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35))
+#define YAFFS_HAS_EVICT_INODE
+#endif
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13)) && \
+ (LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0))
+#define YAFFS_NEW_FOLLOW_LINK 1
+#else
+#define YAFFS_NEW_FOLLOW_LINK 0
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
+#define YAFFS_HAS_WRITE_SUPER
+#endif
+
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
+#include <linux/config.h>
+#endif
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39))
+#include <linux/smp_lock.h>
+#endif
+#include <linux/pagemap.h>
+#include <linux/mtd/mtd.h>
+#include <linux/interrupt.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+
+#if (YAFFS_NEW_FOLLOW_LINK == 1)
+#include <linux/namei.h>
+#endif
+
+#ifdef YAFFS_COMPILE_EXPORTFS
+#include <linux/exportfs.h>
+#endif
+
+#ifdef YAFFS_COMPILE_BACKGROUND
+#include <linux/kthread.h>
+#include <linux/delay.h>
+#endif
+#ifdef YAFFS_COMPILE_FREEZER
+#include <linux/freezer.h>
+#endif
+
+#include <asm/div64.h>
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
+
+#include <linux/statfs.h>
+
+#define UnlockPage(p) unlock_page(p)
+#define Page_Uptodate(page) test_bit(PG_uptodate, &(page)->flags)
+
+/* FIXME: use sb->s_id instead ? */
+#define yaffs_devname(sb, buf) bdevname(sb->s_bdev, buf)
+
+#else
+
+#include <linux/locks.h>
+#define BDEVNAME_SIZE 0
+#define yaffs_devname(sb, buf) kdevname(sb->s_dev)
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0))
+/* added NCB 26/5/2006 for 2.4.25-vrs2-tcl1 kernel */
+#define __user
+#endif
+
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26))
+#define YPROC_ROOT (&proc_root)
+#else
+#define YPROC_ROOT NULL
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26))
+#define Y_INIT_TIMER(a) init_timer(a)
+#else
+#define Y_INIT_TIMER(a) init_timer_on_stack(a)
+#endif
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 27))
+#define YAFFS_USE_WRITE_BEGIN_END 1
+#else
+#define YAFFS_USE_WRITE_BEGIN_END 0
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
+#define YAFFS_SUPER_HAS_DIRTY
+#endif
+
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0))
+#define set_nlink(inode, count) do { (inode)->i_nlink = (count); } while(0)
+#endif
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 28))
+static uint32_t YCALCBLOCKS(uint64_t partition_size, uint32_t block_size)
+{
+ uint64_t result = partition_size;
+ do_div(result, block_size);
+ return (uint32_t) result;
+}
+#else
+#define YCALCBLOCKS(s, b) ((s)/(b))
+#endif
+
+#include <linux/uaccess.h>
+#include <linux/mtd/mtd.h>
+
+#include "yportenv.h"
+#include "yaffs_trace.h"
+#include "yaffs_guts.h"
+#include "yaffs_attribs.h"
+
+#include "yaffs_linux.h"
+
+#include "yaffs_mtdif.h"
+#include "yaffs_packedtags2.h"
+#include "yaffs_getblockinfo.h"
+
+unsigned int yaffs_trace_mask =
+ YAFFS_TRACE_BAD_BLOCKS |
+ YAFFS_TRACE_ALWAYS |
+ 0;
+
+unsigned int yaffs_wr_attempts = YAFFS_WR_ATTEMPTS;
+unsigned int yaffs_auto_checkpoint = 1;
+unsigned int yaffs_gc_control = 1;
+unsigned int yaffs_bg_enable = 1;
+unsigned int yaffs_auto_select = 1;
+/* Module Parameters */
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
+module_param(yaffs_trace_mask, uint, 0644);
+module_param(yaffs_wr_attempts, uint, 0644);
+module_param(yaffs_auto_checkpoint, uint, 0644);
+module_param(yaffs_gc_control, uint, 0644);
+module_param(yaffs_bg_enable, uint, 0644);
+#else
+MODULE_PARM(yaffs_trace_mask, "i");
+MODULE_PARM(yaffs_wr_attempts, "i");
+MODULE_PARM(yaffs_auto_checkpoint, "i");
+MODULE_PARM(yaffs_gc_control, "i");
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25))
+/* use iget and read_inode */
+#define Y_IGET(sb, inum) iget((sb), (inum))
+
+#else
+/* Call local equivalent */
+#define YAFFS_USE_OWN_IGET
+#define Y_IGET(sb, inum) yaffs_iget((sb), (inum))
+
+#endif
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18))
+#define yaffs_inode_to_obj_lv(iptr) ((iptr)->i_private)
+#else
+#define yaffs_inode_to_obj_lv(iptr) ((iptr)->u.generic_ip)
+#endif
+
+#define yaffs_inode_to_obj(iptr) \
+ ((struct yaffs_obj *)(yaffs_inode_to_obj_lv(iptr)))
+#define yaffs_dentry_to_obj(dptr) yaffs_inode_to_obj((dptr)->d_inode)
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
+#define yaffs_super_to_dev(sb) ((struct yaffs_dev *)sb->s_fs_info)
+#else
+#define yaffs_super_to_dev(sb) ((struct yaffs_dev *)sb->u.generic_sbp)
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
+#define Y_CLEAR_INODE(i) clear_inode(i)
+#else
+#define Y_CLEAR_INODE(i) end_writeback(i)
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
+#define YAFFS_USE_DIR_ITERATE
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0))
+#define YAFFS_USE_XATTR
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,12,0))
+#define YAFFS_NEW_PROCFS
+#include <linux/seq_file.h>
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
+#define PAGE_CACHE_SIZE PAGE_SIZE
+#define PAGE_CACHE_SHIFT PAGE_SHIFT
+#define Y_GET_DENTRY(f) ((f)->f_path.dentry)
+#define page_cache_release put_page
+#define YAFFS_NEW_XATTR 1
+#define YAFFS_NEW_GET_LINK 1
+#else
+#define Y_GET_DENTRY(f) ((f)->f_dentry)
+#define YAFFS_NEW_XATTR 0
+#define YAFFS_NEW_GET_LINK 0
+#endif
+
+#define update_dir_time(dir) do {\
+ (dir)->i_ctime = (dir)->i_mtime = CURRENT_TIME; \
+ } while (0)
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0))
+static inline int setattr_prepare(struct dentry *dentry, struct iattr *attr)
+{
+ return inode_change_ok(dentry->d_inode, attr);
+}
+#endif
+
+static void yaffs_fill_inode_from_obj(struct inode *inode,
+ struct yaffs_obj *obj);
+
+
+static void yaffs_gross_lock(struct yaffs_dev *dev)
+{
+ yaffs_trace(YAFFS_TRACE_LOCK, "yaffs locking %p", current);
+ mutex_lock(&(yaffs_dev_to_lc(dev)->gross_lock));
+ yaffs_trace(YAFFS_TRACE_LOCK, "yaffs locked %p", current);
+}
+
+static void yaffs_gross_unlock(struct yaffs_dev *dev)
+{
+ yaffs_trace(YAFFS_TRACE_LOCK, "yaffs unlocking %p", current);
+ mutex_unlock(&(yaffs_dev_to_lc(dev)->gross_lock));
+}
+
+
+static int yaffs_readpage_nolock(struct file *f, struct page *pg)
+{
+ /* Lifted from jffs2 */
+
+ struct yaffs_obj *obj;
+ unsigned char *pg_buf;
+ int ret;
+ loff_t pos = ((loff_t) pg->index) << PAGE_SHIFT;
+ struct yaffs_dev *dev;
+
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_readpage_nolock at %lld, size %08x",
+ (long long)pos,
+ (unsigned)PAGE_SIZE);
+
+ obj = yaffs_dentry_to_obj(Y_GET_DENTRY(f));
+
+ dev = obj->my_dev;
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
+ BUG_ON(!PageLocked(pg));
+#else
+ if (!PageLocked(pg))
+ PAGE_BUG(pg);
+#endif
+
+ pg_buf = kmap(pg);
+ /* FIXME: Can kmap fail? */
+
+ yaffs_gross_lock(dev);
+
+ ret = yaffs_file_rd(obj, pg_buf, pos, PAGE_CACHE_SIZE);
+
+ yaffs_gross_unlock(dev);
+
+ if (ret >= 0)
+ ret = 0;
+
+ if (ret) {
+ ClearPageUptodate(pg);
+ SetPageError(pg);
+ } else {
+ SetPageUptodate(pg);
+ ClearPageError(pg);
+ }
+
+ flush_dcache_page(pg);
+ kunmap(pg);
+
+ yaffs_trace(YAFFS_TRACE_OS, "yaffs_readpage_nolock done");
+ return ret;
+}
+
+static int yaffs_readpage_unlock(struct file *f, struct page *pg)
+{
+ int ret = yaffs_readpage_nolock(f, pg);
+ UnlockPage(pg);
+ return ret;
+}
+
+static int yaffs_readpage(struct file *f, struct page *pg)
+{
+ int ret;
+
+ yaffs_trace(YAFFS_TRACE_OS, "yaffs_readpage");
+ ret = yaffs_readpage_unlock(f, pg);
+ yaffs_trace(YAFFS_TRACE_OS, "yaffs_readpage done");
+ return ret;
+}
+
+
+static void yaffs_set_super_dirty_val(struct yaffs_dev *dev, int val)
+{
+ struct yaffs_linux_context *lc = yaffs_dev_to_lc(dev);
+
+ if (lc)
+ lc->dirty = val;
+
+# ifdef YAFFS_SUPER_HAS_DIRTY
+ {
+ struct super_block *sb = lc->super;
+
+ if (sb)
+ sb->s_dirt = val;
+ }
+#endif
+
+}
+
+static void yaffs_set_super_dirty(struct yaffs_dev *dev)
+{
+ yaffs_set_super_dirty_val(dev, 1);
+}
+
+static void yaffs_clear_super_dirty(struct yaffs_dev *dev)
+{
+ yaffs_set_super_dirty_val(dev, 0);
+}
+
+static int yaffs_check_super_dirty(struct yaffs_dev *dev)
+{
+ struct yaffs_linux_context *lc = yaffs_dev_to_lc(dev);
+
+ if (lc && lc->dirty)
+ return 1;
+
+# ifdef YAFFS_SUPER_HAS_DIRTY
+ {
+ struct super_block *sb = lc->super;
+
+ if (sb && sb->s_dirt)
+ return 1;
+ }
+#endif
+ return 0;
+
+}
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
+static int yaffs_writepage(struct page *page, struct writeback_control *wbc)
+#else
+static int yaffs_writepage(struct page *page)
+#endif
+{
+ struct yaffs_dev *dev;
+ struct address_space *mapping = page->mapping;
+ struct inode *inode;
+ unsigned long end_index;
+ char *buffer;
+ struct yaffs_obj *obj;
+ int n_written = 0;
+ unsigned n_bytes;
+ loff_t i_size;
+
+ if (!mapping)
+ BUG();
+ inode = mapping->host;
+ if (!inode)
+ BUG();
+ i_size = i_size_read(inode);
+
+ end_index = i_size >> PAGE_CACHE_SHIFT;
+
+ if (page->index < end_index)
+ n_bytes = PAGE_CACHE_SIZE;
+ else {
+ n_bytes = i_size & (PAGE_CACHE_SIZE - 1);
+
+ if (page->index > end_index || !n_bytes) {
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_writepage at %lld, inode size = %lld!!",
+ ((loff_t)page->index) << PAGE_CACHE_SHIFT,
+ inode->i_size);
+ yaffs_trace(YAFFS_TRACE_OS,
+ " -> don't care!!");
+
+ zero_user_segment(page, 0, PAGE_CACHE_SIZE);
+ set_page_writeback(page);
+ unlock_page(page);
+ end_page_writeback(page);
+ return 0;
+ }
+ }
+
+ if (n_bytes != PAGE_CACHE_SIZE)
+ zero_user_segment(page, n_bytes, PAGE_CACHE_SIZE);
+
+ get_page(page);
+
+ buffer = kmap(page);
+
+ obj = yaffs_inode_to_obj(inode);
+ dev = obj->my_dev;
+ yaffs_gross_lock(dev);
+
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_writepage at %lld, size %08x",
+ ((loff_t)page->index) << PAGE_CACHE_SHIFT, n_bytes);
+ yaffs_trace(YAFFS_TRACE_OS,
+ "writepag0: obj = %lld, ino = %lld",
+ obj->variant.file_variant.file_size, inode->i_size);
+
+ n_written = yaffs_wr_file(obj, buffer,
+ ((loff_t)page->index) << PAGE_CACHE_SHIFT, n_bytes, 0);
+
+ yaffs_set_super_dirty(dev);
+
+ yaffs_trace(YAFFS_TRACE_OS,
+ "writepag1: obj = %lld, ino = %lld",
+ obj->variant.file_variant.file_size, inode->i_size);
+
+ yaffs_gross_unlock(dev);
+
+ kunmap(page);
+ set_page_writeback(page);
+ unlock_page(page);
+ end_page_writeback(page);
+ put_page(page);
+
+ return (n_written == n_bytes) ? 0 : -ENOSPC;
+}
+
+/* Space holding and freeing is done to ensure we have space available for write_begin/end */
+/* For now we just assume few parallel writes and check against a small number. */
+/* Todo: need to do this with a counter to handle parallel reads better */
+
+static ssize_t yaffs_hold_space(struct file *f)
+{
+ struct yaffs_obj *obj;
+ struct yaffs_dev *dev;
+
+ int n_free_chunks;
+
+ obj = yaffs_dentry_to_obj(Y_GET_DENTRY(f));
+
+ dev = obj->my_dev;
+
+ yaffs_gross_lock(dev);
+
+ n_free_chunks = yaffs_get_n_free_chunks(dev);
+
+ yaffs_gross_unlock(dev);
+
+ return (n_free_chunks > 20) ? 1 : 0;
+}
+
+static void yaffs_release_space(struct file *f)
+{
+ struct yaffs_obj *obj;
+ struct yaffs_dev *dev;
+
+ obj = yaffs_dentry_to_obj(Y_GET_DENTRY(f));
+
+ dev = obj->my_dev;
+
+ yaffs_gross_lock(dev);
+
+ yaffs_gross_unlock(dev);
+}
+
+#if (YAFFS_USE_WRITE_BEGIN_END > 0)
+static int yaffs_write_begin(struct file *filp, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata)
+{
+ struct page *pg = NULL;
+ pgoff_t index = pos >> PAGE_CACHE_SHIFT;
+
+ int ret = 0;
+ int space_held = 0;
+
+ /* Get a page */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
+ pg = grab_cache_page_write_begin(mapping, index, flags);
+#else
+ pg = __grab_cache_page(mapping, index);
+#endif
+
+ *pagep = pg;
+ if (!pg) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ yaffs_trace(YAFFS_TRACE_OS,
+ "start yaffs_write_begin index %d(%x) uptodate %d",
+ (int)index, (int)index, Page_Uptodate(pg) ? 1 : 0);
+
+ /* Get fs space */
+ space_held = yaffs_hold_space(filp);
+
+ if (!space_held) {
+ ret = -ENOSPC;
+ goto out;
+ }
+
+ /* Update page if required */
+
+ if (!Page_Uptodate(pg))
+ ret = yaffs_readpage_nolock(filp, pg);
+
+ if (ret)
+ goto out;
+
+ /* Happy path return */
+ yaffs_trace(YAFFS_TRACE_OS, "end yaffs_write_begin - ok");
+
+ return 0;
+
+out:
+ yaffs_trace(YAFFS_TRACE_OS,
+ "end yaffs_write_begin fail returning %d", ret);
+ if (space_held)
+ yaffs_release_space(filp);
+ if (pg) {
+ unlock_page(pg);
+ page_cache_release(pg);
+ }
+ return ret;
+}
+
+#else
+
+static int yaffs_prepare_write(struct file *f, struct page *pg,
+ unsigned offset, unsigned to)
+{
+ yaffs_trace(YAFFS_TRACE_OS, "yaffs_prepair_write");
+
+ if (!Page_Uptodate(pg))
+ return yaffs_readpage_nolock(f, pg);
+ return 0;
+}
+#endif
+
+
+static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n,
+ loff_t * pos)
+{
+ struct yaffs_obj *obj;
+ int n_written;
+ loff_t ipos;
+ struct inode *inode;
+ struct yaffs_dev *dev;
+
+ obj = yaffs_dentry_to_obj(Y_GET_DENTRY(f));
+
+ if (!obj) {
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_file_write: hey obj is null!");
+ return -EINVAL;
+ }
+
+ dev = obj->my_dev;
+
+ yaffs_gross_lock(dev);
+
+ inode = Y_GET_DENTRY(f)->d_inode;
+
+ if (!S_ISBLK(inode->i_mode) && f->f_flags & O_APPEND)
+ ipos = inode->i_size;
+ else
+ ipos = *pos;
+
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_file_write about to write writing %u(%x) bytes to object %d at %lld",
+ (unsigned)n, (unsigned)n, obj->obj_id, ipos);
+
+ n_written = yaffs_wr_file(obj, buf, ipos, n, 0);
+
+ yaffs_set_super_dirty(dev);
+
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_file_write: %d(%x) bytes written",
+ (unsigned)n, (unsigned)n);
+
+ if (n_written > 0) {
+ ipos += n_written;
+ *pos = ipos;
+ if (ipos > inode->i_size) {
+ inode->i_size = ipos;
+ inode->i_blocks = (ipos + 511) >> 9;
+
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_file_write size updated to %lld bytes, %d blocks",
+ ipos, (int)(inode->i_blocks));
+ }
+
+ }
+ yaffs_gross_unlock(dev);
+ return (n_written == 0) && (n > 0) ? -ENOSPC : n_written;
+}
+
+
+#if (YAFFS_USE_WRITE_BEGIN_END > 0)
+static int yaffs_write_end(struct file *filp, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied,
+ struct page *pg, void *fsdadata)
+{
+ int ret = 0;
+ void *addr, *kva;
+ uint32_t offset_into_page = pos & (PAGE_CACHE_SIZE - 1);
+
+ kva = kmap(pg);
+ addr = kva + offset_into_page;
+
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_write_end addr %p pos %lld n_bytes %d",
+ addr, pos, copied);
+
+ ret = yaffs_file_write(filp, addr, copied, &pos);
+
+ if (ret != copied) {
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_write_end not same size ret %d copied %d",
+ ret, copied);
+ SetPageError(pg);
+ }
+
+ kunmap(pg);
+
+ yaffs_release_space(filp);
+ unlock_page(pg);
+ page_cache_release(pg);
+ return ret;
+}
+#else
+
+static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset,
+ unsigned to)
+{
+ void *addr, *kva;
+
+ loff_t pos = (((loff_t) pg->index) << PAGE_CACHE_SHIFT) + offset;
+ int n_bytes = to - offset;
+ int n_written;
+
+ kva = kmap(pg);
+ addr = kva + offset;
+
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_commit_write addr %p pos %lld n_bytes %d",
+ addr, pos, n_bytes);
+
+ n_written = yaffs_file_write(f, addr, n_bytes, &pos);
+
+ if (n_written != n_bytes) {
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_commit_write not same size n_written %d n_bytes %d",
+ n_written, n_bytes);
+ SetPageError(pg);
+ }
+ kunmap(pg);
+
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_commit_write returning %d",
+ n_written == n_bytes ? 0 : n_written);
+
+ return n_written == n_bytes ? 0 : n_written;
+}
+#endif
+
+static struct address_space_operations yaffs_file_address_operations = {
+ .readpage = yaffs_readpage,
+ .writepage = yaffs_writepage,
+#if (YAFFS_USE_WRITE_BEGIN_END > 0)
+ .write_begin = yaffs_write_begin,
+ .write_end = yaffs_write_end,
+#else
+ .prepare_write = yaffs_prepare_write,
+ .commit_write = yaffs_commit_write,
+#endif
+};
+
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
+static int yaffs_file_flush(struct file *file, fl_owner_t id)
+#else
+static int yaffs_file_flush(struct file *file)
+#endif
+{
+ struct yaffs_obj *obj = yaffs_dentry_to_obj(Y_GET_DENTRY(file));
+
+ struct yaffs_dev *dev = obj->my_dev;
+
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_file_flush object %d (%s)",
+ obj->obj_id,
+ obj->dirty ? "dirty" : "clean");
+
+ yaffs_gross_lock(dev);
+
+ yaffs_flush_file(obj, 1, 0, 0);
+
+ yaffs_gross_unlock(dev);
+
+ return 0;
+}
+
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
+static int yaffs_sync_object(struct file *file, loff_t start, loff_t end, int datasync)
+#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 34))
+static int yaffs_sync_object(struct file *file, int datasync)
+#else
+static int yaffs_sync_object(struct file *file, struct dentry *dentry,
+ int datasync)
+#endif
+{
+ struct yaffs_obj *obj;
+ struct yaffs_dev *dev;
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 34))
+ struct dentry *dentry = file->f_path.dentry;
+#endif
+
+ obj = yaffs_dentry_to_obj(dentry);
+
+ dev = obj->my_dev;
+
+ yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC,
+ "yaffs_sync_object");
+ yaffs_gross_lock(dev);
+ yaffs_flush_file(obj, 1, datasync, 0);
+ yaffs_gross_unlock(dev);
+ return 0;
+}
+
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22))
+static const struct file_operations yaffs_file_operations = {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0)
+ .read = new_sync_read,
+ .write = new_sync_write,
+#endif
+ .read_iter = generic_file_read_iter,
+ .write_iter = generic_file_write_iter,
+#else
+ .read = do_sync_read,
+ .write = do_sync_write,
+ .aio_read = generic_file_aio_read,
+ .aio_write = generic_file_aio_write,
+#endif
+ .mmap = generic_file_mmap,
+ .flush = yaffs_file_flush,
+ .fsync = yaffs_sync_object,
+ .splice_read = generic_file_splice_read,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
+ .splice_write = iter_file_splice_write,
+#else
+ .splice_write = generic_file_splice_write,
+#endif
+ .llseek = generic_file_llseek,
+};
+
+#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18))
+
+static const struct file_operations yaffs_file_operations = {
+ .read = do_sync_read,
+ .write = do_sync_write,
+ .aio_read = generic_file_aio_read,
+ .aio_write = generic_file_aio_write,
+ .mmap = generic_file_mmap,
+ .flush = yaffs_file_flush,
+ .fsync = yaffs_sync_object,
+ .sendfile = generic_file_sendfile,
+};
+
+#else
+
+static const struct file_operations yaffs_file_operations = {
+ .read = generic_file_read,
+ .write = generic_file_write,
+ .mmap = generic_file_mmap,
+ .flush = yaffs_file_flush,
+ .fsync = yaffs_sync_object,
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
+ .sendfile = generic_file_sendfile,
+#endif
+};
+#endif
+
+
+
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25))
+static void zero_user_segment(struct page *page, unsigned start, unsigned end)
+{
+ void *kaddr = kmap_atomic(page, KM_USER0);
+ memset(kaddr + start, 0, end - start);
+ kunmap_atomic(kaddr, KM_USER0);
+ flush_dcache_page(page);
+}
+#endif
+
+
+static int yaffs_vfs_setsize(struct inode *inode, loff_t newsize)
+{
+#ifdef YAFFS_USE_TRUNCATE_SETSIZE
+ truncate_setsize(inode, newsize);
+ return 0;
+#else
+ truncate_inode_pages(&inode->i_data, newsize);
+ return 0;
+#endif
+
+}
+
+
+static int yaffs_vfs_setattr(struct inode *inode, struct iattr *attr)
+{
+#ifdef YAFFS_USE_SETATTR_COPY
+ setattr_copy(inode, attr);
+ return 0;
+#else
+ return inode_setattr(inode, attr);
+#endif
+
+}
+
+static int yaffs_setattr(struct dentry *dentry, struct iattr *attr)
+{
+ struct inode *inode = dentry->d_inode;
+ int error = 0;
+ struct yaffs_dev *dev;
+
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_setattr of object %d",
+ yaffs_inode_to_obj(inode)->obj_id);
+#if 0
+ /* Fail if a requested resize >= 2GB */
+ if (attr->ia_valid & ATTR_SIZE && (attr->ia_size >> 31))
+ error = -EINVAL;
+#endif
+
+ if (error == 0)
+ error = setattr_prepare(dentry, attr);
+ if (error == 0) {
+ int result;
+ if (!error) {
+ error = yaffs_vfs_setattr(inode, attr);
+ yaffs_trace(YAFFS_TRACE_OS, "inode_setattr called");
+ if (attr->ia_valid & ATTR_SIZE) {
+ yaffs_vfs_setsize(inode, attr->ia_size);
+ inode->i_blocks = (inode->i_size + 511) >> 9;
+ }
+ }
+ dev = yaffs_inode_to_obj(inode)->my_dev;
+ if (attr->ia_valid & ATTR_SIZE) {
+ yaffs_trace(YAFFS_TRACE_OS,
+ "resize to %d(%x)",
+ (int)(attr->ia_size),
+ (int)(attr->ia_size));
+ }
+ yaffs_gross_lock(dev);
+ result = yaffs_set_attribs(yaffs_inode_to_obj(inode), attr);
+ if (result == YAFFS_OK) {
+ error = 0;
+ } else {
+ error = -EPERM;
+ }
+ yaffs_gross_unlock(dev);
+
+ }
+
+ yaffs_trace(YAFFS_TRACE_OS, "yaffs_setattr done returning %d", error);
+
+ return error;
+}
+
+#ifdef YAFFS_USE_XATTR
+#if (YAFFS_NEW_XATTR > 0)
+static int yaffs_setxattr(struct dentry *dentry, struct inode *inode,
+ const char *name, const void *value, size_t size, int flags)
+{
+#else
+static int yaffs_setxattr(struct dentry *dentry, const char *name,
+ const void *value, size_t size, int flags)
+{
+ struct inode *inode = dentry->d_inode;
+#endif
+ int error = 0;
+ struct yaffs_dev *dev;
+ struct yaffs_obj *obj = yaffs_inode_to_obj(inode);
+
+ yaffs_trace(YAFFS_TRACE_OS, "yaffs_setxattr of object %d", obj->obj_id);
+
+ if (error == 0) {
+ int result;
+ dev = obj->my_dev;
+ yaffs_gross_lock(dev);
+ result = yaffs_set_xattrib(obj, name, value, size, flags);
+ if (result == YAFFS_OK)
+ error = 0;
+ else if (result < 0)
+ error = result;
+ yaffs_gross_unlock(dev);
+
+ }
+ yaffs_trace(YAFFS_TRACE_OS, "yaffs_setxattr done returning %d", error);
+
+ return error;
+}
+
+#ifdef YAFFS_NEW_XATTR
+static ssize_t yaffs_getxattr(struct dentry * dentry, struct inode *inode,
+ const char *name, void *buff, size_t size)
+{
+#else
+static ssize_t yaffs_getxattr(struct dentry * dentry, const char *name,
+ void *buff, size_t size)
+{
+ struct inode *inode = dentry->d_inode;
+#endif
+ int error = 0;
+ struct yaffs_dev *dev;
+ struct yaffs_obj *obj = yaffs_inode_to_obj(inode);
+
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_getxattr \"%s\" from object %d",
+ name, obj->obj_id);
+
+ if (error == 0) {
+ dev = obj->my_dev;
+ yaffs_gross_lock(dev);
+ error = yaffs_get_xattrib(obj, name, buff, size);
+ yaffs_gross_unlock(dev);
+
+ }
+ yaffs_trace(YAFFS_TRACE_OS, "yaffs_getxattr done returning %d", error);
+
+ return error;
+}
+
+static int yaffs_removexattr(struct dentry *dentry, const char *name)
+{
+ struct inode *inode = dentry->d_inode;
+ int error = 0;
+ struct yaffs_dev *dev;
+ struct yaffs_obj *obj = yaffs_inode_to_obj(inode);
+
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_removexattr of object %d", obj->obj_id);
+
+ if (error == 0) {
+ int result;
+ dev = obj->my_dev;
+ yaffs_gross_lock(dev);
+ result = yaffs_remove_xattrib(obj, name);
+ if (result == YAFFS_OK)
+ error = 0;
+ else if (result < 0)
+ error = result;
+ yaffs_gross_unlock(dev);
+
+ }
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_removexattr done returning %d", error);
+
+ return error;
+}
+#endif
+
+static ssize_t yaffs_listxattr(struct dentry * dentry, char *buff, size_t size)
+{
+ struct inode *inode = dentry->d_inode;
+ int error = 0;
+ struct yaffs_dev *dev;
+ struct yaffs_obj *obj = yaffs_inode_to_obj(inode);
+
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_listxattr of object %d", obj->obj_id);
+
+ if (error == 0) {
+ dev = obj->my_dev;
+ yaffs_gross_lock(dev);
+ error = yaffs_list_xattrib(obj, buff, size);
+ yaffs_gross_unlock(dev);
+
+ }
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_listxattr done returning %d", error);
+
+ return error;
+}
+
+
+static const struct inode_operations yaffs_file_inode_operations = {
+ .setattr = yaffs_setattr,
+#ifdef YAFFS_USE_XATTR
+ .setxattr = yaffs_setxattr,
+ .getxattr = yaffs_getxattr,
+ .removexattr = yaffs_removexattr,
+#endif
+ .listxattr = yaffs_listxattr,
+};
+
+
+static int yaffs_readlink(struct dentry *dentry, char __user * buffer,
+ int buflen)
+{
+ unsigned char *alias;
+ int ret;
+
+ struct yaffs_dev *dev = yaffs_dentry_to_obj(dentry)->my_dev;
+
+ yaffs_gross_lock(dev);
+
+ alias = yaffs_get_symlink_alias(yaffs_dentry_to_obj(dentry));
+
+ yaffs_gross_unlock(dev);
+
+ if (!alias)
+ return -ENOMEM;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0)
+ ret = vfs_readlink(dentry, buffer, buflen, alias);
+#else
+ ret = readlink_copy(buffer, buflen, alias);
+#endif
+ kfree(alias);
+ return ret;
+}
+
+#if (YAFFS_NEW_GET_LINK == 0)
+#if (YAFFS_NEW_FOLLOW_LINK == 1)
+static void *yaffs_follow_link(struct dentry *dentry, struct nameidata *nd)
+{
+ void *ret;
+#else
+static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd)
+{
+ int ret
+#endif
+ unsigned char *alias;
+ int ret_int = 0;
+ struct yaffs_dev *dev = yaffs_dentry_to_obj(dentry)->my_dev;
+
+ yaffs_gross_lock(dev);
+
+ alias = yaffs_get_symlink_alias(yaffs_dentry_to_obj(dentry));
+ yaffs_gross_unlock(dev);
+
+ if (!alias) {
+ ret_int = -ENOMEM;
+ goto out;
+ }
+#if (YAFFS_NEW_FOLLOW_LINK == 1)
+ nd_set_link(nd, alias);
+ ret = alias;
+out:
+ if (ret_int)
+ ret = ERR_PTR(ret_int);
+ return ret;
+#else
+ ret = vfs_follow_link(nd, alias);
+ kfree(alias);
+out:
+ if (ret_int)
+ ret = ret_int;
+ return ret;
+#endif
+}
+#else
+static const char *yaffs_get_link(struct dentry *dentry, struct inode *inode, struct delayed_call *done)
+{
+ unsigned char *alias;
+ struct yaffs_dev *dev;
+
+ if (!dentry)
+ return ERR_PTR(-ECHILD);
+
+ dev = yaffs_dentry_to_obj(dentry)->my_dev;
+
+ yaffs_gross_lock(dev);
+
+ alias = yaffs_get_symlink_alias(yaffs_dentry_to_obj(dentry));
+ yaffs_gross_unlock(dev);
+
+ if (!alias)
+ return ERR_PTR(-ENOMEM);
+ set_delayed_call(done, kfree_link, alias);
+ return alias;
+}
+#endif
+
+#ifdef YAFFS_HAS_PUT_INODE
+
+/* For now put inode is just for debugging
+ * Put inode is called when the inode **structure** is put.
+ */
+static void yaffs_put_inode(struct inode *inode)
+{
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_put_inode: ino %d, count %d"),
+ (int)inode->i_ino, atomic_read(&inode->i_count);
+
+}
+#endif
+
+#if (YAFFS_NEW_FOLLOW_LINK == 1)
+void yaffs_put_link(struct dentry *dentry, struct nameidata *nd, void *alias)
+{
+ kfree(alias);
+}
+#endif
+
+static const struct inode_operations yaffs_symlink_inode_operations = {
+ .readlink = yaffs_readlink,
+#if (YAFFS_NEW_GET_LINK == 1)
+ .get_link = yaffs_get_link,
+#else
+ .follow_link = yaffs_follow_link,
+#endif
+#if (YAFFS_NEW_FOLLOW_LINK == 1)
+ .put_link = yaffs_put_link,
+#endif
+ .setattr = yaffs_setattr,
+#ifdef YAFFS_USE_XATTR
+ .setxattr = yaffs_setxattr,
+ .getxattr = yaffs_getxattr,
+ .removexattr = yaffs_removexattr,
+#endif
+ .listxattr = yaffs_listxattr,
+};
+
+#ifdef YAFFS_USE_OWN_IGET
+
+static struct inode *yaffs_iget(struct super_block *sb, unsigned long ino)
+{
+ struct inode *inode;
+ struct yaffs_obj *obj;
+ struct yaffs_dev *dev = yaffs_super_to_dev(sb);
+
+ yaffs_trace(YAFFS_TRACE_OS, "yaffs_iget for %lu", ino);
+
+ inode = iget_locked(sb, ino);
+ if (!inode)
+ return ERR_PTR(-ENOMEM);
+ if (!(inode->i_state & I_NEW))
+ return inode;
+
+ /* NB This is called as a side effect of other functions, but
+ * we had to release the lock to prevent deadlocks, so
+ * need to lock again.
+ */
+
+ yaffs_gross_lock(dev);
+
+ obj = yaffs_find_by_number(dev, inode->i_ino);
+
+ yaffs_fill_inode_from_obj(inode, obj);
+
+ yaffs_gross_unlock(dev);
+
+ unlock_new_inode(inode);
+ return inode;
+}
+
+#else
+
+static void yaffs_read_inode(struct inode *inode)
+{
+ /* NB This is called as a side effect of other functions, but
+ * we had to release the lock to prevent deadlocks, so
+ * need to lock again.
+ */
+
+ struct yaffs_obj *obj;
+ struct yaffs_dev *dev = yaffs_super_to_dev(inode->i_sb);
+
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_read_inode for %d", (int)inode->i_ino);
+
+ if (current != yaffs_dev_to_lc(dev)->readdir_process)
+ yaffs_gross_lock(dev);
+
+ obj = yaffs_find_by_number(dev, inode->i_ino);
+
+ yaffs_fill_inode_from_obj(inode, obj);
+
+ if (current != yaffs_dev_to_lc(dev)->readdir_process)
+ yaffs_gross_unlock(dev);
+}
+
+#endif
+
+
+
+struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev,
+ struct yaffs_obj *obj)
+{
+ struct inode *inode;
+
+ if (!sb) {
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_get_inode for NULL super_block!!");
+ return NULL;
+
+ }
+
+ if (!obj) {
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_get_inode for NULL object!!");
+ return NULL;
+
+ }
+
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_get_inode for object %d", obj->obj_id);
+
+ inode = Y_IGET(sb, obj->obj_id);
+ if (IS_ERR(inode))
+ return NULL;
+
+ /* NB Side effect: iget calls back to yaffs_read_inode(). */
+ /* iget also increments the inode's i_count */
+ /* NB You can't be holding gross_lock or deadlock will happen! */
+
+ return inode;
+}
+
+
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
+#define YCRED(x) x
+#else
+#define YCRED(x) (x->cred)
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0)
+#define YPROC_uid(p) (YCRED(p)->fsuid)
+#define YPROC_gid(p) (YCRED(p)->fsgid)
+#define EXTRACT_gid(x) x
+#define EXTRACT_uid(x) x
+#define MAKE_gid(x) x
+#define MAKE_uid(x) x
+#else
+#define YPROC_uid(p) from_kuid(&init_user_ns, YCRED(p)->fsuid)
+#define YPROC_gid(p) from_kgid(&init_user_ns, YCRED(p)->fsgid)
+#define EXTRACT_gid(x) from_kgid(&init_user_ns, x)
+#define EXTRACT_uid(x) from_kuid(&init_user_ns, x)
+#define MAKE_gid(x) make_kgid(&init_user_ns, x)
+#define MAKE_uid(x) make_kuid(&init_user_ns, x)
+#endif
+
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
+static int yaffs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
+ dev_t rdev)
+#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
+static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,
+ dev_t rdev)
+#else
+static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,
+ int rdev)
+#endif
+{
+ struct inode *inode;
+
+ struct yaffs_obj *obj = NULL;
+ struct yaffs_dev *dev;
+
+ struct yaffs_obj *parent = yaffs_inode_to_obj(dir);
+
+ int error = -ENOSPC;
+ uid_t uid = YPROC_uid(current);
+ gid_t gid =
+ (dir->i_mode & S_ISGID) ? EXTRACT_gid(dir->i_gid) : YPROC_gid(current);
+
+ if ((dir->i_mode & S_ISGID) && S_ISDIR(mode))
+ mode |= S_ISGID;
+
+ if (parent) {
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_mknod: parent object %d type %d",
+ parent->obj_id, parent->variant_type);
+ } else {
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_mknod: could not get parent object");
+ return -EPERM;
+ }
+
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_mknod: making oject for %s, mode %x dev %x",
+ dentry->d_name.name, mode, rdev);
+
+ dev = parent->my_dev;
+
+ yaffs_gross_lock(dev);
+
+ switch (mode & S_IFMT) {
+ default:
+ /* Special (socket, fifo, device...) */
+ yaffs_trace(YAFFS_TRACE_OS, "yaffs_mknod: making special");
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
+ obj =
+ yaffs_create_special(parent, dentry->d_name.name, mode, uid,
+ gid, old_encode_dev(rdev));
+#else
+ obj =
+ yaffs_create_special(parent, dentry->d_name.name, mode, uid,
+ gid, rdev);
+#endif
+ break;
+ case S_IFREG: /* file */
+ yaffs_trace(YAFFS_TRACE_OS, "yaffs_mknod: making file");
+ obj = yaffs_create_file(parent, dentry->d_name.name, mode, uid,
+ gid);
+ break;
+ case S_IFDIR: /* directory */
+ yaffs_trace(YAFFS_TRACE_OS, "yaffs_mknod: making directory");
+ obj = yaffs_create_dir(parent, dentry->d_name.name, mode,
+ uid, gid);
+ break;
+ case S_IFLNK: /* symlink */
+ yaffs_trace(YAFFS_TRACE_OS, "yaffs_mknod: making symlink");
+ obj = NULL; /* Do we ever get here? */
+ break;
+ }
+
+ /* Can not call yaffs_get_inode() with gross lock held */
+ yaffs_gross_unlock(dev);
+
+ if (obj) {
+ inode = yaffs_get_inode(dir->i_sb, mode, rdev, obj);
+ d_instantiate(dentry, inode);
+ update_dir_time(dir);
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_mknod created object %d count = %d",
+ obj->obj_id, atomic_read(&inode->i_count));
+ error = 0;
+ yaffs_fill_inode_from_obj(dir, parent);
+ } else {
+ yaffs_trace(YAFFS_TRACE_OS, "yaffs_mknod failed making object");
+ error = -ENOMEM;
+ }
+
+ return error;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
+static int yaffs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
+#else
+static int yaffs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+#endif
+{
+ int ret_val;
+ yaffs_trace(YAFFS_TRACE_OS, "yaffs_mkdir");
+ ret_val = yaffs_mknod(dir, dentry, mode | S_IFDIR, 0);
+ return ret_val;
+}
+
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
+static int yaffs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
+ bool dummy)
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
+static int yaffs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
+ struct nameidata *n)
+#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
+static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode,
+ struct nameidata *n)
+#else
+static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode)
+#endif
+{
+ yaffs_trace(YAFFS_TRACE_OS, "yaffs_create");
+ return yaffs_mknod(dir, dentry, mode | S_IFREG, 0);
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
+static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry,
+ unsigned int dummy)
+#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
+static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry,
+ struct nameidata *n)
+#else
+static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry)
+#endif
+{
+ struct yaffs_obj *obj;
+ struct inode *inode = NULL; /* NCB 2.5/2.6 needs NULL here */
+
+ struct yaffs_dev *dev = yaffs_inode_to_obj(dir)->my_dev;
+
+ if (current != yaffs_dev_to_lc(dev)->readdir_process)
+ yaffs_gross_lock(dev);
+
+ yaffs_trace(YAFFS_TRACE_OS, "yaffs_lookup for %d:%s",
+ yaffs_inode_to_obj(dir)->obj_id, dentry->d_name.name);
+
+ obj = yaffs_find_by_name(yaffs_inode_to_obj(dir), dentry->d_name.name);
+
+ obj = yaffs_get_equivalent_obj(obj); /* in case it was a hardlink */
+
+ /* Can't hold gross lock when calling yaffs_get_inode() */
+ if (current != yaffs_dev_to_lc(dev)->readdir_process)
+ yaffs_gross_unlock(dev);
+
+ if (obj) {
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_lookup found %d", obj->obj_id);
+
+ inode = yaffs_get_inode(dir->i_sb, obj->yst_mode, 0, obj);
+ } else {
+ yaffs_trace(YAFFS_TRACE_OS, "yaffs_lookup not found");
+
+ }
+
+/* added NCB for 2.5/6 compatability - forces add even if inode is
+ * NULL which creates dentry hash */
+ d_add(dentry, inode);
+
+ return NULL;
+}
+
+/*
+ * Create a link...
+ */
+static int yaffs_link(struct dentry *old_dentry, struct inode *dir,
+ struct dentry *dentry)
+{
+ struct inode *inode = old_dentry->d_inode;
+ struct yaffs_obj *obj = NULL;
+ struct yaffs_obj *link = NULL;
+ struct yaffs_dev *dev;
+
+ yaffs_trace(YAFFS_TRACE_OS, "yaffs_link");
+
+ obj = yaffs_inode_to_obj(inode);
+ dev = obj->my_dev;
+
+ yaffs_gross_lock(dev);
+
+ if (!S_ISDIR(inode->i_mode)) /* Don't link directories */
+ link =
+ yaffs_link_obj(yaffs_inode_to_obj(dir), dentry->d_name.name,
+ obj);
+
+ if (link) {
+ set_nlink(old_dentry->d_inode, yaffs_get_obj_link_count(obj));
+ d_instantiate(dentry, old_dentry->d_inode);
+ atomic_inc(&old_dentry->d_inode->i_count);
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_link link count %d i_count %d",
+ old_dentry->d_inode->i_nlink,
+ atomic_read(&old_dentry->d_inode->i_count));
+ }
+
+ yaffs_gross_unlock(dev);
+
+ if (link) {
+ update_dir_time(dir);
+ return 0;
+ }
+
+ return -EPERM;
+}
+
+static int yaffs_symlink(struct inode *dir, struct dentry *dentry,
+ const char *symname)
+{
+ struct yaffs_obj *obj;
+ struct yaffs_dev *dev;
+ uid_t uid = YPROC_uid(current);
+ gid_t gid =
+ (dir->i_mode & S_ISGID) ? EXTRACT_gid(dir->i_gid) : YPROC_gid(current);
+
+ yaffs_trace(YAFFS_TRACE_OS, "yaffs_symlink");
+
+ if (strnlen(dentry->d_name.name, YAFFS_MAX_NAME_LENGTH + 1) >
+ YAFFS_MAX_NAME_LENGTH)
+ return -ENAMETOOLONG;
+
+ if (strnlen(symname, YAFFS_MAX_ALIAS_LENGTH + 1) >
+ YAFFS_MAX_ALIAS_LENGTH)
+ return -ENAMETOOLONG;
+
+ dev = yaffs_inode_to_obj(dir)->my_dev;
+ yaffs_gross_lock(dev);
+ obj = yaffs_create_symlink(yaffs_inode_to_obj(dir), dentry->d_name.name,
+ S_IFLNK | S_IRWXUGO, uid, gid, symname);
+ yaffs_gross_unlock(dev);
+
+ if (obj) {
+ struct inode *inode;
+
+ inode = yaffs_get_inode(dir->i_sb, obj->yst_mode, 0, obj);
+ d_instantiate(dentry, inode);
+ update_dir_time(dir);
+ yaffs_trace(YAFFS_TRACE_OS, "symlink created OK");
+ return 0;
+ } else {
+ yaffs_trace(YAFFS_TRACE_OS, "symlink not created");
+ }
+
+ return -ENOMEM;
+}
+
+/*
+ * The VFS layer already does all the dentry stuff for rename.
+ *
+ * NB: POSIX says you can rename an object over an old object of the same name
+ */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
+static int yaffs_rename(struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry, unsigned int unused)
+#else
+static int yaffs_rename(struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry)
+#endif
+{
+ struct yaffs_dev *dev;
+ int ret_val = YAFFS_FAIL;
+ struct yaffs_obj *target;
+
+ yaffs_trace(YAFFS_TRACE_OS, "yaffs_rename");
+ dev = yaffs_inode_to_obj(old_dir)->my_dev;
+
+ yaffs_gross_lock(dev);
+
+ /* Check if the target is an existing directory that is not empty. */
+ target = yaffs_find_by_name(yaffs_inode_to_obj(new_dir),
+ new_dentry->d_name.name);
+
+ if (target && target->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY &&
+ !list_empty(&target->variant.dir_variant.children)) {
+
+ yaffs_trace(YAFFS_TRACE_OS, "target is non-empty dir");
+
+ ret_val = YAFFS_FAIL;
+ } else {
+ /* Now does unlinking internally using shadowing mechanism */
+ yaffs_trace(YAFFS_TRACE_OS, "calling yaffs_rename_obj");
+
+ ret_val = yaffs_rename_obj(yaffs_inode_to_obj(old_dir),
+ old_dentry->d_name.name,
+ yaffs_inode_to_obj(new_dir),
+ new_dentry->d_name.name);
+ }
+ yaffs_gross_unlock(dev);
+
+ if (ret_val == YAFFS_OK) {
+ if (target)
+ inode_dec_link_count(new_dentry->d_inode);
+
+ update_dir_time(old_dir);
+ if (old_dir != new_dir)
+ update_dir_time(new_dir);
+ return 0;
+ } else {
+ return -ENOTEMPTY;
+ }
+}
+
+
+
+
+static int yaffs_unlink(struct inode *dir, struct dentry *dentry)
+{
+ int ret_val;
+
+ struct yaffs_dev *dev;
+ struct yaffs_obj *obj;
+
+ yaffs_trace(YAFFS_TRACE_OS, "yaffs_unlink %d:%s",
+ (int)(dir->i_ino), dentry->d_name.name);
+ obj = yaffs_inode_to_obj(dir);
+ dev = obj->my_dev;
+
+ yaffs_gross_lock(dev);
+
+ ret_val = yaffs_unlinker(obj, dentry->d_name.name);
+
+ if (ret_val == YAFFS_OK) {
+ inode_dec_link_count(dentry->d_inode);
+ dir->i_version++;
+ yaffs_gross_unlock(dev);
+ update_dir_time(dir);
+ return 0;
+ }
+ yaffs_gross_unlock(dev);
+ return -ENOTEMPTY;
+}
+
+
+
+static const struct inode_operations yaffs_dir_inode_operations = {
+ .create = yaffs_create,
+ .lookup = yaffs_lookup,
+ .link = yaffs_link,
+ .unlink = yaffs_unlink,
+ .symlink = yaffs_symlink,
+ .mkdir = yaffs_mkdir,
+ .rmdir = yaffs_unlink,
+ .mknod = yaffs_mknod,
+ .rename = yaffs_rename,
+ .setattr = yaffs_setattr,
+ .listxattr = yaffs_listxattr,
+#ifdef YAFFS_USE_XATTR
+ .setxattr = yaffs_setxattr,
+ .getxattr = yaffs_getxattr,
+ .removexattr = yaffs_removexattr,
+#endif
+};
+
+/*-----------------------------------------------------------------*/
+/* Directory search context allows us to unlock access to yaffs during
+ * filldir without causing problems with the directory being modified.
+ * This is similar to the tried and tested mechanism used in yaffs direct.
+ *
+ * A search context iterates along a doubly linked list of siblings in the
+ * directory. If the iterating object is deleted then this would corrupt
+ * the list iteration, likely causing a crash. The search context avoids
+ * this by using the remove_obj_fn to move the search context to the
+ * next object before the object is deleted.
+ *
+ * Many readdirs (and thus seach conexts) may be alive simulateously so
+ * each struct yaffs_dev has a list of these.
+ *
+ * A seach context lives for the duration of a readdir.
+ *
+ * All these functions must be called while yaffs is locked.
+ */
+
+struct yaffs_search_context {
+ struct yaffs_dev *dev;
+ struct yaffs_obj *dir_obj;
+ struct yaffs_obj *next_return;
+ struct list_head others;
+};
+
+/*
+ * yaffs_new_search() creates a new search context, initialises it and
+ * adds it to the device's search context list.
+ *
+ * Called at start of readdir.
+ */
+static struct yaffs_search_context *yaffs_new_search(struct yaffs_obj *dir)
+{
+ struct yaffs_dev *dev = dir->my_dev;
+ struct yaffs_search_context *sc =
+ kmalloc(sizeof(struct yaffs_search_context), GFP_NOFS);
+ if (sc) {
+ sc->dir_obj = dir;
+ sc->dev = dev;
+ if (list_empty(&sc->dir_obj->variant.dir_variant.children))
+ sc->next_return = NULL;
+ else
+ sc->next_return =
+ list_entry(dir->variant.dir_variant.children.next,
+ struct yaffs_obj, siblings);
+ INIT_LIST_HEAD(&sc->others);
+ list_add(&sc->others, &(yaffs_dev_to_lc(dev)->search_contexts));
+ }
+ return sc;
+}
+
+/*
+ * yaffs_search_end() disposes of a search context and cleans up.
+ */
+static void yaffs_search_end(struct yaffs_search_context *sc)
+{
+ if (sc) {
+ list_del(&sc->others);
+ kfree(sc);
+ }
+}
+
+/*
+ * yaffs_search_advance() moves a search context to the next object.
+ * Called when the search iterates or when an object removal causes
+ * the search context to be moved to the next object.
+ */
+static void yaffs_search_advance(struct yaffs_search_context *sc)
+{
+ if (!sc)
+ return;
+
+ if (sc->next_return == NULL ||
+ list_empty(&sc->dir_obj->variant.dir_variant.children))
+ sc->next_return = NULL;
+ else {
+ struct list_head *next = sc->next_return->siblings.next;
+
+ if (next == &sc->dir_obj->variant.dir_variant.children)
+ sc->next_return = NULL; /* end of list */
+ else
+ sc->next_return =
+ list_entry(next, struct yaffs_obj, siblings);
+ }
+}
+
+/*
+ * yaffs_remove_obj_callback() is called when an object is unlinked.
+ * We check open search contexts and advance any which are currently
+ * on the object being iterated.
+ */
+static void yaffs_remove_obj_callback(struct yaffs_obj *obj)
+{
+
+ struct list_head *i;
+ struct yaffs_search_context *sc;
+ struct list_head *search_contexts =
+ &(yaffs_dev_to_lc(obj->my_dev)->search_contexts);
+
+ /* Iterate through the directory search contexts.
+ * If any are currently on the object being removed, then advance
+ * the search context to the next object to prevent a hanging pointer.
+ */
+ list_for_each(i, search_contexts) {
+ sc = list_entry(i, struct yaffs_search_context, others);
+ if (sc->next_return == obj)
+ yaffs_search_advance(sc);
+ }
+
+}
+
+
+/*-----------------------------------------------------------------*/
+
+#ifdef YAFFS_USE_DIR_ITERATE
+static int yaffs_iterate(struct file *f, struct dir_context *dc)
+{
+ struct yaffs_obj *obj;
+ struct yaffs_dev *dev;
+ struct yaffs_search_context *sc;
+ unsigned long curoffs;
+ struct yaffs_obj *l;
+ int ret_val = 0;
+
+ char name[YAFFS_MAX_NAME_LENGTH + 1];
+
+ obj = yaffs_dentry_to_obj(Y_GET_DENTRY(f));
+ dev = obj->my_dev;
+
+ yaffs_gross_lock(dev);
+
+ yaffs_dev_to_lc(dev)->readdir_process = current;
+
+ sc = yaffs_new_search(obj);
+ if (!sc) {
+ ret_val = -ENOMEM;
+ goto out;
+ }
+
+ if (!dir_emit_dots(f, dc))
+ return 0;
+
+ curoffs = 1;
+
+ while (sc->next_return) {
+ curoffs++;
+ l = sc->next_return;
+ if (curoffs >= dc->pos) {
+ int this_inode = yaffs_get_obj_inode(l);
+ int this_type = yaffs_get_obj_type(l);
+
+ yaffs_get_obj_name(l, name, YAFFS_MAX_NAME_LENGTH + 1);
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_readdir: %s inode %d",
+ name, yaffs_get_obj_inode(l));
+
+ yaffs_gross_unlock(dev);
+
+ if (!dir_emit(dc,
+ name,
+ strlen(name),
+ this_inode,
+ this_type)) {
+ yaffs_gross_lock(dev);
+ goto out;
+ }
+
+ yaffs_gross_lock(dev);
+
+ dc->pos++;
+ f->f_pos++;
+ }
+ yaffs_search_advance(sc);
+ }
+
+out:
+ yaffs_search_end(sc);
+ yaffs_dev_to_lc(dev)->readdir_process = NULL;
+ yaffs_gross_unlock(dev);
+
+ return ret_val;
+}
+
+#else
+
+static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir)
+{
+ struct yaffs_obj *obj;
+ struct yaffs_dev *dev;
+ struct yaffs_search_context *sc;
+ struct inode *inode = Y_GET_DENTRY(f)->d_inode;
+ unsigned long offset, curoffs;
+ struct yaffs_obj *l;
+ int ret_val = 0;
+
+ char name[YAFFS_MAX_NAME_LENGTH + 1];
+
+ obj = yaffs_dentry_to_obj(Y_GET_DENTRY(f));
+ dev = obj->my_dev;
+
+ yaffs_gross_lock(dev);
+
+ yaffs_dev_to_lc(dev)->readdir_process = current;
+
+ offset = f->f_pos;
+
+ sc = yaffs_new_search(obj);
+ if (!sc) {
+ ret_val = -ENOMEM;
+ goto out;
+ }
+
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_readdir: starting at %d", (int)offset);
+
+ if (offset == 0) {
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_readdir: entry . ino %d",
+ (int)inode->i_ino);
+ yaffs_gross_unlock(dev);
+ if (filldir(dirent, ".", 1, offset, inode->i_ino, DT_DIR) < 0) {
+ yaffs_gross_lock(dev);
+ goto out;
+ }
+ yaffs_gross_lock(dev);
+ offset++;
+ f->f_pos++;
+ }
+ if (offset == 1) {
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_readdir: entry .. ino %d",
+ (int)f->f_dentry->d_parent->d_inode->i_ino);
+ yaffs_gross_unlock(dev);
+ if (filldir(dirent, "..", 2, offset,
+ f->f_dentry->d_parent->d_inode->i_ino,
+ DT_DIR) < 0) {
+ yaffs_gross_lock(dev);
+ goto out;
+ }
+ yaffs_gross_lock(dev);
+ offset++;
+ f->f_pos++;
+ }
+
+ curoffs = 1;
+
+ /* If the directory has changed since the open or last call to
+ readdir, rewind to after the 2 canned entries. */
+ if (f->f_version != inode->i_version) {
+ offset = 2;
+ f->f_pos = offset;
+ f->f_version = inode->i_version;
+ }
+
+ while (sc->next_return) {
+ curoffs++;
+ l = sc->next_return;
+ if (curoffs >= offset) {
+ int this_inode = yaffs_get_obj_inode(l);
+ int this_type = yaffs_get_obj_type(l);
+
+ yaffs_get_obj_name(l, name, YAFFS_MAX_NAME_LENGTH + 1);
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_readdir: %s inode %d",
+ name, yaffs_get_obj_inode(l));
+
+ yaffs_gross_unlock(dev);
+
+ if (filldir(dirent,
+ name,
+ strlen(name),
+ offset, this_inode, this_type) < 0) {
+ yaffs_gross_lock(dev);
+ goto out;
+ }
+
+ yaffs_gross_lock(dev);
+
+ offset++;
+ f->f_pos++;
+ }
+ yaffs_search_advance(sc);
+ }
+
+out:
+ yaffs_search_end(sc);
+ yaffs_dev_to_lc(dev)->readdir_process = NULL;
+ yaffs_gross_unlock(dev);
+
+ return ret_val;
+}
+
+#endif
+
+static const struct file_operations yaffs_dir_operations = {
+ .read = generic_read_dir,
+#ifdef YAFFS_USE_DIR_ITERATE
+ .iterate = yaffs_iterate,
+#else
+ .readdir = yaffs_readdir,
+#endif
+ .fsync = yaffs_sync_object,
+ .llseek = generic_file_llseek,
+};
+
+static void yaffs_fill_inode_from_obj(struct inode *inode,
+ struct yaffs_obj *obj)
+{
+ if (inode && obj) {
+
+ /* Check mode against the variant type and attempt to repair if broken. */
+ u32 mode = obj->yst_mode;
+ switch (obj->variant_type) {
+ case YAFFS_OBJECT_TYPE_FILE:
+ if (!S_ISREG(mode)) {
+ obj->yst_mode &= ~S_IFMT;
+ obj->yst_mode |= S_IFREG;
+ }
+
+ break;
+ case YAFFS_OBJECT_TYPE_SYMLINK:
+ if (!S_ISLNK(mode)) {
+ obj->yst_mode &= ~S_IFMT;
+ obj->yst_mode |= S_IFLNK;
+ }
+
+ break;
+ case YAFFS_OBJECT_TYPE_DIRECTORY:
+ if (!S_ISDIR(mode)) {
+ obj->yst_mode &= ~S_IFMT;
+ obj->yst_mode |= S_IFDIR;
+ }
+
+ break;
+ case YAFFS_OBJECT_TYPE_UNKNOWN:
+ case YAFFS_OBJECT_TYPE_HARDLINK:
+ case YAFFS_OBJECT_TYPE_SPECIAL:
+ default:
+ /* TODO? */
+ break;
+ }
+
+ inode->i_flags |= S_NOATIME;
+
+ inode->i_ino = obj->obj_id;
+ inode->i_mode = obj->yst_mode;
+ inode->i_uid = MAKE_uid(obj->yst_uid);
+ inode->i_gid = MAKE_gid(obj->yst_gid);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
+ inode->i_blksize = inode->i_sb->s_blocksize;
+#endif
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
+
+ inode->i_rdev = old_decode_dev(obj->yst_rdev);
+ inode->i_atime.tv_sec = (time_t) (obj->yst_atime);
+ inode->i_atime.tv_nsec = 0;
+ inode->i_mtime.tv_sec = (time_t) obj->yst_mtime;
+ inode->i_mtime.tv_nsec = 0;
+ inode->i_ctime.tv_sec = (time_t) obj->yst_ctime;
+ inode->i_ctime.tv_nsec = 0;
+#else
+ inode->i_rdev = obj->yst_rdev;
+ inode->i_atime = obj->yst_atime;
+ inode->i_mtime = obj->yst_mtime;
+ inode->i_ctime = obj->yst_ctime;
+#endif
+ inode->i_size = yaffs_get_obj_length(obj);
+ inode->i_blocks = (inode->i_size + 511) >> 9;
+
+ set_nlink(inode, yaffs_get_obj_link_count(obj));
+
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_fill_inode mode %x uid %d gid %d size %lld count %d",
+ inode->i_mode, obj->yst_uid, obj->yst_gid,
+ inode->i_size, atomic_read(&inode->i_count));
+
+ switch (obj->yst_mode & S_IFMT) {
+ default: /* fifo, device or socket */
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
+ init_special_inode(inode, obj->yst_mode,
+ old_decode_dev(obj->yst_rdev));
+#else
+ init_special_inode(inode, obj->yst_mode,
+ (dev_t) (obj->yst_rdev));
+#endif
+ break;
+ case S_IFREG: /* file */
+ inode->i_op = &yaffs_file_inode_operations;
+ inode->i_fop = &yaffs_file_operations;
+ inode->i_mapping->a_ops =
+ &yaffs_file_address_operations;
+ break;
+ case S_IFDIR: /* directory */
+ inode->i_op = &yaffs_dir_inode_operations;
+ inode->i_fop = &yaffs_dir_operations;
+ break;
+ case S_IFLNK: /* symlink */
+ inode->i_op = &yaffs_symlink_inode_operations;
+ break;
+ }
+
+ yaffs_inode_to_obj_lv(inode) = obj;
+
+ obj->my_inode = inode;
+
+ } else {
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_fill_inode invalid parameters");
+ }
+
+}
+
+
+
+/*
+ * yaffs background thread functions .
+ * yaffs_bg_thread_fn() the thread function
+ * yaffs_bg_start() launches the background thread.
+ * yaffs_bg_stop() cleans up the background thread.
+ *
+ * NB:
+ * The thread should only run after the yaffs is initialised
+ * The thread should be stopped before yaffs is unmounted.
+ * The thread should not do any writing while the fs is in read only.
+ */
+
+static unsigned yaffs_bg_gc_urgency(struct yaffs_dev *dev)
+{
+ unsigned erased_chunks =
+ dev->n_erased_blocks * dev->param.chunks_per_block;
+ struct yaffs_linux_context *context = yaffs_dev_to_lc(dev);
+ unsigned scattered = 0; /* Free chunks not in an erased block */
+
+ if (erased_chunks < dev->n_free_chunks)
+ scattered = (dev->n_free_chunks - erased_chunks);
+
+ if (!context->bg_running)
+ return 0;
+ else if (scattered < (dev->param.chunks_per_block * 2))
+ return 0;
+ else if (erased_chunks > dev->n_free_chunks / 2)
+ return 0;
+ else if (erased_chunks > dev->n_free_chunks / 4)
+ return 1;
+ else
+ return 2;
+}
+
+#ifdef YAFFS_COMPILE_BACKGROUND
+
+void yaffs_background_waker(unsigned long data)
+{
+ wake_up_process((struct task_struct *)data);
+}
+
+static int yaffs_bg_thread_fn(void *data)
+{
+ struct yaffs_dev *dev = (struct yaffs_dev *)data;
+ struct yaffs_linux_context *context = yaffs_dev_to_lc(dev);
+ unsigned long now = jiffies;
+ unsigned long next_dir_update = now;
+ unsigned long next_gc = now;
+ unsigned long expires;
+ unsigned int urgency;
+
+ int gc_result;
+ struct timer_list timer;
+
+ yaffs_trace(YAFFS_TRACE_BACKGROUND,
+ "yaffs_background starting for dev %p", (void *)dev);
+
+#ifdef YAFFS_COMPILE_FREEZER
+ set_freezable();
+#endif
+ while (context->bg_running) {
+ yaffs_trace(YAFFS_TRACE_BACKGROUND, "yaffs_background");
+
+ if (kthread_should_stop())
+ break;
+
+#ifdef YAFFS_COMPILE_FREEZER
+ if (try_to_freeze())
+ continue;
+#endif
+ yaffs_gross_lock(dev);
+
+ now = jiffies;
+
+ if (time_after(now, next_dir_update) && yaffs_bg_enable) {
+ yaffs_update_dirty_dirs(dev);
+ next_dir_update = now + HZ;
+ }
+
+ if (time_after(now, next_gc) && yaffs_bg_enable) {
+ if (!dev->is_checkpointed) {
+ urgency = yaffs_bg_gc_urgency(dev);
+ gc_result = yaffs_bg_gc(dev, urgency);
+ if (urgency > 1)
+ next_gc = now + HZ / 20 + 1;
+ else if (urgency > 0)
+ next_gc = now + HZ / 10 + 1;
+ else
+ next_gc = now + HZ * 2;
+ } else {
+ /*
+ * gc not running so set to next_dir_update
+ * to cut down on wake ups
+ */
+ next_gc = next_dir_update;
+ }
+ }
+ yaffs_gross_unlock(dev);
+#if 1
+ expires = next_dir_update;
+ if (time_before(next_gc, expires))
+ expires = next_gc;
+ if (time_before(expires, now))
+ expires = now + HZ;
+
+ Y_INIT_TIMER(&timer);
+ timer.expires = expires + 1;
+ timer.data = (unsigned long)current;
+ timer.function = yaffs_background_waker;
+
+ set_current_state(TASK_INTERRUPTIBLE);
+ add_timer(&timer);
+ schedule();
+ del_timer_sync(&timer);
+#else
+ msleep(10);
+#endif
+ }
+
+ return 0;
+}
+
+static int yaffs_bg_start(struct yaffs_dev *dev)
+{
+ int retval = 0;
+ struct yaffs_linux_context *context = yaffs_dev_to_lc(dev);
+
+ if (dev->read_only)
+ return -1;
+
+ context->bg_running = 1;
+
+ context->bg_thread = kthread_run(yaffs_bg_thread_fn,
+ (void *)dev, "yaffs-bg-%d",
+ context->mount_id);
+
+ if (IS_ERR(context->bg_thread)) {
+ retval = PTR_ERR(context->bg_thread);
+ context->bg_thread = NULL;
+ context->bg_running = 0;
+ }
+ return retval;
+}
+
+static void yaffs_bg_stop(struct yaffs_dev *dev)
+{
+ struct yaffs_linux_context *ctxt = yaffs_dev_to_lc(dev);
+
+ ctxt->bg_running = 0;
+
+ if (ctxt->bg_thread) {
+ kthread_stop(ctxt->bg_thread);
+ ctxt->bg_thread = NULL;
+ }
+}
+#else
+static int yaffs_bg_thread_fn(void *data)
+{
+ return 0;
+}
+
+static int yaffs_bg_start(struct yaffs_dev *dev)
+{
+ return 0;
+}
+
+static void yaffs_bg_stop(struct yaffs_dev *dev)
+{
+}
+#endif
+
+
+static void yaffs_flush_inodes(struct super_block *sb)
+{
+ struct inode *iptr;
+ struct yaffs_obj *obj;
+
+ list_for_each_entry(iptr, &sb->s_inodes, i_sb_list) {
+ obj = yaffs_inode_to_obj(iptr);
+ if (obj) {
+ yaffs_trace(YAFFS_TRACE_OS,
+ "flushing obj %d",
+ obj->obj_id);
+ yaffs_flush_file(obj, 1, 0, 0);
+ }
+ }
+}
+
+static void yaffs_flush_super(struct super_block *sb, int do_checkpoint)
+{
+ struct yaffs_dev *dev = yaffs_super_to_dev(sb);
+ if (!dev)
+ return;
+
+ yaffs_flush_inodes(sb);
+ yaffs_update_dirty_dirs(dev);
+ yaffs_flush_whole_cache(dev, 1);
+ if (do_checkpoint)
+ yaffs_checkpoint_save(dev);
+}
+
+static LIST_HEAD(yaffs_context_list);
+struct mutex yaffs_context_lock;
+
+static void yaffs_put_super(struct super_block *sb)
+{
+ struct yaffs_dev *dev = yaffs_super_to_dev(sb);
+ struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
+
+ yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_ALWAYS,
+ "yaffs_put_super");
+
+ yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_BACKGROUND,
+ "Shutting down yaffs background thread");
+ yaffs_bg_stop(dev);
+ yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_BACKGROUND,
+ "yaffs background thread shut down");
+
+ yaffs_gross_lock(dev);
+
+ yaffs_flush_super(sb, 1);
+
+ yaffs_deinitialise(dev);
+
+ yaffs_gross_unlock(dev);
+
+ mutex_lock(&yaffs_context_lock);
+ list_del_init(&(yaffs_dev_to_lc(dev)->context_list));
+ mutex_unlock(&yaffs_context_lock);
+
+ if (yaffs_dev_to_lc(dev)->spare_buffer) {
+ kfree(yaffs_dev_to_lc(dev)->spare_buffer);
+ yaffs_dev_to_lc(dev)->spare_buffer = NULL;
+ }
+
+ kfree(dev);
+
+ yaffs_put_mtd_device(mtd);
+
+ yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_ALWAYS,
+ "yaffs_put_super done");
+}
+
+
+static unsigned yaffs_gc_control_callback(struct yaffs_dev *dev)
+{
+ return yaffs_gc_control;
+}
+
+
+#ifdef YAFFS_COMPILE_EXPORTFS
+
+static struct inode *yaffs2_nfs_get_inode(struct super_block *sb, uint64_t ino,
+ uint32_t generation)
+{
+ return Y_IGET(sb, ino);
+}
+
+static struct dentry *yaffs2_fh_to_dentry(struct super_block *sb,
+ struct fid *fid, int fh_len,
+ int fh_type)
+{
+ return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
+ yaffs2_nfs_get_inode);
+}
+
+static struct dentry *yaffs2_fh_to_parent(struct super_block *sb,
+ struct fid *fid, int fh_len,
+ int fh_type)
+{
+ return generic_fh_to_parent(sb, fid, fh_len, fh_type,
+ yaffs2_nfs_get_inode);
+}
+
+struct dentry *yaffs2_get_parent(struct dentry *dentry)
+{
+
+ struct super_block *sb = dentry->d_inode->i_sb;
+ struct dentry *parent = ERR_PTR(-ENOENT);
+ struct inode *inode;
+ unsigned long parent_ino;
+ struct yaffs_obj *d_obj;
+ struct yaffs_obj *parent_obj;
+
+ d_obj = yaffs_inode_to_obj(dentry->d_inode);
+
+ if (d_obj) {
+ parent_obj = d_obj->parent;
+ if (parent_obj) {
+ parent_ino = yaffs_get_obj_inode(parent_obj);
+ inode = Y_IGET(sb, parent_ino);
+
+ if (IS_ERR(inode)) {
+ parent = ERR_CAST(inode);
+ } else {
+ parent = d_obtain_alias(inode);
+ if (!IS_ERR(parent)) {
+ parent = ERR_PTR(-ENOMEM);
+ iput(inode);
+ }
+ }
+ }
+ }
+
+ return parent;
+}
+
+/* Just declare a zero structure as a NULL value implies
+ * using the default functions of exportfs.
+ */
+
+static struct export_operations yaffs_export_ops = {
+ .fh_to_dentry = yaffs2_fh_to_dentry,
+ .fh_to_parent = yaffs2_fh_to_parent,
+ .get_parent = yaffs2_get_parent,
+};
+
+#endif
+
+static void yaffs_unstitch_obj(struct inode *inode, struct yaffs_obj *obj)
+{
+ /* Clear the association between the inode and
+ * the struct yaffs_obj.
+ */
+ obj->my_inode = NULL;
+ yaffs_inode_to_obj_lv(inode) = NULL;
+
+ /* If the object freeing was deferred, then the real
+ * free happens now.
+ * This should fix the inode inconsistency problem.
+ */
+ yaffs_handle_defered_free(obj);
+}
+
+#ifdef YAFFS_HAS_EVICT_INODE
+/* yaffs_evict_inode combines into one operation what was previously done in
+ * yaffs_clear_inode() and yaffs_delete_inode()
+ *
+ */
+static void yaffs_evict_inode(struct inode *inode)
+{
+ struct yaffs_obj *obj;
+ struct yaffs_dev *dev;
+ int deleteme = 0;
+
+ obj = yaffs_inode_to_obj(inode);
+
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_evict_inode: ino %d, count %d %s",
+ (int)inode->i_ino, atomic_read(&inode->i_count),
+ obj ? "object exists" : "null object");
+
+ if (!inode->i_nlink && !is_bad_inode(inode))
+ deleteme = 1;
+ truncate_inode_pages(&inode->i_data, 0);
+ Y_CLEAR_INODE(inode);
+
+ if (deleteme && obj) {
+ dev = obj->my_dev;
+ yaffs_gross_lock(dev);
+ yaffs_del_obj(obj);
+ yaffs_gross_unlock(dev);
+ }
+ if (obj) {
+ dev = obj->my_dev;
+ yaffs_gross_lock(dev);
+ yaffs_unstitch_obj(inode, obj);
+ yaffs_gross_unlock(dev);
+ }
+}
+#else
+
+/* clear is called to tell the fs to release any per-inode data it holds.
+ * The object might still exist on disk and is just being thrown out of the cache
+ * or else the object has actually been deleted and we're being called via
+ * the chain
+ * yaffs_delete_inode() -> clear_inode()->yaffs_clear_inode()
+ */
+
+static void yaffs_clear_inode(struct inode *inode)
+{
+ struct yaffs_obj *obj;
+ struct yaffs_dev *dev;
+
+ obj = yaffs_inode_to_obj(inode);
+
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_clear_inode: ino %d, count %d %s",
+ (int)inode->i_ino, atomic_read(&inode->i_count),
+ obj ? "object exists" : "null object");
+
+ if (obj) {
+ dev = obj->my_dev;
+ yaffs_gross_lock(dev);
+ yaffs_unstitch_obj(inode, obj);
+ yaffs_gross_unlock(dev);
+ }
+
+}
+
+/* delete is called when the link count is zero and the inode
+ * is put (ie. nobody wants to know about it anymore, time to
+ * delete the file).
+ * NB Must call clear_inode()
+ */
+static void yaffs_delete_inode(struct inode *inode)
+{
+ struct yaffs_obj *obj = yaffs_inode_to_obj(inode);
+ struct yaffs_dev *dev;
+
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_delete_inode: ino %d, count %d %s",
+ (int)inode->i_ino, atomic_read(&inode->i_count),
+ obj ? "object exists" : "null object");
+
+ if (obj) {
+ dev = obj->my_dev;
+ yaffs_gross_lock(dev);
+ yaffs_del_obj(obj);
+ yaffs_gross_unlock(dev);
+ }
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13))
+ truncate_inode_pages(&inode->i_data, 0);
+#endif
+ clear_inode(inode);
+}
+#endif
+
+
+
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
+static int yaffs_statfs(struct dentry *dentry, struct kstatfs *buf)
+{
+ struct yaffs_dev *dev = yaffs_dentry_to_obj(dentry)->my_dev;
+ struct super_block *sb = dentry->d_sb;
+#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
+static int yaffs_statfs(struct super_block *sb, struct kstatfs *buf)
+{
+ struct yaffs_dev *dev = yaffs_super_to_dev(sb);
+#else
+static int yaffs_statfs(struct super_block *sb, struct statfs *buf)
+{
+ struct yaffs_dev *dev = yaffs_super_to_dev(sb);
+#endif
+
+ yaffs_trace(YAFFS_TRACE_OS, "yaffs_statfs");
+
+ yaffs_gross_lock(dev);
+
+ buf->f_type = YAFFS_MAGIC;
+ buf->f_bsize = sb->s_blocksize;
+ buf->f_namelen = 255;
+
+ if (dev->data_bytes_per_chunk & (dev->data_bytes_per_chunk - 1)) {
+ /* Do this if chunk size is not a power of 2 */
+
+ uint64_t bytes_in_dev;
+ uint64_t bytes_free;
+
+ bytes_in_dev =
+ ((uint64_t)
+ ((dev->param.end_block - dev->param.start_block +
+ 1))) * ((uint64_t) (dev->param.chunks_per_block *
+ dev->data_bytes_per_chunk));
+
+ do_div(bytes_in_dev, sb->s_blocksize); /* bytes_in_dev becomes the number of blocks */
+ buf->f_blocks = bytes_in_dev;
+
+ bytes_free = ((uint64_t) (yaffs_get_n_free_chunks(dev))) *
+ ((uint64_t) (dev->data_bytes_per_chunk));
+
+ do_div(bytes_free, sb->s_blocksize);
+
+ buf->f_bfree = bytes_free;
+
+ } else if (sb->s_blocksize > dev->data_bytes_per_chunk) {
+
+ buf->f_blocks =
+ (dev->param.end_block - dev->param.start_block + 1) *
+ dev->param.chunks_per_block /
+ (sb->s_blocksize / dev->data_bytes_per_chunk);
+ buf->f_bfree =
+ yaffs_get_n_free_chunks(dev) /
+ (sb->s_blocksize / dev->data_bytes_per_chunk);
+ } else {
+ buf->f_blocks =
+ (dev->param.end_block - dev->param.start_block + 1) *
+ dev->param.chunks_per_block *
+ (dev->data_bytes_per_chunk / sb->s_blocksize);
+
+ buf->f_bfree =
+ yaffs_get_n_free_chunks(dev) *
+ (dev->data_bytes_per_chunk / sb->s_blocksize);
+ }
+
+ buf->f_files = 0;
+ buf->f_ffree = 0;
+ buf->f_bavail = buf->f_bfree;
+
+ yaffs_gross_unlock(dev);
+ return 0;
+}
+
+
+
+static int yaffs_do_sync_fs(struct super_block *sb, int request_checkpoint)
+{
+
+ struct yaffs_dev *dev = yaffs_super_to_dev(sb);
+ unsigned int oneshot_checkpoint = (yaffs_auto_checkpoint & 4);
+ unsigned gc_urgent = yaffs_bg_gc_urgency(dev);
+ int do_checkpoint;
+ int dirty = yaffs_check_super_dirty(dev);
+
+ yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC | YAFFS_TRACE_BACKGROUND,
+ "yaffs_do_sync_fs: gc-urgency %d %s %s%s",
+ gc_urgent,
+ dirty ? "dirty" : "clean",
+ request_checkpoint ? "checkpoint requested" : "no checkpoint",
+ oneshot_checkpoint ? " one-shot" : "");
+
+ yaffs_gross_lock(dev);
+ do_checkpoint = ((request_checkpoint && !gc_urgent) ||
+ oneshot_checkpoint) && !dev->is_checkpointed;
+
+ if (dirty || do_checkpoint) {
+ yaffs_flush_super(sb, !dev->is_checkpointed && do_checkpoint);
+ yaffs_clear_super_dirty(dev);
+ if (oneshot_checkpoint)
+ yaffs_auto_checkpoint &= ~4;
+ }
+ yaffs_gross_unlock(dev);
+
+ return 0;
+}
+
+
+#ifdef YAFFS_HAS_WRITE_SUPER
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
+static void yaffs_write_super(struct super_block *sb)
+#else
+static int yaffs_write_super(struct super_block *sb)
+#endif
+{
+ unsigned request_checkpoint = (yaffs_auto_checkpoint >= 2);
+
+ yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC | YAFFS_TRACE_BACKGROUND,
+ "yaffs_write_super %s",
+ request_checkpoint ? " checkpt" : "");
+
+ yaffs_do_sync_fs(sb, request_checkpoint);
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18))
+ return 0;
+#endif
+}
+#endif
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
+static int yaffs_sync_fs(struct super_block *sb, int wait)
+#else
+static int yaffs_sync_fs(struct super_block *sb)
+#endif
+{
+ unsigned request_checkpoint = (yaffs_auto_checkpoint >= 1);
+
+ yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC,
+ "yaffs_sync_fs%s", request_checkpoint ? " checkpt" : "");
+
+ yaffs_do_sync_fs(sb, request_checkpoint);
+
+ return 0;
+}
+
+/* the function only is used to change dev->read_only when this file system
+ * is remounted.
+ */
+static int yaffs_remount_fs(struct super_block *sb, int *flags, char *data)
+{
+ int read_only = 0;
+ struct mtd_info *mtd;
+ struct yaffs_dev *dev = 0;
+
+ /* Get the device */
+ mtd = get_mtd_device(NULL, MINOR(sb->s_dev));
+ if (!mtd) {
+ yaffs_trace(YAFFS_TRACE_ALWAYS,
+ "MTD device #%u doesn't appear to exist",
+ MINOR(sb->s_dev));
+ return 1;
+ }
+
+ /* Check it's NAND */
+ if (mtd->type != MTD_NANDFLASH) {
+ yaffs_trace(YAFFS_TRACE_ALWAYS,
+ "MTD device is not NAND it's type %d",
+ mtd->type);
+ return 1;
+ }
+
+ read_only = ((*flags & MS_RDONLY) != 0);
+ if (!read_only && !(mtd->flags & MTD_WRITEABLE)) {
+ read_only = 1;
+ printk(KERN_INFO
+ "yaffs: mtd is read only, setting superblock read only");
+ *flags |= MS_RDONLY;
+ }
+
+ dev = sb->s_fs_info;
+ dev->read_only = read_only;
+
+ return 0;
+}
+
+static const struct super_operations yaffs_super_ops = {
+ .statfs = yaffs_statfs,
+
+#ifndef YAFFS_USE_OWN_IGET
+ .read_inode = yaffs_read_inode,
+#endif
+#ifdef YAFFS_HAS_PUT_INODE
+ .put_inode = yaffs_put_inode,
+#endif
+ .put_super = yaffs_put_super,
+#ifdef YAFFS_HAS_EVICT_INODE
+ .evict_inode = yaffs_evict_inode,
+#else
+ .delete_inode = yaffs_delete_inode,
+ .clear_inode = yaffs_clear_inode,
+#endif
+ .sync_fs = yaffs_sync_fs,
+#ifdef YAFFS_HAS_WRITE_SUPER
+ .write_super = yaffs_write_super,
+#endif
+ .remount_fs = yaffs_remount_fs,
+};
+
+struct yaffs_options {
+ int inband_tags;
+ int skip_checkpoint_read;
+ int skip_checkpoint_write;
+ int no_cache;
+ int tags_ecc_on;
+ int tags_ecc_overridden;
+ int lazy_loading_enabled;
+ int lazy_loading_overridden;
+ int empty_lost_and_found;
+ int empty_lost_and_found_overridden;
+ int disable_summary;
+};
+
+#define MAX_OPT_LEN 30
+static int yaffs_parse_options(struct yaffs_options *options,
+ const char *options_str)
+{
+ char cur_opt[MAX_OPT_LEN + 1];
+ int p;
+ int error = 0;
+
+ /* Parse through the options which is a comma seperated list */
+
+ while (options_str && *options_str && !error) {
+ memset(cur_opt, 0, MAX_OPT_LEN + 1);
+ p = 0;
+
+ while (*options_str == ',')
+ options_str++;
+
+ while (*options_str && *options_str != ',') {
+ if (p < MAX_OPT_LEN) {
+ cur_opt[p] = *options_str;
+ p++;
+ }
+ options_str++;
+ }
+
+ if (!strcmp(cur_opt, "inband-tags")) {
+ options->inband_tags = 1;
+ } else if (!strcmp(cur_opt, "tags-ecc-off")) {
+ options->tags_ecc_on = 0;
+ options->tags_ecc_overridden = 1;
+ } else if (!strcmp(cur_opt, "tags-ecc-on")) {
+ options->tags_ecc_on = 1;
+ options->tags_ecc_overridden = 1;
+ } else if (!strcmp(cur_opt, "lazy-loading-off")) {
+ options->lazy_loading_enabled = 0;
+ options->lazy_loading_overridden = 1;
+ } else if (!strcmp(cur_opt, "lazy-loading-on")) {
+ options->lazy_loading_enabled = 1;
+ options->lazy_loading_overridden = 1;
+ } else if (!strcmp(cur_opt, "disable-summary")) {
+ options->disable_summary = 1;
+ } else if (!strcmp(cur_opt, "empty-lost-and-found-off")) {
+ options->empty_lost_and_found = 0;
+ options->empty_lost_and_found_overridden = 1;
+ } else if (!strcmp(cur_opt, "empty-lost-and-found-on")) {
+ options->empty_lost_and_found = 1;
+ options->empty_lost_and_found_overridden = 1;
+ } else if (!strcmp(cur_opt, "no-cache")) {
+ options->no_cache = 1;
+ } else if (!strcmp(cur_opt, "no-checkpoint-read")) {
+ options->skip_checkpoint_read = 1;
+ } else if (!strcmp(cur_opt, "no-checkpoint-write")) {
+ options->skip_checkpoint_write = 1;
+ } else if (!strcmp(cur_opt, "no-checkpoint")) {
+ options->skip_checkpoint_read = 1;
+ options->skip_checkpoint_write = 1;
+ } else {
+ printk(KERN_INFO "yaffs: Bad mount option \"%s\"\n",
+ cur_opt);
+ error = 1;
+ }
+ }
+
+ return error;
+}
+
+
+static struct dentry *yaffs_make_root(struct inode *inode)
+{
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0))
+ struct dentry *root = d_alloc_root(inode);
+
+ if (!root)
+ iput(inode);
+
+ return root;
+#else
+ return d_make_root(inode);
+#endif
+}
+
+
+
+
+static struct super_block *yaffs_internal_read_super(int yaffs_version,
+ struct super_block *sb,
+ void *data, int silent)
+{
+ int n_blocks;
+ struct inode *inode = NULL;
+ struct dentry *root;
+ struct yaffs_dev *dev = 0;
+ char devname_buf[BDEVNAME_SIZE + 1];
+ struct mtd_info *mtd;
+ int err;
+ char *data_str = (char *)data;
+ struct yaffs_linux_context *context = NULL;
+ struct yaffs_param *param;
+
+ int read_only = 0;
+ int inband_tags = 0;
+
+ struct yaffs_options options;
+
+ unsigned mount_id;
+ int found;
+ struct yaffs_linux_context *context_iterator;
+ struct list_head *l;
+
+ if (!sb) {
+ printk(KERN_INFO "yaffs: sb is NULL\n");
+ return NULL;
+ }
+
+ sb->s_magic = YAFFS_MAGIC;
+ sb->s_op = &yaffs_super_ops;
+ sb->s_flags |= MS_NOATIME;
+
+ read_only = ((sb->s_flags & MS_RDONLY) != 0);
+
+#ifdef YAFFS_COMPILE_EXPORTFS
+ sb->s_export_op = &yaffs_export_ops;
+#endif
+
+ if (!sb->s_dev)
+ printk(KERN_INFO "yaffs: sb->s_dev is NULL\n");
+ else if (!yaffs_devname(sb, devname_buf))
+ printk(KERN_INFO "yaffs: devname is NULL\n");
+ else
+ printk(KERN_INFO "yaffs: dev is %d name is \"%s\" %s\n",
+ sb->s_dev,
+ yaffs_devname(sb, devname_buf), read_only ? "ro" : "rw");
+
+ if (!data_str)
+ data_str = "";
+
+ printk(KERN_INFO "yaffs: passed flags \"%s\"\n", data_str);
+
+ memset(&options, 0, sizeof(options));
+
+ if (yaffs_parse_options(&options, data_str)) {
+ /* Option parsing failed */
+ return NULL;
+ }
+
+ sb->s_blocksize = PAGE_CACHE_SIZE;
+ sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
+
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_read_super: Using yaffs%d", yaffs_version);
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_read_super: block size %d", (int)(sb->s_blocksize));
+
+ yaffs_trace(YAFFS_TRACE_ALWAYS,
+ "yaffs: Attempting MTD mount of %u.%u,\"%s\"",
+ MAJOR(sb->s_dev), MINOR(sb->s_dev),
+ yaffs_devname(sb, devname_buf));
+
+ /* Get the device */
+ mtd = get_mtd_device(NULL, MINOR(sb->s_dev));
+ if (IS_ERR(mtd)) {
+ yaffs_trace(YAFFS_TRACE_ALWAYS,
+ "yaffs: MTD device %u either not valid or unavailable",
+ MINOR(sb->s_dev));
+ return NULL;
+ }
+
+ if (yaffs_auto_select && yaffs_version == 1 && WRITE_SIZE(mtd) >= 2048) {
+ yaffs_trace(YAFFS_TRACE_ALWAYS, "auto selecting yaffs2");
+ yaffs_version = 2;
+ }
+
+ /* Added NCB 26/5/2006 for completeness */
+ if (yaffs_version == 2 && !options.inband_tags
+ && WRITE_SIZE(mtd) == 512) {
+ yaffs_trace(YAFFS_TRACE_ALWAYS, "auto selecting yaffs1");
+ yaffs_version = 1;
+ }
+
+ if (mtd->oobavail < sizeof(struct yaffs_packed_tags2) ||
+ options.inband_tags)
+ inband_tags = 1;
+
+ if(yaffs_verify_mtd(mtd, yaffs_version, inband_tags) < 0)
+ return NULL;
+
+ /* OK, so if we got here, we have an MTD that's NAND and looks
+ * like it has the right capabilities
+ * Set the struct yaffs_dev up for mtd
+ */
+
+ if (!read_only && !(mtd->flags & MTD_WRITEABLE)) {
+ read_only = 1;
+ printk(KERN_INFO
+ "yaffs: mtd is read only, setting superblock read only\n"
+ );
+ sb->s_flags |= MS_RDONLY;
+ }
+
+ dev = kmalloc(sizeof(struct yaffs_dev), GFP_KERNEL);
+ context = kmalloc(sizeof(struct yaffs_linux_context), GFP_KERNEL);
+
+ if (!dev || !context) {
+ kfree(dev);
+ kfree(context);
+ dev = NULL;
+ context = NULL;
+
+ /* Deep shit could not allocate device structure */
+ yaffs_trace(YAFFS_TRACE_ALWAYS,
+ "yaffs_read_super: Failed trying to allocate struct yaffs_dev."
+ );
+ return NULL;
+ }
+ memset(dev, 0, sizeof(struct yaffs_dev));
+ param = &(dev->param);
+
+ memset(context, 0, sizeof(struct yaffs_linux_context));
+ dev->os_context = context;
+ INIT_LIST_HEAD(&(context->context_list));
+ context->dev = dev;
+ context->super = sb;
+
+ dev->read_only = read_only;
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
+ sb->s_fs_info = dev;
+#else
+ sb->u.generic_sbp = dev;
+#endif
+
+
+ dev->driver_context = mtd;
+ param->name = mtd->name;
+
+ /* Set up the memory size parameters.... */
+
+
+ param->n_reserved_blocks = 5;
+ param->n_caches = (options.no_cache) ? 0 : 10;
+ param->inband_tags = inband_tags;
+
+ param->enable_xattr = 1;
+ if (options.lazy_loading_overridden)
+ param->disable_lazy_load = !options.lazy_loading_enabled;
+
+ param->defered_dir_update = 1;
+
+ if (options.tags_ecc_overridden)
+ param->no_tags_ecc = !options.tags_ecc_on;
+
+ param->empty_lost_n_found = 1;
+ param->refresh_period = 500;
+ param->disable_summary = options.disable_summary;
+
+
+#ifdef CONFIG_YAFFS_DISABLE_BAD_BLOCK_MARKING
+ param->disable_bad_block_marking = 1;
+#endif
+ if (options.empty_lost_and_found_overridden)
+ param->empty_lost_n_found = options.empty_lost_and_found;
+
+ /* ... and the functions. */
+ if (yaffs_version == 2) {
+ param->is_yaffs2 = 1;
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
+ param->total_bytes_per_chunk = mtd->writesize;
+ param->chunks_per_block = mtd->erasesize / mtd->writesize;
+#else
+ param->total_bytes_per_chunk = mtd->oobblock;
+ param->chunks_per_block = mtd->erasesize / mtd->oobblock;
+#endif
+ n_blocks = YCALCBLOCKS(mtd->size, mtd->erasesize);
+
+ param->start_block = 0;
+ param->end_block = n_blocks - 1;
+ } else {
+ param->is_yaffs2 = 0;
+ n_blocks = YCALCBLOCKS(mtd->size,
+ YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK);
+
+ param->chunks_per_block = YAFFS_CHUNKS_PER_BLOCK;
+ param->total_bytes_per_chunk = YAFFS_BYTES_PER_CHUNK;
+ }
+
+ param->start_block = 0;
+ param->end_block = n_blocks - 1;
+
+ yaffs_mtd_drv_install(dev);
+
+ param->sb_dirty_fn = yaffs_set_super_dirty;
+ param->gc_control_fn = yaffs_gc_control_callback;
+
+ yaffs_dev_to_lc(dev)->super = sb;
+
+ param->use_nand_ecc = 1;
+
+ param->skip_checkpt_rd = options.skip_checkpoint_read;
+ param->skip_checkpt_wr = options.skip_checkpoint_write;
+
+ mutex_lock(&yaffs_context_lock);
+ /* Get a mount id */
+ found = 0;
+ for (mount_id = 0; !found; mount_id++) {
+ found = 1;
+ list_for_each(l, &yaffs_context_list) {
+ context_iterator =
+ list_entry(l, struct yaffs_linux_context,
+ context_list);
+ if (context_iterator->mount_id == mount_id)
+ found = 0;
+ }
+ }
+ context->mount_id = mount_id;
+
+ list_add_tail(&(yaffs_dev_to_lc(dev)->context_list),
+ &yaffs_context_list);
+ mutex_unlock(&yaffs_context_lock);
+
+ /* Directory search handling... */
+ INIT_LIST_HEAD(&(yaffs_dev_to_lc(dev)->search_contexts));
+ param->remove_obj_fn = yaffs_remove_obj_callback;
+
+ mutex_init(&(yaffs_dev_to_lc(dev)->gross_lock));
+
+ yaffs_gross_lock(dev);
+
+ err = yaffs_guts_initialise(dev);
+
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_read_super: guts initialised %s",
+ (err == YAFFS_OK) ? "OK" : "FAILED");
+
+ if (err == YAFFS_OK)
+ yaffs_bg_start(dev);
+
+ if (!context->bg_thread)
+ param->defered_dir_update = 0;
+
+ sb->s_maxbytes = yaffs_max_file_size(dev);
+
+ /* Release lock before yaffs_get_inode() */
+ yaffs_gross_unlock(dev);
+
+ /* Create root inode */
+ if (err == YAFFS_OK)
+ inode = yaffs_get_inode(sb, S_IFDIR | 0755, 0, yaffs_root(dev));
+
+ if (!inode)
+ return NULL;
+
+ inode->i_op = &yaffs_dir_inode_operations;
+ inode->i_fop = &yaffs_dir_operations;
+
+ yaffs_trace(YAFFS_TRACE_OS, "yaffs_read_super: got root inode");
+
+ root = yaffs_make_root(inode);
+
+ if (!root)
+ return NULL;
+
+ sb->s_root = root;
+ if(!dev->is_checkpointed)
+ yaffs_set_super_dirty(dev);
+
+ yaffs_trace(YAFFS_TRACE_ALWAYS,
+ "yaffs_read_super: is_checkpointed %d",
+ dev->is_checkpointed);
+
+ yaffs_trace(YAFFS_TRACE_OS, "yaffs_read_super: done");
+ return sb;
+}
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
+static int yaffs_internal_read_super_mtd(struct super_block *sb, void *data,
+ int silent)
+{
+ return yaffs_internal_read_super(1, sb, data, silent) ? 0 : -EINVAL;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
+static struct dentry *yaffs_mount(struct file_system_type *fs_type, int flags,
+ const char *dev_name, void *data)
+{
+ return mount_bdev(fs_type, flags, dev_name, data, yaffs_internal_read_super_mtd);
+}
+#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
+static int yaffs_read_super(struct file_system_type *fs,
+ int flags, const char *dev_name,
+ void *data, struct vfsmount *mnt)
+{
+
+ return get_sb_bdev(fs, flags, dev_name, data,
+ yaffs_internal_read_super_mtd, mnt);
+}
+#else
+static struct super_block *yaffs_read_super(struct file_system_type *fs,
+ int flags, const char *dev_name,
+ void *data)
+{
+
+ return get_sb_bdev(fs, flags, dev_name, data,
+ yaffs_internal_read_super_mtd);
+}
+#endif
+
+static struct file_system_type yaffs_fs_type = {
+ .owner = THIS_MODULE,
+ .name = "yaffs",
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
+ .mount = yaffs_mount,
+#else
+ .get_sb = yaffs_read_super,
+#endif
+ .kill_sb = kill_block_super,
+ .fs_flags = FS_REQUIRES_DEV,
+};
+#else
+static struct super_block *yaffs_read_super(struct super_block *sb, void *data,
+ int silent)
+{
+ return yaffs_internal_read_super(1, sb, data, silent);
+}
+
+static DECLARE_FSTYPE(yaffs_fs_type, "yaffs", yaffs_read_super,
+ FS_REQUIRES_DEV);
+#endif
+
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
+static int yaffs2_internal_read_super_mtd(struct super_block *sb, void *data,
+ int silent)
+{
+ return yaffs_internal_read_super(2, sb, data, silent) ? 0 : -EINVAL;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
+static struct dentry *yaffs2_mount(struct file_system_type *fs_type, int flags,
+ const char *dev_name, void *data)
+{
+ return mount_bdev(fs_type, flags, dev_name, data, yaffs2_internal_read_super_mtd);
+}
+#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
+static int yaffs2_read_super(struct file_system_type *fs,
+ int flags, const char *dev_name, void *data,
+ struct vfsmount *mnt)
+{
+ return get_sb_bdev(fs, flags, dev_name, data,
+ yaffs2_internal_read_super_mtd, mnt);
+}
+#else
+static struct super_block *yaffs2_read_super(struct file_system_type *fs,
+ int flags, const char *dev_name,
+ void *data)
+{
+
+ return get_sb_bdev(fs, flags, dev_name, data,
+ yaffs2_internal_read_super_mtd);
+}
+#endif
+
+static struct file_system_type yaffs2_fs_type = {
+ .owner = THIS_MODULE,
+ .name = "yaffs2",
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
+ .mount = yaffs2_mount,
+#else
+ .get_sb = yaffs2_read_super,
+#endif
+ .kill_sb = kill_block_super,
+ .fs_flags = FS_REQUIRES_DEV,
+};
+#else
+static struct super_block *yaffs2_read_super(struct super_block *sb,
+ void *data, int silent)
+{
+ return yaffs_internal_read_super(2, sb, data, silent);
+}
+
+static DECLARE_FSTYPE(yaffs2_fs_type, "yaffs2", yaffs2_read_super,
+ FS_REQUIRES_DEV);
+#endif
+
+
+static struct proc_dir_entry *my_proc_entry;
+
+static char *yaffs_dump_dev_part0(char *buf, struct yaffs_dev *dev)
+{
+ struct yaffs_param *param = &dev->param;
+ int bs[10];
+
+ yaffs_count_blocks_by_state(dev,bs);
+
+ buf += sprintf(buf, "start_block.......... %d\n", param->start_block);
+ buf += sprintf(buf, "end_block............ %d\n", param->end_block);
+ buf += sprintf(buf, "total_bytes_per_chunk %d\n",
+ param->total_bytes_per_chunk);
+ buf += sprintf(buf, "use_nand_ecc......... %d\n", param->use_nand_ecc);
+ buf += sprintf(buf, "no_tags_ecc.......... %d\n", param->no_tags_ecc);
+ buf += sprintf(buf, "is_yaffs2............ %d\n", param->is_yaffs2);
+ buf += sprintf(buf, "inband_tags.......... %d\n", param->inband_tags);
+ buf += sprintf(buf, "empty_lost_n_found... %d\n",
+ param->empty_lost_n_found);
+ buf += sprintf(buf, "disable_lazy_load.... %d\n",
+ param->disable_lazy_load);
+ buf += sprintf(buf, "disable_bad_block_mrk %d\n",
+ param->disable_bad_block_marking);
+ buf += sprintf(buf, "refresh_period....... %d\n",
+ param->refresh_period);
+ buf += sprintf(buf, "n_caches............. %d\n", param->n_caches);
+ buf += sprintf(buf, "n_reserved_blocks.... %d\n",
+ param->n_reserved_blocks);
+ buf += sprintf(buf, "always_check_erased.. %d\n",
+ param->always_check_erased);
+ buf += sprintf(buf, "\n");
+ buf += sprintf(buf, "block count by state\n");
+ buf += sprintf(buf, "0:%d 1:%d 2:%d 3:%d 4:%d\n",
+ bs[0], bs[1], bs[2], bs[3], bs[4]);
+ buf += sprintf(buf, "5:%d 6:%d 7:%d 8:%d 9:%d\n",
+ bs[5], bs[6], bs[7], bs[8], bs[9]);
+
+ return buf;
+}
+
+static char *yaffs_dump_dev_part1(char *buf, struct yaffs_dev *dev)
+{
+ buf += sprintf(buf, "max file size....... %lld\n",
+ (long long) yaffs_max_file_size(dev));
+ buf += sprintf(buf, "data_bytes_per_chunk. %d\n",
+ dev->data_bytes_per_chunk);
+ buf += sprintf(buf, "chunk_grp_bits....... %d\n", dev->chunk_grp_bits);
+ buf += sprintf(buf, "chunk_grp_size....... %d\n", dev->chunk_grp_size);
+ buf += sprintf(buf, "n_erased_blocks...... %d\n", dev->n_erased_blocks);
+ buf += sprintf(buf, "blocks_in_checkpt.... %d\n",
+ dev->blocks_in_checkpt);
+ buf += sprintf(buf, "\n");
+ buf += sprintf(buf, "n_tnodes............. %d\n", dev->n_tnodes);
+ buf += sprintf(buf, "n_obj................ %d\n", dev->n_obj);
+ buf += sprintf(buf, "n_free_chunks........ %d\n", dev->n_free_chunks);
+ buf += sprintf(buf, "\n");
+ buf += sprintf(buf, "n_page_writes........ %u\n", dev->n_page_writes);
+ buf += sprintf(buf, "n_page_reads......... %u\n", dev->n_page_reads);
+ buf += sprintf(buf, "n_erasures........... %u\n", dev->n_erasures);
+ buf += sprintf(buf, "n_gc_copies.......... %u\n", dev->n_gc_copies);
+ buf += sprintf(buf, "all_gcs.............. %u\n", dev->all_gcs);
+ buf += sprintf(buf, "passive_gc_count..... %u\n",
+ dev->passive_gc_count);
+ buf += sprintf(buf, "oldest_dirty_gc_count %u\n",
+ dev->oldest_dirty_gc_count);
+ buf += sprintf(buf, "n_gc_blocks.......... %u\n", dev->n_gc_blocks);
+ buf += sprintf(buf, "bg_gcs............... %u\n", dev->bg_gcs);
+ buf += sprintf(buf, "n_retried_writes..... %u\n",
+ dev->n_retried_writes);
+ buf += sprintf(buf, "n_retired_blocks..... %u\n",
+ dev->n_retired_blocks);
+ buf += sprintf(buf, "n_ecc_fixed.......... %u\n", dev->n_ecc_fixed);
+ buf += sprintf(buf, "n_ecc_unfixed........ %u\n", dev->n_ecc_unfixed);
+ buf += sprintf(buf, "n_tags_ecc_fixed..... %u\n",
+ dev->n_tags_ecc_fixed);
+ buf += sprintf(buf, "n_tags_ecc_unfixed... %u\n",
+ dev->n_tags_ecc_unfixed);
+ buf += sprintf(buf, "cache_hits........... %u\n", dev->cache_hits);
+ buf += sprintf(buf, "n_deleted_files...... %u\n", dev->n_deleted_files);
+ buf += sprintf(buf, "n_unlinked_files..... %u\n",
+ dev->n_unlinked_files);
+ buf += sprintf(buf, "refresh_count........ %u\n", dev->refresh_count);
+ buf += sprintf(buf, "n_bg_deletions....... %u\n", dev->n_bg_deletions);
+ buf += sprintf(buf, "tags_used............ %u\n", dev->tags_used);
+ buf += sprintf(buf, "summary_used......... %u\n", dev->summary_used);
+
+ return buf;
+}
+
+static int yaffs_proc_read(char *page,
+ char **start,
+ off_t offset, int count, int *eof, void *data)
+{
+ struct list_head *item;
+ char *buf = page;
+ int step = offset;
+ int n = 0;
+
+ /* Get proc_file_read() to step 'offset' by one on each sucessive call.
+ * We use 'offset' (*ppos) to indicate where we are in dev_list.
+ * This also assumes the user has posted a read buffer large
+ * enough to hold the complete output; but that's life in /proc.
+ */
+
+ *(int *)start = 1;
+
+ /* Print header first */
+ if (step == 0)
+ buf +=
+ sprintf(buf, "Multi-version YAFFS\n");
+ else if (step == 1)
+ buf += sprintf(buf, "\n");
+ else {
+ step -= 2;
+
+ mutex_lock(&yaffs_context_lock);
+
+ /* Locate and print the Nth entry. Order N-squared but N is small. */
+ list_for_each(item, &yaffs_context_list) {
+ struct yaffs_linux_context *dc =
+ list_entry(item, struct yaffs_linux_context,
+ context_list);
+ struct yaffs_dev *dev = dc->dev;
+
+ if (n < (step & ~1)) {
+ n += 2;
+ continue;
+ }
+ if ((step & 1) == 0) {
+ buf +=
+ sprintf(buf, "\nDevice %d \"%s\"\n", n,
+ dev->param.name);
+ buf = yaffs_dump_dev_part0(buf, dev);
+ } else {
+ buf = yaffs_dump_dev_part1(buf, dev);
+ }
+
+ break;
+ }
+ mutex_unlock(&yaffs_context_lock);
+ }
+
+ return buf - page < count ? buf - page : count;
+}
+
+/**
+ * Set the verbosity of the warnings and error messages.
+ *
+ * Note that the names can only be a..z or _ with the current code.
+ */
+
+static struct {
+ char *mask_name;
+ unsigned mask_bitfield;
+} mask_flags[] = {
+ {"allocate", YAFFS_TRACE_ALLOCATE},
+ {"always", YAFFS_TRACE_ALWAYS},
+ {"background", YAFFS_TRACE_BACKGROUND},
+ {"bad_blocks", YAFFS_TRACE_BAD_BLOCKS},
+ {"buffers", YAFFS_TRACE_BUFFERS},
+ {"bug", YAFFS_TRACE_BUG},
+ {"checkpt", YAFFS_TRACE_CHECKPOINT},
+ {"deletion", YAFFS_TRACE_DELETION},
+ {"erase", YAFFS_TRACE_ERASE},
+ {"error", YAFFS_TRACE_ERROR},
+ {"gc_detail", YAFFS_TRACE_GC_DETAIL},
+ {"gc", YAFFS_TRACE_GC},
+ {"lock", YAFFS_TRACE_LOCK},
+ {"mtd", YAFFS_TRACE_MTD},
+ {"nandaccess", YAFFS_TRACE_NANDACCESS},
+ {"os", YAFFS_TRACE_OS},
+ {"scan_debug", YAFFS_TRACE_SCAN_DEBUG},
+ {"scan", YAFFS_TRACE_SCAN},
+ {"mount", YAFFS_TRACE_MOUNT},
+ {"tracing", YAFFS_TRACE_TRACING},
+ {"sync", YAFFS_TRACE_SYNC},
+ {"write", YAFFS_TRACE_WRITE},
+ {"verify", YAFFS_TRACE_VERIFY},
+ {"verify_nand", YAFFS_TRACE_VERIFY_NAND},
+ {"verify_full", YAFFS_TRACE_VERIFY_FULL},
+ {"verify_all", YAFFS_TRACE_VERIFY_ALL},
+ {"all", 0xffffffff},
+ {"none", 0},
+ {NULL, 0},
+};
+
+#define MAX_MASK_NAME_LENGTH 40
+static int yaffs_proc_write_trace_options(struct file *file, const char *buf,
+ unsigned long count)
+{
+ unsigned rg = 0, mask_bitfield;
+ char *end;
+ char *mask_name;
+ const char *x;
+ char substring[MAX_MASK_NAME_LENGTH + 1];
+ int i;
+ int done = 0;
+ int add, len = 0;
+ int pos = 0;
+
+ rg = yaffs_trace_mask;
+
+ while (!done && (pos < count)) {
+ done = 1;
+ while ((pos < count) && isspace(buf[pos]))
+ pos++;
+
+ switch (buf[pos]) {
+ case '+':
+ case '-':
+ case '=':
+ add = buf[pos];
+ pos++;
+ break;
+
+ default:
+ add = ' ';
+ break;
+ }
+ mask_name = NULL;
+
+ mask_bitfield = simple_strtoul(buf + pos, &end, 0);
+
+ if (end > buf + pos) {
+ mask_name = "numeral";
+ len = end - (buf + pos);
+ pos += len;
+ done = 0;
+ } else {
+ for (x = buf + pos, i = 0;
+ (*x == '_' || (*x >= 'a' && *x <= 'z')) &&
+ i < MAX_MASK_NAME_LENGTH; x++, i++, pos++)
+ substring[i] = *x;
+ substring[i] = '\0';
+
+ for (i = 0; mask_flags[i].mask_name != NULL; i++) {
+ if (strcmp(substring, mask_flags[i].mask_name)
+ == 0) {
+ mask_name = mask_flags[i].mask_name;
+ mask_bitfield =
+ mask_flags[i].mask_bitfield;
+ done = 0;
+ break;
+ }
+ }
+ }
+
+ if (mask_name != NULL) {
+ done = 0;
+ switch (add) {
+ case '-':
+ rg &= ~mask_bitfield;
+ break;
+ case '+':
+ rg |= mask_bitfield;
+ break;
+ case '=':
+ rg = mask_bitfield;
+ break;
+ default:
+ rg |= mask_bitfield;
+ break;
+ }
+ }
+ }
+
+ yaffs_trace_mask = rg | YAFFS_TRACE_ALWAYS;
+
+ printk(KERN_DEBUG "new trace = 0x%08X\n", yaffs_trace_mask);
+
+ if (rg & YAFFS_TRACE_ALWAYS) {
+ for (i = 0; mask_flags[i].mask_name != NULL; i++) {
+ char flag;
+ flag = ((rg & mask_flags[i].mask_bitfield) ==
+ mask_flags[i].mask_bitfield) ? '+' : '-';
+ printk(KERN_DEBUG "%c%s\n", flag,
+ mask_flags[i].mask_name);
+ }
+ }
+
+ return count;
+}
+
+/* Debug strings are of the form:
+ * .bnnn print info on block n
+ * .cobjn,chunkn print nand chunk id for objn:chunkn
+ */
+
+static int yaffs_proc_debug_write(struct file *file, const char *buf,
+ unsigned long count)
+{
+
+ char str[100];
+ char *p0;
+ char *p1;
+ long p1_val;
+ long p0_val;
+ char cmd;
+ struct list_head *item;
+
+ memset(str, 0, sizeof(str));
+ memcpy(str, buf, min((size_t)count, sizeof(str) -1));
+
+ cmd = str[1];
+
+ p0 = str + 2;
+
+ p1 = p0;
+
+ while (*p1 && *p1 != ',') {
+ p1++;
+ }
+ *p1 = '\0';
+ p1++;
+
+ p0_val = simple_strtol(p0, NULL, 0);
+ p1_val = simple_strtol(p1, NULL, 0);
+
+
+ mutex_lock(&yaffs_context_lock);
+
+ /* Locate and print the Nth entry. Order N-squared but N is small. */
+ list_for_each(item, &yaffs_context_list) {
+ struct yaffs_linux_context *dc =
+ list_entry(item, struct yaffs_linux_context,
+ context_list);
+ struct yaffs_dev *dev = dc->dev;
+
+ if (cmd == 'b') {
+ struct yaffs_block_info *bi;
+
+ bi = yaffs_get_block_info(dev,p0_val);
+
+ if(bi) {
+ printk("Block %d: state %d, retire %d, use %d, seq %d\n",
+ (int)p0_val, bi->block_state,
+ bi->needs_retiring, bi->pages_in_use,
+ bi->seq_number);
+ }
+ } else if (cmd == 'c') {
+ struct yaffs_obj *obj;
+ int nand_chunk;
+
+ obj = yaffs_find_by_number(dev, p0_val);
+ if (!obj)
+ printk("No obj %d\n", (int)p0_val);
+ else {
+ if(p1_val == 0)
+ nand_chunk = obj->hdr_chunk;
+ else
+ nand_chunk =
+ yaffs_find_chunk_in_file(obj,
+ p1_val, NULL);
+ printk("Nand chunk for %d:%d is %d\n",
+ (int)p0_val, (int)p1_val, nand_chunk);
+ }
+ }
+ }
+
+ mutex_unlock(&yaffs_context_lock);
+
+ return count;
+}
+
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
+static int yaffs_proc_write(struct file *file, const char *buf,
+ unsigned long count, void *ppos)
+#else
+static ssize_t yaffs_proc_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+#endif
+{
+ if (buf[0] == '.')
+ return yaffs_proc_debug_write(file, buf, count);
+ return yaffs_proc_write_trace_options(file, buf, count);
+}
+
+/* Stuff to handle installation of file systems */
+struct file_system_to_install {
+ struct file_system_type *fst;
+ int installed;
+};
+
+static struct file_system_to_install fs_to_install[] = {
+ {&yaffs_fs_type, 0},
+ {&yaffs2_fs_type, 0},
+ {NULL, 0}
+};
+
+
+#ifdef YAFFS_NEW_PROCFS
+static int yaffs_proc_show(struct seq_file *m, void *v)
+{
+ /* FIXME: Unify in a better way? */
+ char buffer[512];
+ char *start;
+ int len;
+
+ len = yaffs_proc_read(buffer, &start, 0, sizeof(buffer), NULL, NULL);
+ seq_puts(m, buffer);
+ return 0;
+}
+
+static int yaffs_proc_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, yaffs_proc_show, NULL);
+}
+
+static struct file_operations procfs_ops = {
+ .owner = THIS_MODULE,
+ .open = yaffs_proc_open,
+ .read = seq_read,
+ .write = yaffs_proc_write,
+};
+
+static int yaffs_procfs_init(void)
+{
+ /* Install the proc_fs entries */
+ my_proc_entry = proc_create("yaffs",
+ S_IRUGO | S_IFREG,
+ YPROC_ROOT,
+ &procfs_ops);
+
+ if (my_proc_entry) {
+ return 0;
+ } else {
+ return -ENOMEM;
+ }
+}
+
+#else
+
+
+static int yaffs_procfs_init(void)
+{
+ /* Install the proc_fs entries */
+ my_proc_entry = create_proc_entry("yaffs",
+ S_IRUGO | S_IFREG, YPROC_ROOT);
+
+ if (my_proc_entry) {
+ my_proc_entry->write_proc = yaffs_proc_write;
+ my_proc_entry->read_proc = yaffs_proc_read;
+ my_proc_entry->data = NULL;
+ return 0;
+ } else {
+ return -ENOMEM;
+ }
+}
+
+#endif
+
+
+static int __init init_yaffs_fs(void)
+{
+ int error = 0;
+ struct file_system_to_install *fsinst;
+
+ yaffs_trace(YAFFS_TRACE_ALWAYS,
+ "yaffs Installing.");
+
+ mutex_init(&yaffs_context_lock);
+
+ error = yaffs_procfs_init();
+ if (error)
+ return error;
+
+ /* Now add the file system entries */
+
+ fsinst = fs_to_install;
+
+ while (fsinst->fst && !error) {
+ error = register_filesystem(fsinst->fst);
+ if (!error)
+ fsinst->installed = 1;
+ fsinst++;
+ }
+
+ /* Any errors? uninstall */
+ if (error) {
+ fsinst = fs_to_install;
+
+ while (fsinst->fst) {
+ if (fsinst->installed) {
+ unregister_filesystem(fsinst->fst);
+ fsinst->installed = 0;
+ }
+ fsinst++;
+ }
+ }
+
+ return error;
+}
+
+static void __exit exit_yaffs_fs(void)
+{
+
+ struct file_system_to_install *fsinst;
+
+ yaffs_trace(YAFFS_TRACE_ALWAYS,
+ "yaffs removing.");
+
+ remove_proc_entry("yaffs", YPROC_ROOT);
+
+ fsinst = fs_to_install;
+
+ while (fsinst->fst) {
+ if (fsinst->installed) {
+ unregister_filesystem(fsinst->fst);
+ fsinst->installed = 0;
+ }
+ fsinst++;
+ }
+}
+
+module_init(init_yaffs_fs)
+ module_exit(exit_yaffs_fs)
+
+ MODULE_DESCRIPTION("YAFFS2 - a NAND specific flash file system");
+MODULE_AUTHOR("Charles Manning, Aleph One Ltd., 2002-2011");
+MODULE_LICENSE("GPL");
diff -urN linux-4.9.37/fs/yaffs2/yaffs_yaffs1.c linux-4.9.y/fs/yaffs2/yaffs_yaffs1.c
--- linux-4.9.37/fs/yaffs2/yaffs_yaffs1.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/yaffs_yaffs1.c 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,424 @@
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * 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 "yaffs_yaffs1.h"
+#include "yportenv.h"
+#include "yaffs_trace.h"
+#include "yaffs_bitmap.h"
+#include "yaffs_getblockinfo.h"
+#include "yaffs_nand.h"
+#include "yaffs_attribs.h"
+
+int yaffs1_scan(struct yaffs_dev *dev)
+{
+ struct yaffs_ext_tags tags;
+ u32 blk;
+ int result;
+ int chunk;
+ u32 c;
+ int deleted;
+ enum yaffs_block_state state;
+ LIST_HEAD(hard_list);
+ struct yaffs_block_info *bi;
+ u32 seq_number;
+ struct yaffs_obj_hdr *oh;
+ struct yaffs_obj *in;
+ struct yaffs_obj *parent;
+ int alloc_failed = 0;
+ struct yaffs_shadow_fixer *shadow_fixers = NULL;
+ u8 *chunk_data;
+
+ yaffs_trace(YAFFS_TRACE_SCAN,
+ "yaffs1_scan starts intstartblk %d intendblk %d...",
+ dev->internal_start_block, dev->internal_end_block);
+
+ chunk_data = yaffs_get_temp_buffer(dev);
+
+ dev->seq_number = YAFFS_LOWEST_SEQUENCE_NUMBER;
+
+ /* Scan all the blocks to determine their state */
+ bi = dev->block_info;
+ for (blk = dev->internal_start_block; blk <= dev->internal_end_block;
+ blk++) {
+ yaffs_clear_chunk_bits(dev, blk);
+ bi->pages_in_use = 0;
+ bi->soft_del_pages = 0;
+
+ yaffs_query_init_block_state(dev, blk, &state, &seq_number);
+
+ bi->block_state = state;
+ bi->seq_number = seq_number;
+
+ if (bi->seq_number == YAFFS_SEQUENCE_BAD_BLOCK)
+ bi->block_state = state = YAFFS_BLOCK_STATE_DEAD;
+
+ yaffs_trace(YAFFS_TRACE_SCAN_DEBUG,
+ "Block scanning block %d state %d seq %d",
+ blk, state, seq_number);
+
+ if (state == YAFFS_BLOCK_STATE_DEAD) {
+ yaffs_trace(YAFFS_TRACE_BAD_BLOCKS,
+ "block %d is bad", blk);
+ } else if (state == YAFFS_BLOCK_STATE_EMPTY) {
+ yaffs_trace(YAFFS_TRACE_SCAN_DEBUG, "Block empty ");
+ dev->n_erased_blocks++;
+ dev->n_free_chunks += dev->param.chunks_per_block;
+ }
+ bi++;
+ }
+
+ /* For each block.... */
+ for (blk = dev->internal_start_block;
+ !alloc_failed && blk <= dev->internal_end_block; blk++) {
+
+ cond_resched();
+
+ bi = yaffs_get_block_info(dev, blk);
+ state = bi->block_state;
+
+ deleted = 0;
+
+ /* For each chunk in each block that needs scanning.... */
+ for (c = 0;
+ !alloc_failed && c < dev->param.chunks_per_block &&
+ state == YAFFS_BLOCK_STATE_NEEDS_SCAN; c++) {
+ /* Read the tags and decide what to do */
+ chunk = blk * dev->param.chunks_per_block + c;
+
+ result = yaffs_rd_chunk_tags_nand(dev, chunk, NULL,
+ &tags);
+
+ if (result != YAFFS_OK)
+ continue;
+ /* Let's have a good look at this chunk... */
+
+ if (tags.ecc_result == YAFFS_ECC_RESULT_UNFIXED ||
+ tags.is_deleted) {
+ /* YAFFS1 only...
+ * A deleted chunk
+ */
+ deleted++;
+ dev->n_free_chunks++;
+ } else if (!tags.chunk_used) {
+ /* An unassigned chunk in the block
+ * This means that either the block is empty or
+ * this is the one being allocated from
+ */
+
+ if (c == 0) {
+ /* We're looking at the first chunk in
+ *the block so the block is unused */
+ state = YAFFS_BLOCK_STATE_EMPTY;
+ dev->n_erased_blocks++;
+ } else {
+ /* this is the block being allocated */
+ yaffs_trace(YAFFS_TRACE_SCAN,
+ " Allocating from %d %d",
+ blk, c);
+ state = YAFFS_BLOCK_STATE_ALLOCATING;
+ dev->alloc_block = blk;
+ dev->alloc_page = c;
+ dev->alloc_block_finder = blk;
+
+ }
+
+ dev->n_free_chunks +=
+ (dev->param.chunks_per_block - c);
+ } else if (tags.chunk_id > 0) {
+ /* chunk_id > 0 so it is a data chunk... */
+ unsigned int endpos;
+
+ yaffs_set_chunk_bit(dev, blk, c);
+ bi->pages_in_use++;
+
+ in = yaffs_find_or_create_by_number(dev,
+ tags.obj_id,
+ YAFFS_OBJECT_TYPE_FILE);
+ /* PutChunkIntoFile checks for a clash
+ * (two data chunks with the same chunk_id).
+ */
+
+ if (!in)
+ alloc_failed = 1;
+
+ if (in) {
+ if (!yaffs_put_chunk_in_file
+ (in, tags.chunk_id, chunk, 1))
+ alloc_failed = 1;
+ }
+
+ endpos =
+ (tags.chunk_id - 1) *
+ dev->data_bytes_per_chunk +
+ tags.n_bytes;
+ if (in &&
+ in->variant_type ==
+ YAFFS_OBJECT_TYPE_FILE &&
+ in->variant.file_variant.stored_size <
+ endpos) {
+ in->variant.file_variant.stored_size =
+ endpos;
+ if (!dev->param.use_header_file_size) {
+ in->variant.
+ file_variant.file_size =
+ in->variant.
+ file_variant.stored_size;
+ }
+
+ }
+ } else {
+ /* chunk_id == 0, so it is an ObjectHeader.
+ * Make the object
+ */
+ yaffs_set_chunk_bit(dev, blk, c);
+ bi->pages_in_use++;
+
+ result = yaffs_rd_chunk_tags_nand(dev, chunk,
+ chunk_data,
+ NULL);
+
+ oh = (struct yaffs_obj_hdr *)chunk_data;
+
+ in = yaffs_find_by_number(dev, tags.obj_id);
+ if (in && in->variant_type != oh->type) {
+ /* This should not happen, but somehow
+ * Wev'e ended up with an obj_id that
+ * has been reused but not yet deleted,
+ * and worse still it has changed type.
+ * Delete the old object.
+ */
+
+ yaffs_del_obj(in);
+ in = NULL;
+ }
+
+ in = yaffs_find_or_create_by_number(dev,
+ tags.obj_id,
+ oh->type);
+
+ if (!in)
+ alloc_failed = 1;
+
+ if (in && oh->shadows_obj > 0) {
+
+ struct yaffs_shadow_fixer *fixer;
+ fixer =
+ kmalloc(sizeof
+ (struct yaffs_shadow_fixer),
+ GFP_NOFS);
+ if (fixer) {
+ fixer->next = shadow_fixers;
+ shadow_fixers = fixer;
+ fixer->obj_id = tags.obj_id;
+ fixer->shadowed_id =
+ oh->shadows_obj;
+ yaffs_trace(YAFFS_TRACE_SCAN,
+ " Shadow fixer: %d shadows %d",
+ fixer->obj_id,
+ fixer->shadowed_id);
+
+ }
+
+ }
+
+ if (in && in->valid) {
+ /* We have already filled this one.
+ * We have a duplicate and need to
+ * resolve it. */
+
+ unsigned existing_serial = in->serial;
+ unsigned new_serial =
+ tags.serial_number;
+
+ if (((existing_serial + 1) & 3) ==
+ new_serial) {
+ /* Use new one - destroy the
+ * exisiting one */
+ yaffs_chunk_del(dev,
+ in->hdr_chunk,
+ 1, __LINE__);
+ in->valid = 0;
+ } else {
+ /* Use existing - destroy
+ * this one. */
+ yaffs_chunk_del(dev, chunk, 1,
+ __LINE__);
+ }
+ }
+
+ if (in && !in->valid &&
+ (tags.obj_id == YAFFS_OBJECTID_ROOT ||
+ tags.obj_id ==
+ YAFFS_OBJECTID_LOSTNFOUND)) {
+ /* We only load some info, don't fiddle
+ * with directory structure */
+ in->valid = 1;
+ in->variant_type = oh->type;
+
+ in->yst_mode = oh->yst_mode;
+ yaffs_load_attribs(in, oh);
+ in->hdr_chunk = chunk;
+ in->serial = tags.serial_number;
+
+ } else if (in && !in->valid) {
+ /* we need to load this info */
+
+ in->valid = 1;
+ in->variant_type = oh->type;
+
+ in->yst_mode = oh->yst_mode;
+ yaffs_load_attribs(in, oh);
+ in->hdr_chunk = chunk;
+ in->serial = tags.serial_number;
+
+ yaffs_set_obj_name_from_oh(in, oh);
+ in->dirty = 0;
+
+ /* directory stuff...
+ * hook up to parent
+ */
+
+ parent =
+ yaffs_find_or_create_by_number
+ (dev, oh->parent_obj_id,
+ YAFFS_OBJECT_TYPE_DIRECTORY);
+ if (!parent)
+ alloc_failed = 1;
+ if (parent && parent->variant_type ==
+ YAFFS_OBJECT_TYPE_UNKNOWN) {
+ /* Set up as a directory */
+ parent->variant_type =
+ YAFFS_OBJECT_TYPE_DIRECTORY;
+ INIT_LIST_HEAD(&parent->
+ variant.dir_variant.
+ children);
+ } else if (!parent ||
+ parent->variant_type !=
+ YAFFS_OBJECT_TYPE_DIRECTORY) {
+ /* Hoosterman, a problem....
+ * We're trying to use a
+ * non-directory as a directory
+ */
+
+ yaffs_trace(YAFFS_TRACE_ERROR,
+ "yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found."
+ );
+ parent = dev->lost_n_found;
+ }
+
+ yaffs_add_obj_to_dir(parent, in);
+
+ switch (in->variant_type) {
+ case YAFFS_OBJECT_TYPE_UNKNOWN:
+ /* Todo got a problem */
+ break;
+ case YAFFS_OBJECT_TYPE_FILE:
+ if (dev->param.
+ use_header_file_size)
+ in->variant.
+ file_variant.file_size
+ = yaffs_oh_to_size(dev, oh, 0);
+ break;
+ case YAFFS_OBJECT_TYPE_HARDLINK:
+ in->variant.
+ hardlink_variant.equiv_id =
+ oh->equiv_id;
+ list_add(&in->hard_links,
+ &hard_list);
+ break;
+ case YAFFS_OBJECT_TYPE_DIRECTORY:
+ /* Do nothing */
+ break;
+ case YAFFS_OBJECT_TYPE_SPECIAL:
+ /* Do nothing */
+ break;
+ case YAFFS_OBJECT_TYPE_SYMLINK:
+ in->variant.symlink_variant.
+ alias =
+ yaffs_clone_str(oh->alias);
+ if (!in->variant.
+ symlink_variant.alias)
+ alloc_failed = 1;
+ break;
+ }
+ }
+ }
+ }
+
+ if (state == YAFFS_BLOCK_STATE_NEEDS_SCAN) {
+ /* If we got this far while scanning,
+ * then the block is fully allocated. */
+ state = YAFFS_BLOCK_STATE_FULL;
+ }
+
+ if (state == YAFFS_BLOCK_STATE_ALLOCATING) {
+ /* If the block was partially allocated then
+ * treat it as fully allocated. */
+ state = YAFFS_BLOCK_STATE_FULL;
+ dev->alloc_block = -1;
+ }
+
+ bi->block_state = state;
+
+ /* Now let's see if it was dirty */
+ if (bi->pages_in_use == 0 &&
+ !bi->has_shrink_hdr &&
+ bi->block_state == YAFFS_BLOCK_STATE_FULL)
+ yaffs_block_became_dirty(dev, blk);
+ }
+
+ /* Ok, we've done all the scanning.
+ * Fix up the hard link chains.
+ * We should now have scanned all the objects, now it's time to add
+ * these hardlinks.
+ */
+
+ yaffs_link_fixup(dev, &hard_list);
+
+ /*
+ * Fix up any shadowed objects.
+ * There should not be more than one of these.
+ */
+ {
+ struct yaffs_shadow_fixer *fixer;
+ struct yaffs_obj *obj;
+
+ while (shadow_fixers) {
+ fixer = shadow_fixers;
+ shadow_fixers = fixer->next;
+ /* Complete the rename transaction by deleting the
+ * shadowed object then setting the object header
+ to unshadowed.
+ */
+ obj = yaffs_find_by_number(dev, fixer->shadowed_id);
+ if (obj)
+ yaffs_del_obj(obj);
+
+ obj = yaffs_find_by_number(dev, fixer->obj_id);
+
+ if (obj)
+ yaffs_update_oh(obj, NULL, 1, 0, 0, NULL);
+
+ kfree(fixer);
+ }
+ }
+
+ yaffs_release_temp_buffer(dev, chunk_data);
+
+ if (alloc_failed)
+ return YAFFS_FAIL;
+
+ yaffs_trace(YAFFS_TRACE_SCAN, "yaffs1_scan ends");
+
+ return YAFFS_OK;
+}
diff -urN linux-4.9.37/fs/yaffs2/yaffs_yaffs1.h linux-4.9.y/fs/yaffs2/yaffs_yaffs1.h
--- linux-4.9.37/fs/yaffs2/yaffs_yaffs1.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/yaffs_yaffs1.h 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,22 @@
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+#ifndef __YAFFS_YAFFS1_H__
+#define __YAFFS_YAFFS1_H__
+
+#include "yaffs_guts.h"
+int yaffs1_scan(struct yaffs_dev *dev);
+
+#endif
diff -urN linux-4.9.37/fs/yaffs2/yaffs_yaffs2.c linux-4.9.y/fs/yaffs2/yaffs_yaffs2.c
--- linux-4.9.37/fs/yaffs2/yaffs_yaffs2.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/yaffs_yaffs2.c 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,1712 @@
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * 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 "yaffs_guts.h"
+#include "yaffs_trace.h"
+#include "yaffs_yaffs2.h"
+#include "yaffs_checkptrw.h"
+#include "yaffs_bitmap.h"
+#include "yaffs_nand.h"
+#include "yaffs_getblockinfo.h"
+#include "yaffs_verify.h"
+#include "yaffs_attribs.h"
+#include "yaffs_summary.h"
+#include "yaffs_endian.h"
+
+/*
+ * Checkpoints are really no benefit on very small partitions.
+ *
+ * To save space on small partitions don't bother with checkpoints unless
+ * the partition is at least this big.
+ */
+#define YAFFS_CHECKPOINT_MIN_BLOCKS 60
+#define YAFFS_SMALL_HOLE_THRESHOLD 4
+
+/*
+ * Oldest Dirty Sequence Number handling.
+ */
+
+/* yaffs_calc_oldest_dirty_seq()
+ * yaffs2_find_oldest_dirty_seq()
+ * Calculate the oldest dirty sequence number if we don't know it.
+ */
+void yaffs_calc_oldest_dirty_seq(struct yaffs_dev *dev)
+{
+ u32 i;
+ unsigned seq;
+ unsigned block_no = 0;
+ struct yaffs_block_info *b;
+
+ if (!dev->param.is_yaffs2)
+ return;
+
+ /* Find the oldest dirty sequence number. */
+ seq = dev->seq_number + 1;
+ b = dev->block_info;
+ for (i = dev->internal_start_block; i <= dev->internal_end_block; i++) {
+ if (b->block_state == YAFFS_BLOCK_STATE_FULL &&
+ (u32)(b->pages_in_use - b->soft_del_pages) <
+ dev->param.chunks_per_block &&
+ b->seq_number < seq) {
+ seq = b->seq_number;
+ block_no = i;
+ }
+ b++;
+ }
+
+ if (block_no) {
+ dev->oldest_dirty_seq = seq;
+ dev->oldest_dirty_block = block_no;
+ }
+}
+
+void yaffs2_find_oldest_dirty_seq(struct yaffs_dev *dev)
+{
+ if (!dev->param.is_yaffs2)
+ return;
+
+ if (!dev->oldest_dirty_seq)
+ yaffs_calc_oldest_dirty_seq(dev);
+}
+
+/*
+ * yaffs_clear_oldest_dirty_seq()
+ * Called when a block is erased or marked bad. (ie. when its seq_number
+ * becomes invalid). If the value matches the oldest then we clear
+ * dev->oldest_dirty_seq to force its recomputation.
+ */
+void yaffs2_clear_oldest_dirty_seq(struct yaffs_dev *dev,
+ struct yaffs_block_info *bi)
+{
+
+ if (!dev->param.is_yaffs2)
+ return;
+
+ if (!bi || bi->seq_number == dev->oldest_dirty_seq) {
+ dev->oldest_dirty_seq = 0;
+ dev->oldest_dirty_block = 0;
+ }
+}
+
+/*
+ * yaffs2_update_oldest_dirty_seq()
+ * Update the oldest dirty sequence number whenever we dirty a block.
+ * Only do this if the oldest_dirty_seq is actually being tracked.
+ */
+void yaffs2_update_oldest_dirty_seq(struct yaffs_dev *dev, unsigned block_no,
+ struct yaffs_block_info *bi)
+{
+ if (!dev->param.is_yaffs2)
+ return;
+
+ if (dev->oldest_dirty_seq) {
+ if (dev->oldest_dirty_seq > bi->seq_number) {
+ dev->oldest_dirty_seq = bi->seq_number;
+ dev->oldest_dirty_block = block_no;
+ }
+ }
+}
+
+int yaffs_block_ok_for_gc(struct yaffs_dev *dev, struct yaffs_block_info *bi)
+{
+
+ if (!dev->param.is_yaffs2)
+ return 1; /* disqualification only applies to yaffs2. */
+
+ if (!bi->has_shrink_hdr)
+ return 1; /* can gc */
+
+ yaffs2_find_oldest_dirty_seq(dev);
+
+ /* Can't do gc of this block if there are any blocks older than this
+ * one that have discarded pages.
+ */
+ return (bi->seq_number <= dev->oldest_dirty_seq);
+}
+
+/*
+ * yaffs2_find_refresh_block()
+ * periodically finds the oldest full block by sequence number for refreshing.
+ * Only for yaffs2.
+ */
+u32 yaffs2_find_refresh_block(struct yaffs_dev *dev)
+{
+ u32 b;
+ u32 oldest = 0;
+ u32 oldest_seq = 0;
+ struct yaffs_block_info *bi;
+
+ if (!dev->param.is_yaffs2)
+ return oldest;
+
+ /*
+ * If refresh period < 10 then refreshing is disabled.
+ */
+ if (dev->param.refresh_period < 10)
+ return oldest;
+
+ /*
+ * Fix broken values.
+ */
+ if (dev->refresh_skip > dev->param.refresh_period)
+ dev->refresh_skip = dev->param.refresh_period;
+
+ if (dev->refresh_skip > 0)
+ return oldest;
+
+ /*
+ * Refresh skip is now zero.
+ * We'll do a refresh this time around....
+ * Update the refresh skip and find the oldest block.
+ */
+ dev->refresh_skip = dev->param.refresh_period;
+ dev->refresh_count++;
+ bi = dev->block_info;
+ for (b = dev->internal_start_block; b <= dev->internal_end_block; b++) {
+
+ if (bi->block_state == YAFFS_BLOCK_STATE_FULL) {
+
+ if (oldest < 1 || bi->seq_number < oldest_seq) {
+ oldest = b;
+ oldest_seq = bi->seq_number;
+ }
+ }
+ bi++;
+ }
+
+ if (oldest > 0) {
+ yaffs_trace(YAFFS_TRACE_GC,
+ "GC refresh count %d selected block %d with seq_number %d",
+ dev->refresh_count, oldest, oldest_seq);
+ }
+
+ return oldest;
+}
+
+int yaffs2_checkpt_required(struct yaffs_dev *dev)
+{
+ int nblocks;
+
+ if (!dev->param.is_yaffs2)
+ return 0;
+
+ nblocks = dev->internal_end_block - dev->internal_start_block + 1;
+
+ return !dev->param.skip_checkpt_wr &&
+ !dev->read_only && (nblocks >= YAFFS_CHECKPOINT_MIN_BLOCKS);
+}
+
+int yaffs_calc_checkpt_blocks_required(struct yaffs_dev *dev)
+{
+ int retval;
+ int n_bytes = 0;
+ int n_blocks;
+ int dev_blocks;
+
+ if (!dev->param.is_yaffs2)
+ return 0;
+
+ if (!dev->checkpoint_blocks_required && yaffs2_checkpt_required(dev)) {
+ /* Not a valid value so recalculate */
+ dev_blocks = dev->param.end_block - dev->param.start_block + 1;
+ n_bytes += sizeof(struct yaffs_checkpt_validity);
+ n_bytes += sizeof(struct yaffs_checkpt_dev);
+ n_bytes += dev_blocks * sizeof(struct yaffs_block_info);
+ n_bytes += dev_blocks * dev->chunk_bit_stride;
+ n_bytes +=
+ (sizeof(struct yaffs_checkpt_obj) + sizeof(u32)) *
+ dev->n_obj;
+ n_bytes += (dev->tnode_size + sizeof(u32)) * dev->n_tnodes;
+ n_bytes += sizeof(struct yaffs_checkpt_validity);
+ n_bytes += sizeof(u32); /* checksum */
+
+ /* Round up and add 2 blocks to allow for some bad blocks,
+ * so add 3 */
+
+ n_blocks =
+ (n_bytes /
+ (dev->data_bytes_per_chunk *
+ dev->param.chunks_per_block)) + 3;
+
+ dev->checkpoint_blocks_required = n_blocks;
+ }
+
+ retval = dev->checkpoint_blocks_required - dev->blocks_in_checkpt;
+ if (retval < 0)
+ retval = 0;
+ return retval;
+}
+
+/*--------------------- Checkpointing --------------------*/
+
+static void yaffs2_do_endian_validity_marker(struct yaffs_dev *dev,
+ struct yaffs_checkpt_validity *v)
+{
+
+ if (!dev->swap_endian)
+ return;
+ v->struct_type = swap_s32(v->struct_type);
+ v->magic = swap_u32(v->magic);
+ v->version = swap_u32(v->version);
+ v->head = swap_u32(v->head);
+}
+
+static int yaffs2_wr_checkpt_validity_marker(struct yaffs_dev *dev, int head)
+{
+ struct yaffs_checkpt_validity cp;
+
+ memset(&cp, 0, sizeof(cp));
+
+ cp.struct_type = sizeof(cp);
+ cp.magic = YAFFS_MAGIC;
+ cp.version = YAFFS_CHECKPOINT_VERSION;
+ cp.head = (head) ? 1 : 0;
+
+ yaffs2_do_endian_validity_marker(dev, &cp);
+
+ return (yaffs2_checkpt_wr(dev, &cp, sizeof(cp)) == sizeof(cp)) ? 1 : 0;
+}
+
+static int yaffs2_rd_checkpt_validity_marker(struct yaffs_dev *dev, int head)
+{
+ struct yaffs_checkpt_validity cp;
+ int ok;
+
+ ok = (yaffs2_checkpt_rd(dev, &cp, sizeof(cp)) == sizeof(cp));
+ yaffs2_do_endian_validity_marker(dev, &cp);
+
+ if (ok)
+ ok = (cp.struct_type == sizeof(cp)) &&
+ (cp.magic == YAFFS_MAGIC) &&
+ (cp.version == YAFFS_CHECKPOINT_VERSION) &&
+ (cp.head == ((head) ? 1 : 0));
+ return ok ? 1 : 0;
+}
+
+static void yaffs2_dev_to_checkpt_dev(struct yaffs_checkpt_dev *cp,
+ struct yaffs_dev *dev)
+{
+ cp->struct_type = sizeof(*cp);
+
+ cp->n_erased_blocks = dev->n_erased_blocks;
+ cp->alloc_block = dev->alloc_block;
+ cp->alloc_page = dev->alloc_page;
+ cp->n_free_chunks = dev->n_free_chunks;
+
+ cp->n_deleted_files = dev->n_deleted_files;
+ cp->n_unlinked_files = dev->n_unlinked_files;
+ cp->n_bg_deletions = dev->n_bg_deletions;
+ cp->seq_number = dev->seq_number;
+
+}
+
+static void yaffs_checkpt_dev_to_dev(struct yaffs_dev *dev,
+ struct yaffs_checkpt_dev *cp)
+{
+ dev->n_erased_blocks = cp->n_erased_blocks;
+ dev->alloc_block = cp->alloc_block;
+ dev->alloc_page = cp->alloc_page;
+ dev->n_free_chunks = cp->n_free_chunks;
+
+ dev->n_deleted_files = cp->n_deleted_files;
+ dev->n_unlinked_files = cp->n_unlinked_files;
+ dev->n_bg_deletions = cp->n_bg_deletions;
+ dev->seq_number = cp->seq_number;
+}
+
+static void yaffs2_do_endian_checkpt_dev(struct yaffs_dev *dev,
+ struct yaffs_checkpt_dev *cp)
+{
+ if (!dev->swap_endian)
+ return;
+ cp->struct_type = swap_s32(cp->struct_type);
+ cp->n_erased_blocks = swap_s32(cp->n_erased_blocks);
+ cp->alloc_block = swap_s32(cp->alloc_block);
+ cp->alloc_page = swap_u32(cp->alloc_page);
+ cp->n_free_chunks = swap_s32(cp->n_free_chunks);
+ cp->n_deleted_files = swap_s32(cp->n_deleted_files);
+ cp->n_unlinked_files = swap_s32(cp->n_unlinked_files);
+ cp->n_bg_deletions = swap_s32(cp->n_bg_deletions);
+}
+
+static int yaffs2_wr_checkpt_dev(struct yaffs_dev *dev)
+{
+ struct yaffs_checkpt_dev cp;
+ u32 n_bytes;
+ u32 n_blocks = dev->internal_end_block - dev->internal_start_block + 1;
+ int ok;
+ u32 i;
+ union yaffs_block_info_union bu;
+
+ /* Write device runtime values */
+ yaffs2_dev_to_checkpt_dev(&cp, dev);
+ yaffs2_do_endian_checkpt_dev(dev, &cp);
+
+ ok = (yaffs2_checkpt_wr(dev, &cp, sizeof(cp)) == sizeof(cp));
+ if (!ok)
+ return 0;
+
+ /* Write block info. */
+ if (!dev->swap_endian) {
+ n_bytes = n_blocks * sizeof(struct yaffs_block_info);
+ ok = (yaffs2_checkpt_wr(dev, dev->block_info, n_bytes) ==
+ (int)n_bytes);
+ } else {
+ /*
+ * Need to swap the endianisms. We can't do this in place
+ * since that would damage live data,
+ * so write one block info at a time using a copy.
+ */
+ for (i = 0; i < n_blocks && ok; i++) {
+ bu.bi = dev->block_info[i];
+ bu.as_u32[0] = swap_u32(bu.as_u32[0]);
+ bu.as_u32[1] = swap_u32(bu.as_u32[1]);
+ ok = (yaffs2_checkpt_wr(dev, &bu, sizeof(bu)) == sizeof(bu));
+ }
+ }
+
+ if (!ok)
+ return 0;
+
+ /*
+ * Write chunk bits. Chunk bits are in bytes so
+ * no endian conversion is needed.
+ */
+ n_bytes = n_blocks * dev->chunk_bit_stride;
+ ok = (yaffs2_checkpt_wr(dev, dev->chunk_bits, n_bytes) ==
+ (int)n_bytes);
+
+ return ok ? 1 : 0;
+}
+
+static int yaffs2_rd_checkpt_dev(struct yaffs_dev *dev)
+{
+ struct yaffs_checkpt_dev cp;
+ u32 n_bytes;
+ u32 n_blocks =
+ (dev->internal_end_block - dev->internal_start_block + 1);
+ int ok;
+
+ ok = (yaffs2_checkpt_rd(dev, &cp, sizeof(cp)) == sizeof(cp));
+ if (!ok)
+ return 0;
+ yaffs2_do_endian_checkpt_dev(dev, &cp);
+
+ if (cp.struct_type != sizeof(cp))
+ return 0;
+
+ yaffs_checkpt_dev_to_dev(dev, &cp);
+
+ n_bytes = n_blocks * sizeof(struct yaffs_block_info);
+
+ ok = (yaffs2_checkpt_rd(dev, dev->block_info, n_bytes) ==
+ (int)n_bytes);
+
+ if (!ok)
+ return 0;
+
+ if (dev->swap_endian) {
+ /* The block info can just be handled as a list of u32s. */
+ u32 *as_u32 = (u32 *) dev->block_info;
+ u32 n_u32s = n_bytes/sizeof(u32);
+ u32 i;
+
+ for (i=0; i < n_u32s; i++)
+ as_u32[i] = swap_u32(as_u32[i]);
+ }
+
+ n_bytes = n_blocks * dev->chunk_bit_stride;
+
+ ok = (yaffs2_checkpt_rd(dev, dev->chunk_bits, n_bytes) ==
+ (int)n_bytes);
+
+
+ return ok ? 1 : 0;
+}
+
+
+static void yaffs2_checkpt_obj_bit_assign(struct yaffs_checkpt_obj *cp,
+ int bit_offset,
+ int bit_width,
+ u32 value)
+{
+ u32 and_mask;
+
+ and_mask = ((1<<bit_width)-1) << bit_offset;
+
+ cp->bit_field &= ~and_mask;
+ cp->bit_field |= ((value << bit_offset) & and_mask);
+}
+
+static u32 yaffs2_checkpt_obj_bit_get(struct yaffs_checkpt_obj *cp,
+ int bit_offset,
+ int bit_width)
+{
+ u32 and_mask;
+
+ and_mask = ((1<<bit_width)-1);
+
+ return (cp->bit_field >> bit_offset) & and_mask;
+}
+
+static void yaffs2_obj_checkpt_obj(struct yaffs_checkpt_obj *cp,
+ struct yaffs_obj *obj)
+{
+ cp->obj_id = obj->obj_id;
+ cp->parent_id = (obj->parent) ? obj->parent->obj_id : 0;
+ cp->hdr_chunk = obj->hdr_chunk;
+
+ yaffs2_checkpt_obj_bit_assign(cp, CHECKPOINT_VARIANT_BITS, obj->variant_type);
+ yaffs2_checkpt_obj_bit_assign(cp, CHECKPOINT_DELETED_BITS, obj->deleted);
+ yaffs2_checkpt_obj_bit_assign(cp, CHECKPOINT_SOFT_DEL_BITS, obj->soft_del);
+ yaffs2_checkpt_obj_bit_assign(cp, CHECKPOINT_UNLINKED_BITS, obj->unlinked);
+ yaffs2_checkpt_obj_bit_assign(cp, CHECKPOINT_FAKE_BITS, obj->fake);
+ yaffs2_checkpt_obj_bit_assign(cp, CHECKPOINT_RENAME_ALLOWED_BITS, obj->rename_allowed);
+ yaffs2_checkpt_obj_bit_assign(cp, CHECKPOINT_UNLINK_ALLOWED_BITS, obj->unlink_allowed);
+ yaffs2_checkpt_obj_bit_assign(cp, CHECKPOINT_SERIAL_BITS, obj->serial);
+
+ cp->n_data_chunks = obj->n_data_chunks;
+
+ if (obj->variant_type == YAFFS_OBJECT_TYPE_FILE)
+ cp->size_or_equiv_obj = obj->variant.file_variant.file_size;
+ else if (obj->variant_type == YAFFS_OBJECT_TYPE_HARDLINK)
+ cp->size_or_equiv_obj = obj->variant.hardlink_variant.equiv_id;
+}
+
+static int yaffs2_checkpt_obj_to_obj(struct yaffs_obj *obj,
+ struct yaffs_checkpt_obj *cp)
+{
+ struct yaffs_obj *parent;
+ u32 cp_variant_type = yaffs2_checkpt_obj_bit_get(cp, CHECKPOINT_VARIANT_BITS);
+
+ if (obj->variant_type != cp_variant_type) {
+ yaffs_trace(YAFFS_TRACE_ERROR,
+ "Checkpoint read object %d type %d chunk %d does not match existing object type %d",
+ cp->obj_id, cp_variant_type, cp->hdr_chunk,
+ obj->variant_type);
+ return 0;
+ }
+
+ obj->obj_id = cp->obj_id;
+
+ if (cp->parent_id)
+ parent = yaffs_find_or_create_by_number(obj->my_dev,
+ cp->parent_id,
+ YAFFS_OBJECT_TYPE_DIRECTORY);
+ else
+ parent = NULL;
+
+ if (parent) {
+ if (parent->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) {
+ yaffs_trace(YAFFS_TRACE_ALWAYS,
+ "Checkpoint read object %d parent %d type %d chunk %d Parent type, %d, not directory",
+ cp->obj_id, cp->parent_id,
+ cp_variant_type, cp->hdr_chunk,
+ parent->variant_type);
+ return 0;
+ }
+ yaffs_add_obj_to_dir(parent, obj);
+ }
+
+ obj->hdr_chunk = cp->hdr_chunk;
+
+ obj->variant_type = yaffs2_checkpt_obj_bit_get(cp, CHECKPOINT_VARIANT_BITS);
+ obj->deleted = yaffs2_checkpt_obj_bit_get(cp, CHECKPOINT_DELETED_BITS);
+ obj->soft_del = yaffs2_checkpt_obj_bit_get(cp, CHECKPOINT_SOFT_DEL_BITS);
+ obj->unlinked = yaffs2_checkpt_obj_bit_get(cp, CHECKPOINT_UNLINKED_BITS);
+ obj->fake = yaffs2_checkpt_obj_bit_get(cp, CHECKPOINT_FAKE_BITS);
+ obj->rename_allowed = yaffs2_checkpt_obj_bit_get(cp, CHECKPOINT_RENAME_ALLOWED_BITS);
+ obj->unlink_allowed = yaffs2_checkpt_obj_bit_get(cp, CHECKPOINT_UNLINK_ALLOWED_BITS);
+ obj->serial = yaffs2_checkpt_obj_bit_get(cp, CHECKPOINT_SERIAL_BITS);
+
+ obj->n_data_chunks = cp->n_data_chunks;
+
+ if (obj->variant_type == YAFFS_OBJECT_TYPE_FILE) {
+ obj->variant.file_variant.file_size = cp->size_or_equiv_obj;
+ obj->variant.file_variant.stored_size = cp->size_or_equiv_obj;
+ } else if (obj->variant_type == YAFFS_OBJECT_TYPE_HARDLINK) {
+ obj->variant.hardlink_variant.equiv_id = cp->size_or_equiv_obj;
+ }
+ if (obj->hdr_chunk > 0)
+ obj->lazy_loaded = 1;
+ return 1;
+}
+
+static void yaffs2_do_endian_tnode(struct yaffs_dev *dev, struct yaffs_tnode *tn)
+{
+ int i;
+ u32 *as_u32 = (u32 *)tn;
+ int tnode_size_u32 = dev->tnode_size / sizeof(u32);
+
+ if (!dev->swap_endian)
+ return;
+ /* Swap all the tnode data as u32s to fix endianisms. */
+ for (i = 0; i<tnode_size_u32; i++)
+ as_u32[i] = swap_u32(as_u32[i]);
+}
+
+struct yaffs_tnode *yaffs2_do_endian_tnode_copy(struct yaffs_dev *dev,
+ struct yaffs_tnode *tn)
+{
+ if (!dev->swap_endian)
+ return tn;
+
+ memcpy(dev->tn_swap_buffer, tn, dev->tnode_size);
+ tn = dev->tn_swap_buffer;
+
+ yaffs2_do_endian_tnode(dev, tn);
+
+ return tn;
+}
+
+static int yaffs2_checkpt_tnode_worker(struct yaffs_obj *in,
+ struct yaffs_tnode *tn, u32 level,
+ int chunk_offset)
+{
+ int i;
+ struct yaffs_dev *dev = in->my_dev;
+ int ok = 1;
+ u32 base_offset;
+
+ if (!tn)
+ return 1;
+
+ if (level > 0) {
+ for (i = 0; i < YAFFS_NTNODES_INTERNAL && ok; i++) {
+ if (!tn->internal[i])
+ continue;
+ ok = yaffs2_checkpt_tnode_worker(in,
+ tn->internal[i],
+ level - 1,
+ (chunk_offset <<
+ YAFFS_TNODES_INTERNAL_BITS) + i);
+ }
+ return ok;
+ }
+
+ /* Level 0 tnode */
+ base_offset = chunk_offset << YAFFS_TNODES_LEVEL0_BITS;
+ yaffs_do_endian_u32(dev, &base_offset);
+
+ ok = (yaffs2_checkpt_wr(dev, &base_offset, sizeof(base_offset)) ==
+ sizeof(base_offset));
+ if (ok) {
+ /*
+ * NB Can't do an in-place endian swizzle since that would
+ * damage current tnode data.
+ * If a tnode endian conversion is required we do a copy.
+ */
+ tn = yaffs2_do_endian_tnode_copy(dev, tn);
+ ok = (yaffs2_checkpt_wr(dev, tn, dev->tnode_size) ==
+ (int)dev->tnode_size);
+ }
+ return ok;
+}
+
+static int yaffs2_wr_checkpt_tnodes(struct yaffs_obj *obj)
+{
+ u32 end_marker = ~0;
+ int ok = 1;
+
+ if (obj->variant_type != YAFFS_OBJECT_TYPE_FILE)
+ return ok;
+
+ ok = yaffs2_checkpt_tnode_worker(obj,
+ obj->variant.file_variant.top,
+ obj->variant.file_variant.
+ top_level, 0);
+ if (ok)
+ ok = (yaffs2_checkpt_wr(obj->my_dev, &end_marker,
+ sizeof(end_marker)) == sizeof(end_marker));
+
+ return ok ? 1 : 0;
+}
+
+static int yaffs2_rd_checkpt_tnodes(struct yaffs_obj *obj)
+{
+ u32 base_chunk;
+ int ok = 1;
+ struct yaffs_dev *dev = obj->my_dev;
+ struct yaffs_file_var *file_stuct_ptr = &obj->variant.file_variant;
+ struct yaffs_tnode *tn;
+ int nread = 0;
+
+ ok = (yaffs2_checkpt_rd(dev, &base_chunk, sizeof(base_chunk)) ==
+ sizeof(base_chunk));
+
+ yaffs_do_endian_u32(dev, &base_chunk);
+
+ while (ok && (~base_chunk)) {
+ nread++;
+ /* Read level 0 tnode */
+
+ tn = yaffs_get_tnode(dev);
+ if (tn) {
+ ok = (yaffs2_checkpt_rd(dev, tn, dev->tnode_size) ==
+ (int)dev->tnode_size);
+ yaffs2_do_endian_tnode(dev, tn);
+ }
+ else
+ ok = 0;
+
+ if (tn && ok)
+ ok = yaffs_add_find_tnode_0(dev,
+ file_stuct_ptr,
+ base_chunk, tn) ? 1 : 0;
+
+ if (ok) {
+ ok = (yaffs2_checkpt_rd
+ (dev, &base_chunk,
+ sizeof(base_chunk)) == sizeof(base_chunk));
+ yaffs_do_endian_u32(dev, &base_chunk);
+ }
+
+ }
+
+ yaffs_trace(YAFFS_TRACE_CHECKPOINT,
+ "Checkpoint read tnodes %d records, last %d. ok %d",
+ nread, base_chunk, ok);
+
+ return ok ? 1 : 0;
+}
+
+
+static void yaffs2_do_endian_checkpt_obj(struct yaffs_dev *dev,
+ struct yaffs_checkpt_obj *cp)
+{
+ if (!dev->swap_endian)
+ return;
+ cp->struct_type = swap_s32(cp->struct_type);
+ cp->obj_id = swap_u32(cp->obj_id);
+ cp->parent_id = swap_u32(cp->parent_id);
+ cp->hdr_chunk = swap_s32(cp->hdr_chunk);
+ cp->bit_field = swap_u32(cp->bit_field);
+ cp->n_data_chunks = swap_s32(cp->n_data_chunks);
+ cp->size_or_equiv_obj = swap_loff_t(cp->size_or_equiv_obj);
+}
+
+static int yaffs2_wr_checkpt_objs(struct yaffs_dev *dev)
+{
+ struct yaffs_obj *obj;
+ struct yaffs_checkpt_obj cp;
+ int i;
+ int ok = 1;
+ struct list_head *lh;
+ u32 cp_variant_type;
+
+ /* Iterate through the objects in each hash entry,
+ * dumping them to the checkpointing stream.
+ */
+
+ for (i = 0; ok && i < YAFFS_NOBJECT_BUCKETS; i++) {
+ list_for_each(lh, &dev->obj_bucket[i].list) {
+ obj = list_entry(lh, struct yaffs_obj, hash_link);
+ if (!obj->defered_free) {
+ yaffs2_obj_checkpt_obj(&cp, obj);
+ cp.struct_type = sizeof(cp);
+ cp_variant_type = yaffs2_checkpt_obj_bit_get(
+ &cp, CHECKPOINT_VARIANT_BITS);
+ yaffs_trace(YAFFS_TRACE_CHECKPOINT,
+ "Checkpoint write object %d parent %d type %d chunk %d obj addr %p",
+ cp.obj_id, cp.parent_id,
+ cp_variant_type, cp.hdr_chunk, obj);
+
+ yaffs2_do_endian_checkpt_obj (dev, &cp);
+ ok = (yaffs2_checkpt_wr(dev, &cp,
+ sizeof(cp)) == sizeof(cp));
+
+ if (ok &&
+ obj->variant_type ==
+ YAFFS_OBJECT_TYPE_FILE)
+ ok = yaffs2_wr_checkpt_tnodes(obj);
+ }
+ }
+ }
+
+ /* Dump end of list */
+ memset(&cp, 0xff, sizeof(struct yaffs_checkpt_obj));
+ cp.struct_type = sizeof(cp);
+ yaffs2_do_endian_checkpt_obj (dev, &cp);
+
+ if (ok)
+ ok = (yaffs2_checkpt_wr(dev, &cp, sizeof(cp)) == sizeof(cp));
+
+ return ok ? 1 : 0;
+}
+
+static int yaffs2_rd_checkpt_objs(struct yaffs_dev *dev)
+{
+ struct yaffs_obj *obj;
+ struct yaffs_checkpt_obj cp;
+ int ok = 1;
+ int done = 0;
+ u32 cp_variant_type;
+ LIST_HEAD(hard_list);
+
+
+ while (ok && !done) {
+ ok = (yaffs2_checkpt_rd(dev, &cp, sizeof(cp)) == sizeof(cp));
+ yaffs2_do_endian_checkpt_obj (dev, &cp);
+
+ if (cp.struct_type != sizeof(cp)) {
+ yaffs_trace(YAFFS_TRACE_CHECKPOINT,
+ "struct size %d instead of %d ok %d",
+ cp.struct_type, (int)sizeof(cp), ok);
+ ok = 0;
+ }
+
+ cp_variant_type = yaffs2_checkpt_obj_bit_get(
+ &cp, CHECKPOINT_VARIANT_BITS);
+ yaffs_trace(YAFFS_TRACE_CHECKPOINT,
+ "Checkpoint read object %d parent %d type %d chunk %d ",
+ cp.obj_id, cp.parent_id, cp_variant_type,
+ cp.hdr_chunk);
+
+ if (ok && cp.obj_id == (u32)(~0)) {
+ done = 1;
+ } else if (ok) {
+ obj =
+ yaffs_find_or_create_by_number(dev, cp.obj_id,
+ cp_variant_type);
+ if (obj) {
+ ok = yaffs2_checkpt_obj_to_obj(obj, &cp);
+ if (!ok)
+ break;
+ if (obj->variant_type ==
+ YAFFS_OBJECT_TYPE_FILE) {
+ ok = yaffs2_rd_checkpt_tnodes(obj);
+ } else if (obj->variant_type ==
+ YAFFS_OBJECT_TYPE_HARDLINK) {
+ list_add(&obj->hard_links, &hard_list);
+ }
+ } else {
+ ok = 0;
+ }
+ }
+ }
+
+ if (ok)
+ yaffs_link_fixup(dev, &hard_list);
+
+ return ok ? 1 : 0;
+}
+
+static int yaffs2_wr_checkpt_sum(struct yaffs_dev *dev)
+{
+ u32 checkpt_sum;
+ int ok;
+
+ yaffs2_get_checkpt_sum(dev, &checkpt_sum);
+
+ yaffs_do_endian_u32(dev, &checkpt_sum);
+
+ ok = (yaffs2_checkpt_wr(dev, &checkpt_sum, sizeof(checkpt_sum)) ==
+ sizeof(checkpt_sum));
+
+ if (!ok)
+ return 0;
+
+ return 1;
+}
+
+static int yaffs2_rd_checkpt_sum(struct yaffs_dev *dev)
+{
+ u32 checkpt_sum0;
+ u32 checkpt_sum1;
+ int ok;
+
+ yaffs2_get_checkpt_sum(dev, &checkpt_sum0);
+
+ ok = (yaffs2_checkpt_rd(dev, &checkpt_sum1, sizeof(checkpt_sum1)) ==
+ sizeof(checkpt_sum1));
+
+ if (!ok)
+ return 0;
+ yaffs_do_endian_u32(dev, &checkpt_sum1);
+
+ if (checkpt_sum0 != checkpt_sum1)
+ return 0;
+
+ return 1;
+}
+
+static int yaffs2_wr_checkpt_data(struct yaffs_dev *dev)
+{
+ int ok = 1;
+
+ if (!yaffs2_checkpt_required(dev)) {
+ yaffs_trace(YAFFS_TRACE_CHECKPOINT,
+ "skipping checkpoint write");
+ ok = 0;
+ }
+
+ if (ok)
+ ok = yaffs2_checkpt_open(dev, 1);
+
+ if (ok) {
+ yaffs_trace(YAFFS_TRACE_CHECKPOINT,
+ "write checkpoint validity");
+ ok = yaffs2_wr_checkpt_validity_marker(dev, 1);
+ }
+ if (ok) {
+ yaffs_trace(YAFFS_TRACE_CHECKPOINT,
+ "write checkpoint device");
+ ok = yaffs2_wr_checkpt_dev(dev);
+ }
+ if (ok) {
+ yaffs_trace(YAFFS_TRACE_CHECKPOINT,
+ "write checkpoint objects");
+ ok = yaffs2_wr_checkpt_objs(dev);
+ }
+ if (ok) {
+ yaffs_trace(YAFFS_TRACE_CHECKPOINT,
+ "write checkpoint validity");
+ ok = yaffs2_wr_checkpt_validity_marker(dev, 0);
+ }
+
+ if (ok)
+ ok = yaffs2_wr_checkpt_sum(dev);
+
+ if (!yaffs_checkpt_close(dev))
+ ok = 0;
+
+ if (ok)
+ dev->is_checkpointed = 1;
+ else
+ dev->is_checkpointed = 0;
+
+ return dev->is_checkpointed;
+}
+
+static int yaffs2_rd_checkpt_data(struct yaffs_dev *dev)
+{
+ int ok = 1;
+
+ if (!dev->param.is_yaffs2)
+ ok = 0;
+
+ if (ok && dev->param.skip_checkpt_rd) {
+ yaffs_trace(YAFFS_TRACE_CHECKPOINT,
+ "skipping checkpoint read");
+ ok = 0;
+ }
+
+ if (ok)
+ ok = yaffs2_checkpt_open(dev, 0); /* open for read */
+
+ if (ok) {
+ yaffs_trace(YAFFS_TRACE_CHECKPOINT,
+ "read checkpoint validity");
+ ok = yaffs2_rd_checkpt_validity_marker(dev, 1);
+ }
+ if (ok) {
+ yaffs_trace(YAFFS_TRACE_CHECKPOINT,
+ "read checkpoint device");
+ ok = yaffs2_rd_checkpt_dev(dev);
+ }
+ if (ok) {
+ yaffs_trace(YAFFS_TRACE_CHECKPOINT,
+ "read checkpoint objects");
+ ok = yaffs2_rd_checkpt_objs(dev);
+ }
+ if (ok) {
+ yaffs_trace(YAFFS_TRACE_CHECKPOINT,
+ "read checkpoint validity");
+ ok = yaffs2_rd_checkpt_validity_marker(dev, 0);
+ }
+
+ if (ok) {
+ ok = yaffs2_rd_checkpt_sum(dev);
+ yaffs_trace(YAFFS_TRACE_CHECKPOINT,
+ "read checkpoint checksum %d", ok);
+ }
+
+ if (!yaffs_checkpt_close(dev))
+ ok = 0;
+
+ if (ok)
+ dev->is_checkpointed = 1;
+ else
+ dev->is_checkpointed = 0;
+
+ return ok ? 1 : 0;
+}
+
+void yaffs2_checkpt_invalidate(struct yaffs_dev *dev)
+{
+ if (dev->is_checkpointed || dev->blocks_in_checkpt > 0) {
+ dev->is_checkpointed = 0;
+ yaffs2_checkpt_invalidate_stream(dev);
+ }
+ if (dev->param.sb_dirty_fn)
+ dev->param.sb_dirty_fn(dev);
+}
+
+int yaffs_checkpoint_save(struct yaffs_dev *dev)
+{
+ yaffs_trace(YAFFS_TRACE_CHECKPOINT,
+ "save entry: is_checkpointed %d",
+ dev->is_checkpointed);
+
+ yaffs_verify_objects(dev);
+ yaffs_verify_blocks(dev);
+ yaffs_verify_free_chunks(dev);
+
+ if (!dev->is_checkpointed) {
+ yaffs2_checkpt_invalidate(dev);
+ yaffs2_wr_checkpt_data(dev);
+ }
+
+ yaffs_trace(YAFFS_TRACE_CHECKPOINT | YAFFS_TRACE_MOUNT,
+ "save exit: is_checkpointed %d",
+ dev->is_checkpointed);
+
+ return dev->is_checkpointed;
+}
+
+int yaffs2_checkpt_restore(struct yaffs_dev *dev)
+{
+ int retval;
+
+ yaffs_trace(YAFFS_TRACE_CHECKPOINT,
+ "restore entry: is_checkpointed %d",
+ dev->is_checkpointed);
+
+ retval = yaffs2_rd_checkpt_data(dev);
+
+ if (dev->is_checkpointed) {
+ yaffs_verify_objects(dev);
+ yaffs_verify_blocks(dev);
+ yaffs_verify_free_chunks(dev);
+ }
+
+ yaffs_trace(YAFFS_TRACE_CHECKPOINT,
+ "restore exit: is_checkpointed %d",
+ dev->is_checkpointed);
+
+ return retval;
+}
+
+/* End of checkpointing */
+
+/* Hole handling logic for truncate past end of file */
+
+int yaffs2_handle_hole(struct yaffs_obj *obj, loff_t new_size)
+{
+ /* if new_size > old_file_size.
+ * We're going to be writing a hole.
+ * If the hole is small then write zeros otherwise write a start
+ * of hole marker.
+ */
+ loff_t old_file_size;
+ loff_t increase;
+ int small_hole;
+ int result = YAFFS_OK;
+ struct yaffs_dev *dev = NULL;
+ u8 *local_buffer = NULL;
+ int small_increase_ok = 0;
+
+ if (!obj)
+ return YAFFS_FAIL;
+
+ if (obj->variant_type != YAFFS_OBJECT_TYPE_FILE)
+ return YAFFS_FAIL;
+
+ dev = obj->my_dev;
+
+ /* Bail out if not yaffs2 mode */
+ if (!dev->param.is_yaffs2)
+ return YAFFS_OK;
+
+ old_file_size = obj->variant.file_variant.file_size;
+
+ if (new_size <= old_file_size)
+ return YAFFS_OK;
+
+ increase = new_size - old_file_size;
+
+ if (increase < YAFFS_SMALL_HOLE_THRESHOLD * dev->data_bytes_per_chunk &&
+ yaffs_check_alloc_available(dev, YAFFS_SMALL_HOLE_THRESHOLD + 1))
+ small_hole = 1;
+ else
+ small_hole = 0;
+
+ if (small_hole)
+ local_buffer = yaffs_get_temp_buffer(dev);
+
+ if (local_buffer) {
+ /* fill hole with zero bytes */
+ loff_t pos = old_file_size;
+ int this_write;
+ int written;
+ memset(local_buffer, 0, dev->data_bytes_per_chunk);
+ small_increase_ok = 1;
+
+ while (increase > 0 && small_increase_ok) {
+ this_write = increase;
+ if (this_write > (int)dev->data_bytes_per_chunk)
+ this_write = dev->data_bytes_per_chunk;
+ written =
+ yaffs_do_file_wr(obj, local_buffer, pos, this_write,
+ 0);
+ if (written == this_write) {
+ pos += this_write;
+ increase -= this_write;
+ } else {
+ small_increase_ok = 0;
+ }
+ }
+
+ yaffs_release_temp_buffer(dev, local_buffer);
+
+ /* If out of space then reverse any chunks we've added */
+ if (!small_increase_ok)
+ yaffs_resize_file_down(obj, old_file_size);
+ }
+
+ if (!small_increase_ok &&
+ obj->parent &&
+ obj->parent->obj_id != YAFFS_OBJECTID_UNLINKED &&
+ obj->parent->obj_id != YAFFS_OBJECTID_DELETED) {
+ /* Write a hole start header with the old file size */
+ yaffs_update_oh(obj, NULL, 0, 1, 0, NULL);
+ }
+
+ return result;
+}
+
+/* Yaffs2 scanning */
+
+struct yaffs_block_index {
+ int seq;
+ int block;
+};
+
+static int yaffs2_ybicmp(const void *a, const void *b)
+{
+ int aseq = ((struct yaffs_block_index *)a)->seq;
+ int bseq = ((struct yaffs_block_index *)b)->seq;
+ int ablock = ((struct yaffs_block_index *)a)->block;
+ int bblock = ((struct yaffs_block_index *)b)->block;
+
+ if (aseq == bseq)
+ return ablock - bblock;
+
+ return aseq - bseq;
+}
+
+static inline int yaffs2_scan_chunk(struct yaffs_dev *dev,
+ struct yaffs_block_info *bi,
+ int blk, int chunk_in_block,
+ int *found_chunks,
+ u8 *chunk_data,
+ struct list_head *hard_list,
+ int summary_available)
+{
+ struct yaffs_obj_hdr *oh;
+ struct yaffs_obj *in;
+ struct yaffs_obj *parent;
+ int equiv_id;
+ loff_t file_size;
+ int is_shrink;
+ int is_unlinked;
+ struct yaffs_ext_tags tags;
+ int result;
+ int alloc_failed = 0;
+ int chunk = blk * dev->param.chunks_per_block + chunk_in_block;
+ struct yaffs_file_var *file_var;
+ struct yaffs_hardlink_var *hl_var;
+ struct yaffs_symlink_var *sl_var;
+
+ if (summary_available) {
+ result = yaffs_summary_fetch(dev, &tags, chunk_in_block);
+ tags.seq_number = bi->seq_number;
+ }
+
+ if (!summary_available || tags.obj_id == 0) {
+ result = yaffs_rd_chunk_tags_nand(dev, chunk, NULL, &tags);
+ dev->tags_used++;
+ } else {
+ dev->summary_used++;
+ }
+
+ if (result == YAFFS_FAIL)
+ yaffs_trace(YAFFS_TRACE_SCAN,
+ "Could not get tags for chunk %d\n", chunk);
+ /* Let's have a good look at this chunk... */
+
+ if (!tags.chunk_used) {
+ /* An unassigned chunk in the block.
+ * If there are used chunks after this one, then
+ * it is a chunk that was skipped due to failing
+ * the erased check. Just skip it so that it can
+ * be deleted.
+ * But, more typically, We get here when this is
+ * an unallocated chunk and his means that
+ * either the block is empty or this is the one
+ * being allocated from
+ */
+
+ if (*found_chunks) {
+ /* This is a chunk that was skipped due
+ * to failing the erased check */
+ } else if (chunk_in_block == 0) {
+ /* We're looking at the first chunk in
+ * the block so the block is unused */
+ bi->block_state = YAFFS_BLOCK_STATE_EMPTY;
+ dev->n_erased_blocks++;
+ } else {
+ if (bi->block_state == YAFFS_BLOCK_STATE_NEEDS_SCAN ||
+ bi->block_state == YAFFS_BLOCK_STATE_ALLOCATING) {
+ if (dev->seq_number == bi->seq_number) {
+ /* Allocating from this block*/
+ yaffs_trace(YAFFS_TRACE_SCAN,
+ " Allocating from %d %d",
+ blk, chunk_in_block);
+
+ bi->block_state =
+ YAFFS_BLOCK_STATE_ALLOCATING;
+ dev->alloc_block = blk;
+ dev->alloc_page = chunk_in_block;
+ dev->alloc_block_finder = blk;
+ } else {
+ /* This is a partially written block
+ * that is not the current
+ * allocation block.
+ */
+ yaffs_trace(YAFFS_TRACE_SCAN,
+ "Partially written block %d detected. gc will fix this.",
+ blk);
+ }
+ }
+ }
+
+ dev->n_free_chunks++;
+
+ } else if (tags.ecc_result ==
+ YAFFS_ECC_RESULT_UNFIXED) {
+ yaffs_trace(YAFFS_TRACE_SCAN,
+ " Unfixed ECC in chunk(%d:%d), chunk ignored",
+ blk, chunk_in_block);
+ dev->n_free_chunks++;
+ } else if (tags.obj_id > YAFFS_MAX_OBJECT_ID ||
+ tags.chunk_id > YAFFS_MAX_CHUNK_ID ||
+ tags.obj_id == YAFFS_OBJECTID_SUMMARY ||
+ (tags.chunk_id > 0 &&
+ tags.n_bytes > dev->data_bytes_per_chunk) ||
+ tags.seq_number != bi->seq_number) {
+ yaffs_trace(YAFFS_TRACE_SCAN,
+ "Chunk (%d:%d) with bad tags:obj = %d, chunk_id = %d, n_bytes = %d, ignored",
+ blk, chunk_in_block, tags.obj_id,
+ tags.chunk_id, tags.n_bytes);
+ dev->n_free_chunks++;
+ } else if (tags.chunk_id > 0) {
+ /* chunk_id > 0 so it is a data chunk... */
+ loff_t endpos;
+ loff_t chunk_base = (tags.chunk_id - 1) *
+ dev->data_bytes_per_chunk;
+
+ *found_chunks = 1;
+
+ yaffs_set_chunk_bit(dev, blk, chunk_in_block);
+ bi->pages_in_use++;
+
+ in = yaffs_find_or_create_by_number(dev,
+ tags.obj_id,
+ YAFFS_OBJECT_TYPE_FILE);
+ if (!in)
+ /* Out of memory */
+ alloc_failed = 1;
+
+ if (in &&
+ in->variant_type == YAFFS_OBJECT_TYPE_FILE &&
+ chunk_base < in->variant.file_variant.shrink_size) {
+ /* This has not been invalidated by
+ * a resize */
+ if (!yaffs_put_chunk_in_file(in, tags.chunk_id,
+ chunk, -1))
+ alloc_failed = 1;
+
+ /* File size is calculated by looking at
+ * the data chunks if we have not
+ * seen an object header yet.
+ * Stop this practice once we find an
+ * object header.
+ */
+ endpos = chunk_base + tags.n_bytes;
+
+ if (!in->valid &&
+ in->variant.file_variant.stored_size < endpos) {
+ in->variant.file_variant.
+ stored_size = endpos;
+ in->variant.file_variant.
+ file_size = endpos;
+ }
+ } else if (in) {
+ /* This chunk has been invalidated by a
+ * resize, or a past file deletion
+ * so delete the chunk*/
+ yaffs_chunk_del(dev, chunk, 1, __LINE__);
+ }
+ } else {
+ /* chunk_id == 0, so it is an ObjectHeader.
+ * Thus, we read in the object header and make
+ * the object
+ */
+ *found_chunks = 1;
+
+ yaffs_set_chunk_bit(dev, blk, chunk_in_block);
+ bi->pages_in_use++;
+
+ oh = NULL;
+ in = NULL;
+
+ if (tags.extra_available) {
+ in = yaffs_find_or_create_by_number(dev,
+ tags.obj_id,
+ tags.extra_obj_type);
+ if (!in)
+ alloc_failed = 1;
+ }
+
+ if (!in ||
+ (!in->valid && dev->param.disable_lazy_load) ||
+ tags.extra_shadows ||
+ (!in->valid && (tags.obj_id == YAFFS_OBJECTID_ROOT ||
+ tags.obj_id == YAFFS_OBJECTID_LOSTNFOUND))) {
+
+ /* If we don't have valid info then we
+ * need to read the chunk
+ * TODO In future we can probably defer
+ * reading the chunk and living with
+ * invalid data until needed.
+ */
+
+ result = yaffs_rd_chunk_tags_nand(dev,
+ chunk,
+ chunk_data,
+ NULL);
+
+ oh = (struct yaffs_obj_hdr *)chunk_data;
+
+ yaffs_do_endian_oh(dev, oh);
+
+ if (dev->param.inband_tags) {
+ /* Fix up the header if they got
+ * corrupted by inband tags */
+ oh->shadows_obj =
+ oh->inband_shadowed_obj_id;
+ oh->is_shrink =
+ oh->inband_is_shrink;
+ }
+
+ if (!in) {
+ in = yaffs_find_or_create_by_number(dev,
+ tags.obj_id, oh->type);
+ if (!in)
+ alloc_failed = 1;
+ }
+ }
+
+ if (!in) {
+ /* TODO Hoosterman we have a problem! */
+ yaffs_trace(YAFFS_TRACE_ERROR,
+ "yaffs tragedy: Could not make object for object %d at chunk %d during scan",
+ tags.obj_id, chunk);
+ return YAFFS_FAIL;
+ }
+
+ if (in->valid) {
+ /* We have already filled this one.
+ * We have a duplicate that will be
+ * discarded, but we first have to suck
+ * out resize info if it is a file.
+ */
+ if ((in->variant_type == YAFFS_OBJECT_TYPE_FILE) &&
+ ((oh && oh->type == YAFFS_OBJECT_TYPE_FILE) ||
+ (tags.extra_available &&
+ tags.extra_obj_type == YAFFS_OBJECT_TYPE_FILE)
+ )) {
+ loff_t this_size = (oh) ?
+ yaffs_oh_to_size(dev, oh, 0) :
+ tags.extra_file_size;
+ u32 parent_obj_id = (oh) ?
+ (u32)oh->parent_obj_id :
+ tags.extra_parent_id;
+
+ is_shrink = (oh) ?
+ oh->is_shrink :
+ tags.extra_is_shrink;
+
+ /* If it is deleted (unlinked
+ * at start also means deleted)
+ * we treat the file size as
+ * being zeroed at this point.
+ */
+ if (parent_obj_id == YAFFS_OBJECTID_DELETED ||
+ parent_obj_id == YAFFS_OBJECTID_UNLINKED) {
+ this_size = 0;
+ is_shrink = 1;
+ }
+
+ if (is_shrink &&
+ in->variant.file_variant.shrink_size >
+ this_size)
+ in->variant.file_variant.shrink_size =
+ this_size;
+
+ if (is_shrink)
+ bi->has_shrink_hdr = 1;
+ }
+ /* Use existing - destroy this one. */
+ yaffs_chunk_del(dev, chunk, 1, __LINE__);
+ }
+
+ if (!in->valid && in->variant_type !=
+ (oh ? oh->type : tags.extra_obj_type)) {
+ yaffs_trace(YAFFS_TRACE_ERROR,
+ "yaffs tragedy: Bad type, %d != %d, for object %d at chunk %d during scan",
+ oh ? oh->type : tags.extra_obj_type,
+ in->variant_type, tags.obj_id,
+ chunk);
+ in = yaffs_retype_obj(in, oh ? oh->type : tags.extra_obj_type);
+ }
+
+ if (!in->valid &&
+ (tags.obj_id == YAFFS_OBJECTID_ROOT ||
+ tags.obj_id == YAFFS_OBJECTID_LOSTNFOUND)) {
+ /* We only load some info, don't fiddle
+ * with directory structure */
+ in->valid = 1;
+
+ if (oh) {
+ in->yst_mode = oh->yst_mode;
+ yaffs_load_attribs(in, oh);
+ in->lazy_loaded = 0;
+ } else {
+ in->lazy_loaded = 1;
+ }
+ in->hdr_chunk = chunk;
+
+ } else if (!in->valid) {
+ /* we need to load this info */
+ in->valid = 1;
+ in->hdr_chunk = chunk;
+ if (oh) {
+ in->variant_type = oh->type;
+ in->yst_mode = oh->yst_mode;
+ yaffs_load_attribs(in, oh);
+
+ if (oh->shadows_obj > 0)
+ yaffs_handle_shadowed_obj(dev,
+ oh->shadows_obj, 1);
+
+ yaffs_set_obj_name_from_oh(in, oh);
+ parent = yaffs_find_or_create_by_number(dev,
+ oh->parent_obj_id,
+ YAFFS_OBJECT_TYPE_DIRECTORY);
+ file_size = yaffs_oh_to_size(dev, oh, 0);
+ is_shrink = oh->is_shrink;
+ equiv_id = oh->equiv_id;
+ } else {
+ in->variant_type = tags.extra_obj_type;
+ parent = yaffs_find_or_create_by_number(dev,
+ tags.extra_parent_id,
+ YAFFS_OBJECT_TYPE_DIRECTORY);
+ file_size = tags.extra_file_size;
+ is_shrink = tags.extra_is_shrink;
+ equiv_id = tags.extra_equiv_id;
+ in->lazy_loaded = 1;
+ }
+ in->dirty = 0;
+
+ if (!parent)
+ alloc_failed = 1;
+
+ /* directory stuff...
+ * hook up to parent
+ */
+
+ if (parent &&
+ parent->variant_type == YAFFS_OBJECT_TYPE_UNKNOWN) {
+ /* Set up as a directory */
+ parent->variant_type =
+ YAFFS_OBJECT_TYPE_DIRECTORY;
+ INIT_LIST_HEAD(&parent->
+ variant.dir_variant.children);
+ } else if (!parent ||
+ parent->variant_type !=
+ YAFFS_OBJECT_TYPE_DIRECTORY) {
+ /* Hoosterman, another problem....
+ * Trying to use a non-directory as a directory
+ */
+
+ yaffs_trace(YAFFS_TRACE_ERROR,
+ "yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found."
+ );
+ parent = dev->lost_n_found;
+ }
+ yaffs_add_obj_to_dir(parent, in);
+
+ is_unlinked = (parent == dev->del_dir) ||
+ (parent == dev->unlinked_dir);
+
+ if (is_shrink)
+ /* Mark the block */
+ bi->has_shrink_hdr = 1;
+
+ /* Note re hardlinks.
+ * Since we might scan a hardlink before its equivalent
+ * object is scanned we put them all in a list.
+ * After scanning is complete, we should have all the
+ * objects, so we run through this list and fix up all
+ * the chains.
+ */
+
+ switch (in->variant_type) {
+ case YAFFS_OBJECT_TYPE_UNKNOWN:
+ /* Todo got a problem */
+ break;
+ case YAFFS_OBJECT_TYPE_FILE:
+ file_var = &in->variant.file_variant;
+ if (file_var->stored_size < file_size) {
+ /* This covers the case where the file
+ * size is greater than the data held.
+ * This will happen if the file is
+ * resized to be larger than its
+ * current data extents.
+ */
+ file_var->file_size = file_size;
+ file_var->stored_size = file_size;
+ }
+
+ if (file_var->shrink_size > file_size)
+ file_var->shrink_size = file_size;
+
+ break;
+ case YAFFS_OBJECT_TYPE_HARDLINK:
+ hl_var = &in->variant.hardlink_variant;
+ if (!is_unlinked) {
+ hl_var->equiv_id = equiv_id;
+ list_add(&in->hard_links, hard_list);
+ }
+ break;
+ case YAFFS_OBJECT_TYPE_DIRECTORY:
+ /* Do nothing */
+ break;
+ case YAFFS_OBJECT_TYPE_SPECIAL:
+ /* Do nothing */
+ break;
+ case YAFFS_OBJECT_TYPE_SYMLINK:
+ sl_var = &in->variant.symlink_variant;
+ if (oh) {
+ sl_var->alias =
+ yaffs_clone_str(oh->alias);
+ if (!sl_var->alias)
+ alloc_failed = 1;
+ }
+ break;
+ }
+ }
+ }
+ return alloc_failed ? YAFFS_FAIL : YAFFS_OK;
+}
+
+int yaffs2_scan_backwards(struct yaffs_dev *dev)
+{
+ u32 blk;
+ int block_iter;
+ int start_iter;
+ int end_iter;
+ int n_to_scan = 0;
+ enum yaffs_block_state state;
+ int c;
+ LIST_HEAD(hard_list);
+ struct yaffs_block_info *bi;
+ u32 seq_number;
+ int n_blocks = dev->internal_end_block - dev->internal_start_block + 1;
+ u8 *chunk_data;
+ int found_chunks;
+ int alloc_failed = 0;
+ struct yaffs_block_index *block_index = NULL;
+ int alt_block_index = 0;
+ int summary_available;
+
+ yaffs_trace(YAFFS_TRACE_SCAN,
+ "yaffs2_scan_backwards starts intstartblk %d intendblk %d...",
+ dev->internal_start_block, dev->internal_end_block);
+
+ dev->seq_number = YAFFS_LOWEST_SEQUENCE_NUMBER;
+
+ block_index =
+ kmalloc(n_blocks * sizeof(struct yaffs_block_index), GFP_NOFS);
+
+ if (!block_index) {
+ block_index =
+ vmalloc(n_blocks * sizeof(struct yaffs_block_index));
+ alt_block_index = 1;
+ }
+
+ if (!block_index) {
+ yaffs_trace(YAFFS_TRACE_SCAN,
+ "yaffs2_scan_backwards() could not allocate block index!"
+ );
+ return YAFFS_FAIL;
+ }
+
+ dev->blocks_in_checkpt = 0;
+
+ chunk_data = yaffs_get_temp_buffer(dev);
+
+ /* Scan all the blocks to determine their state */
+ bi = dev->block_info;
+ for (blk = dev->internal_start_block; blk <= dev->internal_end_block;
+ blk++) {
+ yaffs_clear_chunk_bits(dev, blk);
+ bi->pages_in_use = 0;
+ bi->soft_del_pages = 0;
+
+ yaffs_query_init_block_state(dev, blk, &state, &seq_number);
+
+ bi->block_state = state;
+ bi->seq_number = seq_number;
+
+ if (bi->seq_number == YAFFS_SEQUENCE_CHECKPOINT_DATA)
+ bi->block_state = YAFFS_BLOCK_STATE_CHECKPOINT;
+ if (bi->seq_number == YAFFS_SEQUENCE_BAD_BLOCK)
+ bi->block_state = YAFFS_BLOCK_STATE_DEAD;
+
+ yaffs_trace(YAFFS_TRACE_SCAN_DEBUG,
+ "Block scanning block %d state %d seq %d",
+ blk, bi->block_state, seq_number);
+
+ if (bi->block_state == YAFFS_BLOCK_STATE_CHECKPOINT) {
+ dev->blocks_in_checkpt++;
+
+ } else if (bi->block_state == YAFFS_BLOCK_STATE_DEAD) {
+ yaffs_trace(YAFFS_TRACE_BAD_BLOCKS,
+ "block %d is bad", blk);
+ } else if (bi->block_state == YAFFS_BLOCK_STATE_EMPTY) {
+ yaffs_trace(YAFFS_TRACE_SCAN_DEBUG, "Block empty ");
+ dev->n_erased_blocks++;
+ dev->n_free_chunks += dev->param.chunks_per_block;
+ } else if (bi->block_state ==
+ YAFFS_BLOCK_STATE_NEEDS_SCAN) {
+ /* Determine the highest sequence number */
+ if (seq_number >= YAFFS_LOWEST_SEQUENCE_NUMBER &&
+ seq_number < YAFFS_HIGHEST_SEQUENCE_NUMBER) {
+ block_index[n_to_scan].seq = seq_number;
+ block_index[n_to_scan].block = blk;
+ n_to_scan++;
+ if (seq_number >= dev->seq_number)
+ dev->seq_number = seq_number;
+ } else {
+ /* TODO: Nasty sequence number! */
+ yaffs_trace(YAFFS_TRACE_SCAN,
+ "Block scanning block %d has bad sequence number %d",
+ blk, seq_number);
+ }
+ }
+ bi++;
+ }
+
+ yaffs_trace(YAFFS_TRACE_ALWAYS, "%d blocks to be sorted...", n_to_scan);
+
+ cond_resched();
+
+ /* Sort the blocks by sequence number */
+ sort(block_index, n_to_scan, sizeof(struct yaffs_block_index),
+ yaffs2_ybicmp, NULL);
+
+ cond_resched();
+
+ yaffs_trace(YAFFS_TRACE_SCAN, "...done");
+
+ /* Now scan the blocks looking at the data. */
+ start_iter = 0;
+ end_iter = n_to_scan - 1;
+ yaffs_trace(YAFFS_TRACE_SCAN_DEBUG, "%d blocks to scan", n_to_scan);
+
+ /* For each block.... backwards */
+ for (block_iter = end_iter;
+ !alloc_failed && block_iter >= start_iter;
+ block_iter--) {
+ /* Cooperative multitasking! This loop can run for so
+ long that watchdog timers expire. */
+ cond_resched();
+
+ /* get the block to scan in the correct order */
+ blk = block_index[block_iter].block;
+ bi = yaffs_get_block_info(dev, blk);
+
+ summary_available = yaffs_summary_read(dev, dev->sum_tags, blk);
+
+ /* For each chunk in each block that needs scanning.... */
+ found_chunks = 0;
+ if (summary_available)
+ c = dev->chunks_per_summary - 1;
+ else
+ c = dev->param.chunks_per_block - 1;
+
+ for (/* c is already initialised */;
+ !alloc_failed && c >= 0 &&
+ (bi->block_state == YAFFS_BLOCK_STATE_NEEDS_SCAN ||
+ bi->block_state == YAFFS_BLOCK_STATE_ALLOCATING);
+ c--) {
+ /* Scan backwards...
+ * Read the tags and decide what to do
+ */
+ if (yaffs2_scan_chunk(dev, bi, blk, c,
+ &found_chunks, chunk_data,
+ &hard_list, summary_available) ==
+ YAFFS_FAIL)
+ alloc_failed = 1;
+ }
+
+ if (bi->block_state == YAFFS_BLOCK_STATE_NEEDS_SCAN) {
+ /* If we got this far while scanning, then the block
+ * is fully allocated. */
+ bi->block_state = YAFFS_BLOCK_STATE_FULL;
+ }
+
+ /* Now let's see if it was dirty */
+ if (bi->pages_in_use == 0 &&
+ !bi->has_shrink_hdr &&
+ bi->block_state == YAFFS_BLOCK_STATE_FULL) {
+ yaffs_block_became_dirty(dev, blk);
+ }
+ }
+
+ yaffs_skip_rest_of_block(dev);
+
+ if (alt_block_index)
+ vfree(block_index);
+ else
+ kfree(block_index);
+
+ /* Ok, we've done all the scanning.
+ * Fix up the hard link chains.
+ * We have scanned all the objects, now it's time to add these
+ * hardlinks.
+ */
+ yaffs_link_fixup(dev, &hard_list);
+
+ yaffs_release_temp_buffer(dev, chunk_data);
+
+ if (alloc_failed)
+ return YAFFS_FAIL;
+
+ yaffs_trace(YAFFS_TRACE_SCAN, "yaffs2_scan_backwards ends");
+
+ return YAFFS_OK;
+}
diff -urN linux-4.9.37/fs/yaffs2/yaffs_yaffs2.h linux-4.9.y/fs/yaffs2/yaffs_yaffs2.h
--- linux-4.9.37/fs/yaffs2/yaffs_yaffs2.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/yaffs_yaffs2.h 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,39 @@
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+#ifndef __YAFFS_YAFFS2_H__
+#define __YAFFS_YAFFS2_H__
+
+#include "yaffs_guts.h"
+
+void yaffs_calc_oldest_dirty_seq(struct yaffs_dev *dev);
+void yaffs2_find_oldest_dirty_seq(struct yaffs_dev *dev);
+void yaffs2_clear_oldest_dirty_seq(struct yaffs_dev *dev,
+ struct yaffs_block_info *bi);
+void yaffs2_update_oldest_dirty_seq(struct yaffs_dev *dev, unsigned block_no,
+ struct yaffs_block_info *bi);
+int yaffs_block_ok_for_gc(struct yaffs_dev *dev, struct yaffs_block_info *bi);
+u32 yaffs2_find_refresh_block(struct yaffs_dev *dev);
+int yaffs2_checkpt_required(struct yaffs_dev *dev);
+int yaffs_calc_checkpt_blocks_required(struct yaffs_dev *dev);
+
+void yaffs2_checkpt_invalidate(struct yaffs_dev *dev);
+int yaffs2_checkpt_save(struct yaffs_dev *dev);
+int yaffs2_checkpt_restore(struct yaffs_dev *dev);
+
+int yaffs2_handle_hole(struct yaffs_obj *obj, loff_t new_size);
+int yaffs2_scan_backwards(struct yaffs_dev *dev);
+
+#endif
diff -urN linux-4.9.37/fs/yaffs2/yportenv.h linux-4.9.y/fs/yaffs2/yportenv.h
--- linux-4.9.37/fs/yaffs2/yportenv.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/fs/yaffs2/yportenv.h 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,85 @@
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+#ifndef __YPORTENV_H__
+#define __YPORTENV_H__
+
+/*
+ * Define the MTD version in terms of Linux Kernel versions
+ * This allows yaffs to be used independantly of the kernel
+ * as well as with it.
+ */
+
+#define MTD_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c))
+
+#ifdef YAFFS_OUT_OF_TREE
+#include "moduleconfig.h"
+#endif
+
+#include <linux/version.h>
+#define MTD_VERSION_CODE LINUX_VERSION_CODE
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))
+#include <linux/config.h>
+#endif
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/xattr.h>
+#include <linux/list.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/stat.h>
+#include <linux/sort.h>
+#include <linux/bitops.h>
+
+/* These type wrappings are used to support Unicode names in WinCE. */
+#define YCHAR char
+#define YUCHAR unsigned char
+#define _Y(x) x
+
+#define YAFFS_LOSTNFOUND_NAME "lost+found"
+#define YAFFS_LOSTNFOUND_PREFIX "obj"
+
+
+#define YAFFS_ROOT_MODE 0755
+#define YAFFS_LOSTNFOUND_MODE 0700
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
+#define Y_CURRENT_TIME CURRENT_TIME.tv_sec
+#define Y_TIME_CONVERT(x) (x).tv_sec
+#else
+#define Y_CURRENT_TIME CURRENT_TIME
+#define Y_TIME_CONVERT(x) (x)
+#endif
+
+#define compile_time_assertion(assertion) \
+ ({ int x = __builtin_choose_expr(assertion, 0, (void)0); (void) x; })
+
+
+#define yaffs_printf(msk, fmt, ...) \
+ printk(KERN_DEBUG "yaffs: " fmt "\n", ##__VA_ARGS__)
+
+#define yaffs_trace(msk, fmt, ...) do { \
+ if (yaffs_trace_mask & (msk)) \
+ printk(KERN_DEBUG "yaffs: " fmt "\n", ##__VA_ARGS__); \
+} while (0)
+
+
+#endif
diff -urN linux-4.9.37/.get_maintainer.ignore linux-4.9.y/.get_maintainer.ignore
--- linux-4.9.37/.get_maintainer.ignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/.get_maintainer.ignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-Christoph Hellwig <hch@lst.de>
diff -urN linux-4.9.37/.gitattributes linux-4.9.y/.gitattributes
--- linux-4.9.37/.gitattributes 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/.gitattributes 1970-01-01 03:00:00.000000000 +0300
@@ -1,2 +0,0 @@
-*.c diff=cpp
-*.h diff=cpp
diff -urN linux-4.9.37/.gitignore linux-4.9.y/.gitignore
--- linux-4.9.37/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,116 +0,0 @@
-#
-# NOTE! Don't add files that are generated in specific
-# subdirectories here. Add them in the ".gitignore" file
-# in that subdirectory instead.
-#
-# NOTE! Please use 'git ls-files -i --exclude-standard'
-# command after changing this file, to see if there are
-# any tracked files which get ignored after the change.
-#
-# Normal rules
-#
-.*
-*.o
-*.o.*
-*.a
-*.s
-*.ko
-*.so
-*.so.dbg
-*.mod.c
-*.i
-*.lst
-*.symtypes
-*.order
-*.elf
-*.bin
-*.tar
-*.gz
-*.bz2
-*.lzma
-*.xz
-*.lz4
-*.lzo
-*.patch
-*.gcno
-modules.builtin
-Module.symvers
-*.dwo
-*.su
-*.c.[012]*.*
-
-#
-# Top-level generic files
-#
-/tags
-/TAGS
-/linux
-/vmlinux
-/vmlinux.32
-/vmlinux-gdb.py
-/vmlinuz
-/System.map
-/Module.markers
-
-#
-# Debian directory (make deb-pkg)
-#
-/debian/
-
-#
-# tar directory (make tar*-pkg)
-#
-/tar-install/
-
-#
-# git files that we don't want to ignore even if they are dot-files
-#
-!.gitignore
-!.mailmap
-!.cocciconfig
-
-#
-# Generated include files
-#
-include/config
-include/generated
-arch/*/include/generated
-
-# stgit generated dirs
-patches-*
-
-# quilt's files
-patches
-series
-
-# cscope files
-cscope.*
-ncscope.*
-
-# gnu global files
-GPATH
-GRTAGS
-GSYMS
-GTAGS
-
-# id-utils files
-ID
-
-*.orig
-*~
-\#*#
-
-#
-# Leavings from module signing
-#
-extra_certificates
-signing_key.pem
-signing_key.priv
-signing_key.x509
-x509.genkey
-
-# Kconfig presets
-all.config
-
-# Kdevelop4
-*.kdev4
diff -urN linux-4.9.37/include/dt-bindings/clock/gk7202v300-clock.h linux-4.9.y/include/dt-bindings/clock/gk7202v300-clock.h
--- linux-4.9.37/include/dt-bindings/clock/gk7202v300-clock.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/include/dt-bindings/clock/gk7202v300-clock.h 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#ifndef __DTS_GK7202V300_CLOCK_H
+#define __DTS_GK7202V300_CLOCK_H
+
+/* clk in GK7202V300 CRG */
+/* fixed rate clocks */
+#define GK7202V300_FIXED_100K 1
+#define GK7202V300_FIXED_400K 2
+#define GK7202V300_FIXED_3M 3
+#define GK7202V300_FIXED_6M 4
+#define GK7202V300_FIXED_12M 5
+#define GK7202V300_FIXED_24M 6
+#define GK7202V300_FIXED_25M 7
+#define GK7202V300_FIXED_50M 8
+#define GK7202V300_FIXED_83P3M 9
+#define GK7202V300_FIXED_90M 10
+#define GK7202V300_FIXED_100M 11
+#define GK7202V300_FIXED_112M 12
+#define GK7202V300_FIXED_125M 13
+#define GK7202V300_FIXED_148P5M 14
+#define GK7202V300_FIXED_150M 15
+#define GK7202V300_FIXED_200M 16
+#define GK7202V300_FIXED_250M 17
+#define GK7202V300_FIXED_300M 18
+#define GK7202V300_FIXED_324M 19
+#define GK7202V300_FIXED_342M 20
+#define GK7202V300_FIXED_375M 21
+#define GK7202V300_FIXED_400M 22
+#define GK7202V300_FIXED_448M 23
+#define GK7202V300_FIXED_500M 24
+#define GK7202V300_FIXED_540M 25
+#define GK7202V300_FIXED_600M 26
+#define GK7202V300_FIXED_750M 27
+#define GK7202V300_FIXED_1000M 28
+#define GK7202V300_FIXED_1500M 29
+
+/* mux clocks */
+#define GK7202V300_SYSAXI_CLK 30
+#define GK7202V300_SYSAPB_CLK 31
+#define GK7202V300_FMC_MUX 32
+#define GK7202V300_UART_MUX 33
+#define GK7202V300_MMC0_MUX 34
+#define GK7202V300_MMC1_MUX 35
+#define GK7202V300_MMC2_MUX 36
+#define GK7202V300_ETH_MUX 37
+#define GK7202V300_USB2_MUX 80
+/* gate clocks */
+#define GK7202V300_UART0_CLK 40
+#define GK7202V300_UART1_CLK 41
+#define GK7202V300_UART2_CLK 42
+#define GK7202V300_FMC_CLK 43
+#define GK7202V300_ETH0_CLK 44
+#define GK7202V300_EDMAC_AXICLK 45
+#define GK7202V300_EDMAC_CLK 46
+#define GK7202V300_SPI0_CLK 48
+#define GK7202V300_SPI1_CLK 49
+#define GK7202V300_MMC0_CLK 50
+#define GK7202V300_MMC1_CLK 51
+#define GK7202V300_MMC2_CLK 52
+#define GK7202V300_I2C0_CLK 53
+#define GK7202V300_I2C1_CLK 54
+#define GK7202V300_I2C2_CLK 55
+#define GK7202V300_USB2_BUS_CLK 81
+#define GK7202V300_USB2_REF_CLK 82
+#define GK7202V300_USB2_UTMI_CLK 83
+#define GK7202V300_USB2_PHY_APB_CLK 84
+#define GK7202V300_USB2_PHY_PLL_CLK 85
+#define GK7202V300_USB2_PHY_XO_CLK 86
+
+#define GK7202V300_NR_CLKS 256
+#define GK7202V300_NR_RSTS 256
+
+#endif /* __DTS_GK7202V300_CLOCK_H */
diff -urN linux-4.9.37/include/dt-bindings/clock/gk7205v200-clock.h linux-4.9.y/include/dt-bindings/clock/gk7205v200-clock.h
--- linux-4.9.37/include/dt-bindings/clock/gk7205v200-clock.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/include/dt-bindings/clock/gk7205v200-clock.h 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#ifndef __DTS_GK7205V200_CLOCK_H
+#define __DTS_GK7205V200_CLOCK_H
+
+/* clk in GK7205V200 CRG */
+/* fixed rate clocks */
+#define GK7205V200_FIXED_100K 1
+#define GK7205V200_FIXED_400K 2
+#define GK7205V200_FIXED_3M 3
+#define GK7205V200_FIXED_6M 4
+#define GK7205V200_FIXED_12M 5
+#define GK7205V200_FIXED_24M 6
+#define GK7205V200_FIXED_25M 7
+#define GK7205V200_FIXED_50M 8
+#define GK7205V200_FIXED_83P3M 9
+#define GK7205V200_FIXED_90M 10
+#define GK7205V200_FIXED_100M 11
+#define GK7205V200_FIXED_112M 12
+#define GK7205V200_FIXED_125M 13
+#define GK7205V200_FIXED_148P5M 14
+#define GK7205V200_FIXED_150M 15
+#define GK7205V200_FIXED_200M 16
+#define GK7205V200_FIXED_250M 17
+#define GK7205V200_FIXED_300M 18
+#define GK7205V200_FIXED_324M 19
+#define GK7205V200_FIXED_342M 20
+#define GK7205V200_FIXED_375M 21
+#define GK7205V200_FIXED_400M 22
+#define GK7205V200_FIXED_448M 23
+#define GK7205V200_FIXED_500M 24
+#define GK7205V200_FIXED_540M 25
+#define GK7205V200_FIXED_600M 26
+#define GK7205V200_FIXED_750M 27
+#define GK7205V200_FIXED_1000M 28
+#define GK7205V200_FIXED_1500M 29
+
+/* mux clocks */
+#define GK7205V200_SYSAXI_CLK 30
+#define GK7205V200_SYSAPB_CLK 31
+#define GK7205V200_FMC_MUX 32
+#define GK7205V200_UART_MUX 33
+#define GK7205V200_MMC0_MUX 34
+#define GK7205V200_MMC1_MUX 35
+#define GK7205V200_MMC2_MUX 36
+#define GK7205V200_ETH_MUX 37
+#define GK7205V200_USB2_MUX 80
+/* gate clocks */
+#define GK7205V200_UART0_CLK 40
+#define GK7205V200_UART1_CLK 41
+#define GK7205V200_UART2_CLK 42
+#define GK7205V200_FMC_CLK 43
+#define GK7205V200_ETH0_CLK 44
+#define GK7205V200_EDMAC_AXICLK 45
+#define GK7205V200_EDMAC_CLK 46
+#define GK7205V200_SPI0_CLK 48
+#define GK7205V200_SPI1_CLK 49
+#define GK7205V200_MMC0_CLK 50
+#define GK7205V200_MMC1_CLK 51
+#define GK7205V200_MMC2_CLK 52
+#define GK7205V200_I2C0_CLK 53
+#define GK7205V200_I2C1_CLK 54
+#define GK7205V200_I2C2_CLK 55
+#define GK7205V200_USB2_BUS_CLK 81
+#define GK7205V200_USB2_REF_CLK 82
+#define GK7205V200_USB2_UTMI_CLK 83
+#define GK7205V200_USB2_PHY_APB_CLK 84
+#define GK7205V200_USB2_PHY_PLL_CLK 85
+#define GK7205V200_USB2_PHY_XO_CLK 86
+
+#define GK7205V200_NR_CLKS 256
+#define GK7205V200_NR_RSTS 256
+
+#endif /* __DTS_GK7205V200_CLOCK_H */
diff -urN linux-4.9.37/include/dt-bindings/clock/gk7205v300-clock.h linux-4.9.y/include/dt-bindings/clock/gk7205v300-clock.h
--- linux-4.9.37/include/dt-bindings/clock/gk7205v300-clock.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/include/dt-bindings/clock/gk7205v300-clock.h 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#ifndef __DTS_GK7205V300_CLOCK_H
+#define __DTS_GK7205V300_CLOCK_H
+
+/* clk in GK7205V300 CRG */
+/* fixed rate clocks */
+#define GK7205V300_FIXED_100K 1
+#define GK7205V300_FIXED_400K 2
+#define GK7205V300_FIXED_3M 3
+#define GK7205V300_FIXED_6M 4
+#define GK7205V300_FIXED_12M 5
+#define GK7205V300_FIXED_24M 6
+#define GK7205V300_FIXED_25M 7
+#define GK7205V300_FIXED_50M 8
+#define GK7205V300_FIXED_83P3M 9
+#define GK7205V300_FIXED_90M 10
+#define GK7205V300_FIXED_100M 11
+#define GK7205V300_FIXED_112M 12
+#define GK7205V300_FIXED_125M 13
+#define GK7205V300_FIXED_148P5M 14
+#define GK7205V300_FIXED_150M 15
+#define GK7205V300_FIXED_200M 16
+#define GK7205V300_FIXED_250M 17
+#define GK7205V300_FIXED_300M 18
+#define GK7205V300_FIXED_324M 19
+#define GK7205V300_FIXED_342M 20
+#define GK7205V300_FIXED_375M 21
+#define GK7205V300_FIXED_400M 22
+#define GK7205V300_FIXED_448M 23
+#define GK7205V300_FIXED_500M 24
+#define GK7205V300_FIXED_540M 25
+#define GK7205V300_FIXED_600M 26
+#define GK7205V300_FIXED_750M 27
+#define GK7205V300_FIXED_1000M 28
+#define GK7205V300_FIXED_1500M 29
+
+/* mux clocks */
+#define GK7205V300_SYSAXI_CLK 30
+#define GK7205V300_SYSAPB_CLK 31
+#define GK7205V300_FMC_MUX 32
+#define GK7205V300_UART_MUX 33
+#define GK7205V300_MMC0_MUX 34
+#define GK7205V300_MMC1_MUX 35
+#define GK7205V300_MMC2_MUX 36
+#define GK7205V300_ETH_MUX 37
+#define GK7205V300_USB2_MUX 80
+/* gate clocks */
+#define GK7205V300_UART0_CLK 40
+#define GK7205V300_UART1_CLK 41
+#define GK7205V300_UART2_CLK 42
+#define GK7205V300_FMC_CLK 43
+#define GK7205V300_ETH0_CLK 44
+#define GK7205V300_EDMAC_AXICLK 45
+#define GK7205V300_EDMAC_CLK 46
+#define GK7205V300_SPI0_CLK 48
+#define GK7205V300_SPI1_CLK 49
+#define GK7205V300_MMC0_CLK 50
+#define GK7205V300_MMC1_CLK 51
+#define GK7205V300_MMC2_CLK 52
+#define GK7205V300_I2C0_CLK 53
+#define GK7205V300_I2C1_CLK 54
+#define GK7205V300_I2C2_CLK 55
+#define GK7205V300_USB2_BUS_CLK 81
+#define GK7205V300_USB2_REF_CLK 82
+#define GK7205V300_USB2_UTMI_CLK 83
+#define GK7205V300_USB2_PHY_APB_CLK 84
+#define GK7205V300_USB2_PHY_PLL_CLK 85
+#define GK7205V300_USB2_PHY_XO_CLK 86
+
+#define GK7205V300_NR_CLKS 256
+#define GK7205V300_NR_RSTS 256
+
+#endif /* __DTS_GK7205V300_CLOCK_H */
diff -urN linux-4.9.37/include/dt-bindings/clock/gk7605v100-clock.h linux-4.9.y/include/dt-bindings/clock/gk7605v100-clock.h
--- linux-4.9.37/include/dt-bindings/clock/gk7605v100-clock.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/include/dt-bindings/clock/gk7605v100-clock.h 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#ifndef __DTS_GK7605V100_CLOCK_H
+#define __DTS_GK7605V100_CLOCK_H
+
+/* clk in GK7605V100 CRG */
+/* fixed rate clocks */
+#define GK7605V100_FIXED_100K 1
+#define GK7605V100_FIXED_400K 2
+#define GK7605V100_FIXED_3M 3
+#define GK7605V100_FIXED_6M 4
+#define GK7605V100_FIXED_12M 5
+#define GK7605V100_FIXED_24M 6
+#define GK7605V100_FIXED_25M 7
+#define GK7605V100_FIXED_50M 8
+#define GK7605V100_FIXED_83P3M 9
+#define GK7605V100_FIXED_90M 10
+#define GK7605V100_FIXED_100M 11
+#define GK7605V100_FIXED_112M 12
+#define GK7605V100_FIXED_125M 13
+#define GK7605V100_FIXED_148P5M 14
+#define GK7605V100_FIXED_150M 15
+#define GK7605V100_FIXED_200M 16
+#define GK7605V100_FIXED_250M 17
+#define GK7605V100_FIXED_300M 18
+#define GK7605V100_FIXED_324M 19
+#define GK7605V100_FIXED_342M 20
+#define GK7605V100_FIXED_375M 21
+#define GK7605V100_FIXED_400M 22
+#define GK7605V100_FIXED_448M 23
+#define GK7605V100_FIXED_500M 24
+#define GK7605V100_FIXED_540M 25
+#define GK7605V100_FIXED_600M 26
+#define GK7605V100_FIXED_750M 27
+#define GK7605V100_FIXED_1000M 28
+#define GK7605V100_FIXED_1500M 29
+
+/* mux clocks */
+#define GK7605V100_SYSAXI_CLK 30
+#define GK7605V100_SYSAPB_CLK 31
+#define GK7605V100_FMC_MUX 32
+#define GK7605V100_UART_MUX 33
+#define GK7605V100_MMC0_MUX 34
+#define GK7605V100_MMC1_MUX 35
+#define GK7605V100_MMC2_MUX 36
+#define GK7605V100_ETH_MUX 37
+#define GK7605V100_USB2_MUX 80
+/* gate clocks */
+#define GK7605V100_UART0_CLK 40
+#define GK7605V100_UART1_CLK 41
+#define GK7605V100_UART2_CLK 42
+#define GK7605V100_FMC_CLK 43
+#define GK7605V100_ETH0_CLK 44
+#define GK7605V100_EDMAC_AXICLK 45
+#define GK7605V100_EDMAC_CLK 46
+#define GK7605V100_SPI0_CLK 48
+#define GK7605V100_SPI1_CLK 49
+#define GK7605V100_MMC0_CLK 50
+#define GK7605V100_MMC1_CLK 51
+#define GK7605V100_MMC2_CLK 52
+#define GK7605V100_I2C0_CLK 53
+#define GK7605V100_I2C1_CLK 54
+#define GK7605V100_I2C2_CLK 55
+#define GK7605V100_USB2_BUS_CLK 81
+#define GK7605V100_USB2_REF_CLK 82
+#define GK7605V100_USB2_UTMI_CLK 83
+#define GK7605V100_USB2_PHY_APB_CLK 84
+#define GK7605V100_USB2_PHY_PLL_CLK 85
+#define GK7605V100_USB2_PHY_XO_CLK 86
+
+#define GK7605V100_NR_CLKS 256
+#define GK7605V100_NR_RSTS 256
+
+#endif /* __DTS_GK7605V100_CLOCK_H */
diff -urN linux-4.9.37/include/kvm/arm_psci.h linux-4.9.y/include/kvm/arm_psci.h
--- linux-4.9.37/include/kvm/arm_psci.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/include/kvm/arm_psci.h 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2012 - ARM Ltd
+ * Author: Marc Zyngier <marc.zyngier@arm.com>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __KVM_ARM_PSCI_H__
+#define __KVM_ARM_PSCI_H__
+
+#include <uapi/linux/psci.h>
+
+#define KVM_ARM_PSCI_0_1 PSCI_VERSION(0, 1)
+#define KVM_ARM_PSCI_0_2 PSCI_VERSION(0, 2)
+
+int kvm_psci_version(struct kvm_vcpu *vcpu);
+int kvm_psci_call(struct kvm_vcpu *vcpu);
+
+#endif /* __KVM_ARM_PSCI_H__ */
diff -urN linux-4.9.37/include/linux/blkdev.h linux-4.9.y/include/linux/blkdev.h
--- linux-4.9.37/include/linux/blkdev.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/include/linux/blkdev.h 2021-06-07 13:01:34.000000000 +0300
@@ -1174,7 +1174,11 @@
enum blk_default_limits {
BLK_MAX_SEGMENTS = 128,
BLK_SAFE_MAX_SECTORS = 255,
+#ifndef CONFIG_GOKE_MC
BLK_DEF_MAX_SECTORS = 2560,
+#else
+ BLK_DEF_MAX_SECTORS = 8192,
+#endif
BLK_MAX_SEGMENT_SIZE = 65536,
BLK_SEG_BOUNDARY_MASK = 0xFFFFFFFFUL,
};
diff -urN linux-4.9.37/include/linux/cpuidle.h linux-4.9.y/include/linux/cpuidle.h
--- linux-4.9.37/include/linux/cpuidle.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/include/linux/cpuidle.h 2021-06-07 13:01:34.000000000 +0300
@@ -62,6 +62,7 @@
};
/* Idle State Flags */
+#define CPUIDLE_FLAG_TIME_VALID (0x01) /* is residency time measurable? */
#define CPUIDLE_FLAG_COUPLED (0x02) /* state applies to multiple cpus */
#define CPUIDLE_FLAG_TIMER_STOP (0x04) /* timer is stopped on this state */
diff -urN linux-4.9.37/include/linux/dma-mapping.h linux-4.9.y/include/linux/dma-mapping.h
--- linux-4.9.37/include/linux/dma-mapping.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/include/linux/dma-mapping.h 2021-06-07 13:01:34.000000000 +0300
@@ -705,6 +705,8 @@
/*
* Managed DMA API
*/
+void bsp_dmac_map_area(const void *kaddr, size_t size,
+ enum dma_data_direction dir);
extern void *dmam_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp);
extern void dmam_free_coherent(struct device *dev, size_t size, void *vaddr,
diff -urN linux-4.9.37/include/linux/fb.h linux-4.9.y/include/linux/fb.h
--- linux-4.9.37/include/linux/fb.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/include/linux/fb.h 2021-06-07 13:01:34.000000000 +0300
@@ -237,7 +237,14 @@
void (*deferred_io)(struct fb_info *info, struct list_head *pagelist);
};
#endif
+#ifdef CONFIG_ARCH_GOKE
+#define FBIOGET_DMABUF _IOR('F', 0x21, struct fb_dmabuf_export)
+struct fb_dmabuf_export {
+ __u32 fd;
+ __u32 flags;
+};
+#endif
/*
* Frame buffer operations
*
@@ -320,6 +327,12 @@
/* called at KDB enter and leave time to prepare the console */
int (*fb_debug_enter)(struct fb_info *info);
int (*fb_debug_leave)(struct fb_info *info);
+#ifdef CONFIG_ARCH_GOKE
+#ifdef CONFIG_DMA_SHARED_BUFFER
+ /* Export the frame buffer as a dmabuf object */
+ struct dma_buf *(*fb_dmabuf_export)(struct fb_info *info);
+#endif
+#endif
};
#ifdef CONFIG_FB_TILEBLITTING
diff -urN linux-4.9.37/include/linux/fence.h linux-4.9.y/include/linux/fence.h
--- linux-4.9.37/include/linux/fence.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/include/linux/fence.h 2021-06-07 13:01:34.000000000 +0300
@@ -108,6 +108,7 @@
* @get_driver_name: returns the driver name.
* @get_timeline_name: return the name of the context this fence belongs to.
* @enable_signaling: enable software signaling of fence.
+ * @disable_signaling: disable software signaling of fence (optional).
* @signaled: [optional] peek whether the fence is signaled, can be null.
* @wait: custom wait implementation, or fence_default_wait.
* @release: [optional] called on destruction of fence, can be null
@@ -167,6 +168,7 @@
const char * (*get_driver_name)(struct fence *fence);
const char * (*get_timeline_name)(struct fence *fence);
bool (*enable_signaling)(struct fence *fence);
+ void (*disable_signaling)(struct fence *fence);
bool (*signaled)(struct fence *fence);
signed long (*wait)(struct fence *fence, bool intr, signed long timeout);
void (*release)(struct fence *fence);
@@ -183,6 +185,16 @@
void fence_free(struct fence *fence);
/**
+ * fence_put - decreases refcount of the fence
+ * @fence: [in] fence to reduce refcount of
+ */
+static inline void fence_put(struct fence *fence)
+{
+ if (fence)
+ kref_put(&fence->refcount, fence_release);
+}
+
+/**
* fence_get - increases refcount of the fence
* @fence: [in] fence to increase refcount of
*
@@ -210,13 +222,49 @@
}
/**
- * fence_put - decreases refcount of the fence
- * @fence: [in] fence to reduce refcount of
+ * fence_get_rcu_safe - acquire a reference to an RCU tracked fence
+ * @fence: [in] pointer to fence to increase refcount of
+ *
+ * Function returns NULL if no refcount could be obtained, or the fence.
+ * This function handles acquiring a reference to a fence that may be
+ * reallocated within the RCU grace period (such as with SLAB_DESTROY_BY_RCU),
+ * so long as the caller is using RCU on the pointer to the fence.
+ *
+ * An alternative mechanism is to employ a seqlock to protect a bunch of
+ * fences, such as used by struct reservation_object. When using a seqlock,
+ * the seqlock must be taken before and checked after a reference to the
+ * fence is acquired (as shown here).
+ *
+ * The caller is required to hold the RCU read lock.
*/
-static inline void fence_put(struct fence *fence)
+static inline struct fence *fence_get_rcu_safe(struct fence * __rcu *fencep)
{
- if (fence)
- kref_put(&fence->refcount, fence_release);
+ do {
+ struct fence *fence;
+
+ fence = rcu_dereference(*fencep);
+ if (!fence || !fence_get_rcu(fence))
+ return NULL;
+
+ /* The atomic_inc_not_zero() inside fence_get_rcu()
+ * provides a full memory barrier upon success (such as now).
+ * This is paired with the write barrier from assigning
+ * to the __rcu protected fence pointer so that if that
+ * pointer still matches the current fence, we know we
+ * have successfully acquire a reference to it. If it no
+ * longer matches, we are holding a reference to some other
+ * reallocated pointer. This is possible if the allocator
+ * is using a freelist like SLAB_DESTROY_BY_RCU where the
+ * fence remains valid for the RCU grace period, but it
+ * may be reallocated. When using such allocators, we are
+ * responsible for ensuring the reference we get is to
+ * the right fence, as below.
+ */
+ if (fence == rcu_access_pointer(*fencep))
+ return rcu_pointer_handoff(fence);
+
+ fence_put(fence);
+ } while (1);
}
int fence_signal(struct fence *fence);
diff -urN linux-4.9.37/include/linux/fs.h linux-4.9.y/include/linux/fs.h
--- linux-4.9.37/include/linux/fs.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/include/linux/fs.h 2021-06-07 13:01:34.000000000 +0300
@@ -941,9 +941,9 @@
/* Page cache limit. The filesystems should put that into their s_maxbytes
limits, otherwise bad things can happen in VM. */
#if BITS_PER_LONG==32
-#define MAX_LFS_FILESIZE (((loff_t)PAGE_SIZE << (BITS_PER_LONG-1))-1)
+#define MAX_LFS_FILESIZE ((loff_t)ULONG_MAX << PAGE_SHIFT)
#elif BITS_PER_LONG==64
-#define MAX_LFS_FILESIZE ((loff_t)0x7fffffffffffffffLL)
+#define MAX_LFS_FILESIZE ((loff_t)LLONG_MAX)
#endif
#define FL_POSIX 1
diff -urN linux-4.9.37/include/linux/goke_cma.h linux-4.9.y/include/linux/goke_cma.h
--- linux-4.9.37/include/linux/goke_cma.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/include/linux/goke_cma.h 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+#ifndef __GOKE_CMA_H__
+#define __GOKE_CMA_H__
+
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/dma-contiguous.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/cma.h>
+#include <linux/memblock.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/of_reserved_mem.h>
+
+#define NAME_LEN_MAX 64
+#define ZONE_MAX 64
+
+struct cma_zone {
+ struct device pdev;
+ char name[NAME_LEN_MAX];
+ gfp_t gfp;
+ phys_addr_t phys_start;
+ phys_addr_t nbytes;
+ u32 alloc_type;
+ u32 block_align;
+};
+
+#ifdef CONFIG_CMA
+int is_cma_address(phys_addr_t phys, unsigned long size);
+phys_addr_t goke_get_zones_start(void);
+struct cma_zone *goke_get_cma_zone(const char *name);
+struct device *goke_get_cma_device(const char *name);
+int __init goke_declare_heap_memory(void);
+#endif /* CONFIG_CMA */
+
+#endif
diff -urN linux-4.9.37/include/linux/i2c.h linux-4.9.y/include/linux/i2c.h
--- linux-4.9.37/include/linux/i2c.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/include/linux/i2c.h 2021-06-07 13:01:34.000000000 +0300
@@ -68,6 +68,20 @@
*/
extern int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
int num);
+
+#ifdef CONFIG_ARCH_GOKE
+
+extern int gk_i2c_master_send(const struct i2c_client *client, const char *buf,
+ int count);
+
+extern int gk_i2c_master_recv(const struct i2c_client *client, char *buf,
+ int count);
+
+extern int gk_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
+ int num);
+
+#endif
+
/* Unlocked flavor */
extern int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
int num);
@@ -553,6 +567,9 @@
const struct i2c_lock_operations *lock_ops;
struct rt_mutex bus_lock;
struct rt_mutex mux_lock;
+#ifdef CONFIG_ARCH_GOKE
+ spinlock_t spinlock;
+#endif
int timeout; /* in jiffies */
int retries;
diff -urN linux-4.9.37/include/linux/lzma/LzFind.h linux-4.9.y/include/linux/lzma/LzFind.h
--- linux-4.9.37/include/linux/lzma/LzFind.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/include/linux/lzma/LzFind.h 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,115 @@
+/* LzFind.h -- Match finder for LZ algorithms
+2009-04-22 : Igor Pavlov : Public domain */
+
+#ifndef __LZ_FIND_H
+#define __LZ_FIND_H
+
+#include "Types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef UInt32 CLzRef;
+
+typedef struct _CMatchFinder
+{
+ Byte *buffer;
+ UInt32 pos;
+ UInt32 posLimit;
+ UInt32 streamPos;
+ UInt32 lenLimit;
+
+ UInt32 cyclicBufferPos;
+ UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */
+
+ UInt32 matchMaxLen;
+ CLzRef *hash;
+ CLzRef *son;
+ UInt32 hashMask;
+ UInt32 cutValue;
+
+ Byte *bufferBase;
+ ISeqInStream *stream;
+ int streamEndWasReached;
+
+ UInt32 blockSize;
+ UInt32 keepSizeBefore;
+ UInt32 keepSizeAfter;
+
+ UInt32 numHashBytes;
+ int directInput;
+ size_t directInputRem;
+ int btMode;
+ int bigHash;
+ UInt32 historySize;
+ UInt32 fixedHashSize;
+ UInt32 hashSizeSum;
+ UInt32 numSons;
+ SRes result;
+ UInt32 crc[256];
+} CMatchFinder;
+
+#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer)
+#define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)])
+
+#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos)
+
+int MatchFinder_NeedMove(CMatchFinder *p);
+Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p);
+void MatchFinder_MoveBlock(CMatchFinder *p);
+void MatchFinder_ReadIfRequired(CMatchFinder *p);
+
+void MatchFinder_Construct(CMatchFinder *p);
+
+/* Conditions:
+ historySize <= 3 GB
+ keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB
+*/
+int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
+ UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
+ ISzAlloc *alloc);
+void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc);
+void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems);
+void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue);
+
+UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son,
+ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
+ UInt32 *distances, UInt32 maxLen);
+
+/*
+Conditions:
+ Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func.
+ Mf_GetPointerToCurrentPos_Func's result must be used only before any other function
+*/
+
+typedef void (*Mf_Init_Func)(void *object);
+typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index);
+typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object);
+typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object);
+typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances);
+typedef void (*Mf_Skip_Func)(void *object, UInt32);
+
+typedef struct _IMatchFinder
+{
+ Mf_Init_Func Init;
+ Mf_GetIndexByte_Func GetIndexByte;
+ Mf_GetNumAvailableBytes_Func GetNumAvailableBytes;
+ Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos;
+ Mf_GetMatches_Func GetMatches;
+ Mf_Skip_Func Skip;
+} IMatchFinder;
+
+void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable);
+
+void MatchFinder_Init(CMatchFinder *p);
+UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
+UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
+void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
+void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff -urN linux-4.9.37/include/linux/lzma/LzHash.h linux-4.9.y/include/linux/lzma/LzHash.h
--- linux-4.9.37/include/linux/lzma/LzHash.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/include/linux/lzma/LzHash.h 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,54 @@
+/* LzHash.h -- HASH functions for LZ algorithms
+2009-02-07 : Igor Pavlov : Public domain */
+
+#ifndef __LZ_HASH_H
+#define __LZ_HASH_H
+
+#define kHash2Size (1 << 10)
+#define kHash3Size (1 << 16)
+#define kHash4Size (1 << 20)
+
+#define kFix3HashSize (kHash2Size)
+#define kFix4HashSize (kHash2Size + kHash3Size)
+#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size)
+
+#define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8);
+
+#define HASH3_CALC { \
+ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
+ hash2Value = temp & (kHash2Size - 1); \
+ hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; }
+
+#define HASH4_CALC { \
+ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
+ hash2Value = temp & (kHash2Size - 1); \
+ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
+ hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; }
+
+#define HASH5_CALC { \
+ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
+ hash2Value = temp & (kHash2Size - 1); \
+ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
+ hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \
+ hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \
+ hash4Value &= (kHash4Size - 1); }
+
+/* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */
+#define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF;
+
+
+#define MT_HASH2_CALC \
+ hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1);
+
+#define MT_HASH3_CALC { \
+ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
+ hash2Value = temp & (kHash2Size - 1); \
+ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); }
+
+#define MT_HASH4_CALC { \
+ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
+ hash2Value = temp & (kHash2Size - 1); \
+ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
+ hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); }
+
+#endif
diff -urN linux-4.9.37/include/linux/lzma/LzmaDec.h linux-4.9.y/include/linux/lzma/LzmaDec.h
--- linux-4.9.37/include/linux/lzma/LzmaDec.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/include/linux/lzma/LzmaDec.h 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,231 @@
+/* LzmaDec.h -- LZMA Decoder
+2009-02-07 : Igor Pavlov : Public domain */
+
+#ifndef __LZMA_DEC_H
+#define __LZMA_DEC_H
+
+#include "Types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* #define _LZMA_PROB32 */
+/* _LZMA_PROB32 can increase the speed on some CPUs,
+ but memory usage for CLzmaDec::probs will be doubled in that case */
+
+#ifdef _LZMA_PROB32
+#define CLzmaProb UInt32
+#else
+#define CLzmaProb UInt16
+#endif
+
+
+/* ---------- LZMA Properties ---------- */
+
+#define LZMA_PROPS_SIZE 5
+
+typedef struct _CLzmaProps
+{
+ unsigned lc, lp, pb;
+ UInt32 dicSize;
+} CLzmaProps;
+
+/* LzmaProps_Decode - decodes properties
+Returns:
+ SZ_OK
+ SZ_ERROR_UNSUPPORTED - Unsupported properties
+*/
+
+SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size);
+
+
+/* ---------- LZMA Decoder state ---------- */
+
+/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case.
+ Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */
+
+#define LZMA_REQUIRED_INPUT_MAX 20
+
+typedef struct
+{
+ CLzmaProps prop;
+ CLzmaProb *probs;
+ Byte *dic;
+ const Byte *buf;
+ UInt32 range, code;
+ SizeT dicPos;
+ SizeT dicBufSize;
+ UInt32 processedPos;
+ UInt32 checkDicSize;
+ unsigned state;
+ UInt32 reps[4];
+ unsigned remainLen;
+ int needFlush;
+ int needInitState;
+ UInt32 numProbs;
+ unsigned tempBufSize;
+ Byte tempBuf[LZMA_REQUIRED_INPUT_MAX];
+} CLzmaDec;
+
+#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; }
+
+void LzmaDec_Init(CLzmaDec *p);
+
+/* There are two types of LZMA streams:
+ 0) Stream with end mark. That end mark adds about 6 bytes to compressed size.
+ 1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */
+
+typedef enum
+{
+ LZMA_FINISH_ANY, /* finish at any point */
+ LZMA_FINISH_END /* block must be finished at the end */
+} ELzmaFinishMode;
+
+/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!!
+
+ You must use LZMA_FINISH_END, when you know that current output buffer
+ covers last bytes of block. In other cases you must use LZMA_FINISH_ANY.
+
+ If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK,
+ and output value of destLen will be less than output buffer size limit.
+ You can check status result also.
+
+ You can use multiple checks to test data integrity after full decompression:
+ 1) Check Result and "status" variable.
+ 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.
+ 3) Check that output(srcLen) = compressedSize, if you know real compressedSize.
+ You must use correct finish mode in that case. */
+
+typedef enum
+{
+ LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */
+ LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */
+ LZMA_STATUS_NOT_FINISHED, /* stream was not finished */
+ LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */
+ LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */
+} ELzmaStatus;
+
+/* ELzmaStatus is used only as output value for function call */
+
+
+/* ---------- Interfaces ---------- */
+
+/* There are 3 levels of interfaces:
+ 1) Dictionary Interface
+ 2) Buffer Interface
+ 3) One Call Interface
+ You can select any of these interfaces, but don't mix functions from different
+ groups for same object. */
+
+
+/* There are two variants to allocate state for Dictionary Interface:
+ 1) LzmaDec_Allocate / LzmaDec_Free
+ 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs
+ You can use variant 2, if you set dictionary buffer manually.
+ For Buffer Interface you must always use variant 1.
+
+LzmaDec_Allocate* can return:
+ SZ_OK
+ SZ_ERROR_MEM - Memory allocation error
+ SZ_ERROR_UNSUPPORTED - Unsupported properties
+*/
+
+SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc);
+void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc);
+
+SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc);
+void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc);
+
+/* ---------- Dictionary Interface ---------- */
+
+/* You can use it, if you want to eliminate the overhead for data copying from
+ dictionary to some other external buffer.
+ You must work with CLzmaDec variables directly in this interface.
+
+ STEPS:
+ LzmaDec_Constr()
+ LzmaDec_Allocate()
+ for (each new stream)
+ {
+ LzmaDec_Init()
+ while (it needs more decompression)
+ {
+ LzmaDec_DecodeToDic()
+ use data from CLzmaDec::dic and update CLzmaDec::dicPos
+ }
+ }
+ LzmaDec_Free()
+*/
+
+/* LzmaDec_DecodeToDic
+
+ The decoding to internal dictionary buffer (CLzmaDec::dic).
+ You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!!
+
+finishMode:
+ It has meaning only if the decoding reaches output limit (dicLimit).
+ LZMA_FINISH_ANY - Decode just dicLimit bytes.
+ LZMA_FINISH_END - Stream must be finished after dicLimit.
+
+Returns:
+ SZ_OK
+ status:
+ LZMA_STATUS_FINISHED_WITH_MARK
+ LZMA_STATUS_NOT_FINISHED
+ LZMA_STATUS_NEEDS_MORE_INPUT
+ LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
+ SZ_ERROR_DATA - Data error
+*/
+
+SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit,
+ const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
+
+
+/* ---------- Buffer Interface ---------- */
+
+/* It's zlib-like interface.
+ See LzmaDec_DecodeToDic description for information about STEPS and return results,
+ but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need
+ to work with CLzmaDec variables manually.
+
+finishMode:
+ It has meaning only if the decoding reaches output limit (*destLen).
+ LZMA_FINISH_ANY - Decode just destLen bytes.
+ LZMA_FINISH_END - Stream must be finished after (*destLen).
+*/
+
+SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen,
+ const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
+
+
+/* ---------- One Call Interface ---------- */
+
+/* LzmaDecode
+
+finishMode:
+ It has meaning only if the decoding reaches output limit (*destLen).
+ LZMA_FINISH_ANY - Decode just destLen bytes.
+ LZMA_FINISH_END - Stream must be finished after (*destLen).
+
+Returns:
+ SZ_OK
+ status:
+ LZMA_STATUS_FINISHED_WITH_MARK
+ LZMA_STATUS_NOT_FINISHED
+ LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
+ SZ_ERROR_DATA - Data error
+ SZ_ERROR_MEM - Memory allocation error
+ SZ_ERROR_UNSUPPORTED - Unsupported properties
+ SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
+*/
+
+SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
+ const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
+ ELzmaStatus *status, ISzAlloc *alloc);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff -urN linux-4.9.37/include/linux/lzma/LzmaEnc.h linux-4.9.y/include/linux/lzma/LzmaEnc.h
--- linux-4.9.37/include/linux/lzma/LzmaEnc.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/include/linux/lzma/LzmaEnc.h 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,80 @@
+/* LzmaEnc.h -- LZMA Encoder
+2009-02-07 : Igor Pavlov : Public domain */
+
+#ifndef __LZMA_ENC_H
+#define __LZMA_ENC_H
+
+#include "Types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LZMA_PROPS_SIZE 5
+
+typedef struct _CLzmaEncProps
+{
+ int level; /* 0 <= level <= 9 */
+ UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version
+ (1 << 12) <= dictSize <= (1 << 30) for 64-bit version
+ default = (1 << 24) */
+ int lc; /* 0 <= lc <= 8, default = 3 */
+ int lp; /* 0 <= lp <= 4, default = 0 */
+ int pb; /* 0 <= pb <= 4, default = 2 */
+ int algo; /* 0 - fast, 1 - normal, default = 1 */
+ int fb; /* 5 <= fb <= 273, default = 32 */
+ int btMode; /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */
+ int numHashBytes; /* 2, 3 or 4, default = 4 */
+ UInt32 mc; /* 1 <= mc <= (1 << 30), default = 32 */
+ unsigned writeEndMark; /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */
+ int numThreads; /* 1 or 2, default = 2 */
+} CLzmaEncProps;
+
+void LzmaEncProps_Init(CLzmaEncProps *p);
+void LzmaEncProps_Normalize(CLzmaEncProps *p);
+UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2);
+
+
+/* ---------- CLzmaEncHandle Interface ---------- */
+
+/* LzmaEnc_* functions can return the following exit codes:
+Returns:
+ SZ_OK - OK
+ SZ_ERROR_MEM - Memory allocation error
+ SZ_ERROR_PARAM - Incorrect paramater in props
+ SZ_ERROR_WRITE - Write callback error.
+ SZ_ERROR_PROGRESS - some break from progress callback
+ SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
+*/
+
+typedef void * CLzmaEncHandle;
+
+CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc);
+void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig);
+SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props);
+SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size);
+SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream,
+ ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
+SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
+ int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
+
+/* ---------- One Call Interface ---------- */
+
+/* LzmaEncode
+Return code:
+ SZ_OK - OK
+ SZ_ERROR_MEM - Memory allocation error
+ SZ_ERROR_PARAM - Incorrect paramater
+ SZ_ERROR_OUTPUT_EOF - output buffer overflow
+ SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
+*/
+
+SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
+ const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
+ ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff -urN linux-4.9.37/include/linux/lzma/Types.h linux-4.9.y/include/linux/lzma/Types.h
--- linux-4.9.37/include/linux/lzma/Types.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/include/linux/lzma/Types.h 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,226 @@
+/* Types.h -- Basic types
+2009-11-23 : Igor Pavlov : Public domain */
+
+#ifndef __7Z_TYPES_H
+#define __7Z_TYPES_H
+
+#include <stddef.h>
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#ifndef EXTERN_C_BEGIN
+#ifdef __cplusplus
+#define EXTERN_C_BEGIN extern "C" {
+#define EXTERN_C_END }
+#else
+#define EXTERN_C_BEGIN
+#define EXTERN_C_END
+#endif
+#endif
+
+EXTERN_C_BEGIN
+
+#define SZ_OK 0
+
+#define SZ_ERROR_DATA 1
+#define SZ_ERROR_MEM 2
+#define SZ_ERROR_CRC 3
+#define SZ_ERROR_UNSUPPORTED 4
+#define SZ_ERROR_PARAM 5
+#define SZ_ERROR_INPUT_EOF 6
+#define SZ_ERROR_OUTPUT_EOF 7
+#define SZ_ERROR_READ 8
+#define SZ_ERROR_WRITE 9
+#define SZ_ERROR_PROGRESS 10
+#define SZ_ERROR_FAIL 11
+#define SZ_ERROR_THREAD 12
+
+#define SZ_ERROR_ARCHIVE 16
+#define SZ_ERROR_NO_ARCHIVE 17
+
+typedef int SRes;
+
+#ifdef _WIN32
+typedef DWORD WRes;
+#else
+typedef int WRes;
+#endif
+
+#ifndef RINOK
+#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; }
+#endif
+
+typedef unsigned char Byte;
+typedef short Int16;
+typedef unsigned short UInt16;
+
+#ifdef _LZMA_UINT32_IS_ULONG
+typedef long Int32;
+typedef unsigned long UInt32;
+#else
+typedef int Int32;
+typedef unsigned int UInt32;
+#endif
+
+#ifdef _SZ_NO_INT_64
+
+/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers.
+ NOTES: Some code will work incorrectly in that case! */
+
+typedef long Int64;
+typedef unsigned long UInt64;
+
+#else
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+typedef __int64 Int64;
+typedef unsigned __int64 UInt64;
+#else
+typedef long long int Int64;
+typedef unsigned long long int UInt64;
+#endif
+
+#endif
+
+#ifdef _LZMA_NO_SYSTEM_SIZE_T
+typedef UInt32 SizeT;
+#else
+typedef size_t SizeT;
+#endif
+
+typedef int Bool;
+#define True 1
+#define False 0
+
+
+#ifdef _WIN32
+#define MY_STD_CALL __stdcall
+#else
+#define MY_STD_CALL
+#endif
+
+#ifdef _MSC_VER
+
+#if _MSC_VER >= 1300
+#define MY_NO_INLINE __declspec(noinline)
+#else
+#define MY_NO_INLINE
+#endif
+
+#define MY_CDECL __cdecl
+#define MY_FAST_CALL __fastcall
+
+#else
+
+#define MY_CDECL
+#define MY_FAST_CALL
+
+#endif
+
+
+/* The following interfaces use first parameter as pointer to structure */
+
+typedef struct
+{
+ SRes (*Read)(void *p, void *buf, size_t *size);
+ /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
+ (output(*size) < input(*size)) is allowed */
+} ISeqInStream;
+
+/* it can return SZ_ERROR_INPUT_EOF */
+SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size);
+SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType);
+SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf);
+
+typedef struct
+{
+ size_t (*Write)(void *p, const void *buf, size_t size);
+ /* Returns: result - the number of actually written bytes.
+ (result < size) means error */
+} ISeqOutStream;
+
+typedef enum
+{
+ SZ_SEEK_SET = 0,
+ SZ_SEEK_CUR = 1,
+ SZ_SEEK_END = 2
+} ESzSeek;
+
+typedef struct
+{
+ SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */
+ SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
+} ISeekInStream;
+
+typedef struct
+{
+ SRes (*Look)(void *p, void **buf, size_t *size);
+ /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
+ (output(*size) > input(*size)) is not allowed
+ (output(*size) < input(*size)) is allowed */
+ SRes (*Skip)(void *p, size_t offset);
+ /* offset must be <= output(*size) of Look */
+
+ SRes (*Read)(void *p, void *buf, size_t *size);
+ /* reads directly (without buffer). It's same as ISeqInStream::Read */
+ SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
+} ILookInStream;
+
+SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size);
+SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset);
+
+/* reads via ILookInStream::Read */
+SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType);
+SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size);
+
+#define LookToRead_BUF_SIZE (1 << 14)
+
+typedef struct
+{
+ ILookInStream s;
+ ISeekInStream *realStream;
+ size_t pos;
+ size_t size;
+ Byte buf[LookToRead_BUF_SIZE];
+} CLookToRead;
+
+void LookToRead_CreateVTable(CLookToRead *p, int lookahead);
+void LookToRead_Init(CLookToRead *p);
+
+typedef struct
+{
+ ISeqInStream s;
+ ILookInStream *realStream;
+} CSecToLook;
+
+void SecToLook_CreateVTable(CSecToLook *p);
+
+typedef struct
+{
+ ISeqInStream s;
+ ILookInStream *realStream;
+} CSecToRead;
+
+void SecToRead_CreateVTable(CSecToRead *p);
+
+typedef struct
+{
+ SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize);
+ /* Returns: result. (result != SZ_OK) means break.
+ Value (UInt64)(Int64)-1 for size means unknown value. */
+} ICompressProgress;
+
+typedef struct
+{
+ void *(*Alloc)(void *p, size_t size);
+ void (*Free)(void *p, void *address); /* address can be 0 */
+} ISzAlloc;
+
+#define IAlloc_Alloc(p, size) (p)->Alloc((p), size)
+#define IAlloc_Free(p, a) (p)->Free((p), a)
+
+EXTERN_C_END
+
+#endif
diff -urN linux-4.9.37/include/linux/lzma.h linux-4.9.y/include/linux/lzma.h
--- linux-4.9.37/include/linux/lzma.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/include/linux/lzma.h 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,62 @@
+#ifndef __LZMA_H__
+#define __LZMA_H__
+
+#ifdef __KERNEL__
+ #include <linux/kernel.h>
+ #include <linux/sched.h>
+ #include <linux/slab.h>
+ #include <linux/vmalloc.h>
+ #include <linux/init.h>
+ #define LZMA_MALLOC vmalloc
+ #define LZMA_FREE vfree
+ #define PRINT_ERROR(msg) printk(KERN_WARNING #msg)
+ #define INIT __init
+ #define STATIC static
+#else
+ #include <stdint.h>
+ #include <stdlib.h>
+ #include <stdio.h>
+ #include <unistd.h>
+ #include <string.h>
+ #include <asm/types.h>
+ #include <errno.h>
+ #include <linux/jffs2.h>
+ #ifndef PAGE_SIZE
+ extern int page_size;
+ #define PAGE_SIZE page_size
+ #endif
+ #define LZMA_MALLOC malloc
+ #define LZMA_FREE free
+ #define PRINT_ERROR(msg) fprintf(stderr, msg)
+ #define INIT
+ #define STATIC
+#endif
+
+#include "lzma/LzmaDec.h"
+#include "lzma/LzmaEnc.h"
+
+#define LZMA_BEST_LEVEL (9)
+#define LZMA_BEST_LC (0)
+#define LZMA_BEST_LP (0)
+#define LZMA_BEST_PB (0)
+#define LZMA_BEST_FB (273)
+
+#define LZMA_BEST_DICT(n) (((int)((n) / 2)) * 2)
+
+static void *p_lzma_malloc(void *p, size_t size)
+{
+ if (size == 0)
+ return NULL;
+
+ return LZMA_MALLOC(size);
+}
+
+static void p_lzma_free(void *p, void *address)
+{
+ if (address != NULL)
+ LZMA_FREE(address);
+}
+
+static ISzAlloc lzma_alloc = {p_lzma_malloc, p_lzma_free};
+
+#endif
diff -urN linux-4.9.37/include/linux/mfd/goke_fmc.h linux-4.9.y/include/linux/mfd/goke_fmc.h
--- linux-4.9.37/include/linux/mfd/goke_fmc.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/include/linux/mfd/goke_fmc.h 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,515 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#ifndef __BSP_FMC_H
+#define __BSP_FMC_H
+
+#include <linux/compiler.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
+#include <linux/bitops.h>
+
+/*****************************************************************************/
+#define _512B (512)
+#define _1K (1024)
+#define _2K (2048)
+#define _4K (4096)
+#define _8K (8192)
+#define _16K (16384)
+#define _32K (32768)
+#define _64K (0x10000UL)
+#define _128K (0x20000UL)
+#define _256K (0x40000UL)
+#define _512K (0x80000UL)
+#define _1M (0x100000UL)
+#define _2M (0x200000UL)
+#define _4M (0x400000UL)
+#define _8M (0x800000UL)
+#define _16M (0x1000000UL)
+#define _32M (0x2000000UL)
+#define _64M (0x4000000UL)
+#define _128M (0x8000000UL)
+#define _256M (0x10000000UL)
+#define _512M (0x20000000UL)
+#define _1G (0x40000000ULL)
+#define _2G (0x80000000ULL)
+#define _4G (0x100000000ULL)
+#define _8G (0x200000000ULL)
+#define _16G (0x400000000ULL)
+#define _64G (0x1000000000ULL)
+
+/*****************************************************************************/
+/* FMC REG MAP */
+/*****************************************************************************/
+#define FMC_CFG 0x00
+#define FMC_CFG_SPI_NAND_SEL(_type) (((_size) & 0x3) << 11)
+#define SPI_NOR_ADDR_MODE BIT(10)
+#define FMC_CFG_OP_MODE_MASK BIT_MASK(0)
+#define FMC_CFG_OP_MODE_BOOT 0
+#define FMC_CFG_OP_MODE_NORMAL 1
+#define SPI_NOR_ADDR_MODE_3BYTES (0x0 << 10)
+#define SPI_NOR_ADDR_MODE_4BYTES (0x1 << 10)
+
+#define FMC_CFG_BLOCK_SIZE(_size) (((_size) & 0x3) << 8)
+#define FMC_CFG_ECC_TYPE(_type) (((_type) & 0x7) << 5)
+#define FMC_CFG_PAGE_SIZE(_size) (((_size) & 0x3) << 3)
+#define FMC_CFG_FLASH_SEL(_type) (((_type) & 0x3) << 1)
+#define FMC_CFG_OP_MODE(_mode) ((_mode) & 0x1)
+
+#define SPI_NAND_MFR_OTHER 0x0
+#define SPI_NAND_MFR_WINBOND 0x1
+#define SPI_NAND_MFR_ESMT 0x2
+#define SPI_NAND_MFR_MICRON 0x3
+
+#define SPI_NAND_SEL_SHIFT 11
+#define SPI_NAND_SEL_MASK (0x3 << SPI_NAND_SEL_SHIFT)
+
+#define SPI_NOR_ADDR_MODE_3_BYTES 0x0
+#define SPI_NOR_ADDR_MODE_4_BYTES 0x1
+
+#define SPI_NOR_ADDR_MODE_SHIFT 10
+#define SPI_NOR_ADDR_MODE_MASK (0x1 << SPI_NOR_ADDR_MODE_SHIFT)
+
+#define BLOCK_SIZE_64_PAGE 0x0
+#define BLOCK_SIZE_128_PAGE 0x1
+#define BLOCK_SIZE_256_PAGE 0x2
+#define BLOCK_SIZE_512_PAGE 0x3
+
+#define BLOCK_SIZE_MASK (0x3 << 8)
+
+#define ECC_TYPE_0BIT 0x0
+#define ECC_TYPE_8BIT 0x1
+#define ECC_TYPE_16BIT 0x2
+#define ECC_TYPE_24BIT 0x3
+#define ECC_TYPE_28BIT 0x4
+#define ECC_TYPE_40BIT 0x5
+#define ECC_TYPE_64BIT 0x6
+
+#define ECC_TYPE_SHIFT 5
+#define ECC_TYPE_MASK (0x7 << ECC_TYPE_SHIFT)
+
+#define PAGE_SIZE_2KB 0x0
+#define PAGE_SIZE_4KB 0x1
+#define PAGE_SIZE_8KB 0x2
+#define PAGE_SIZE_16KB 0x3
+
+#define PAGE_SIZE_SHIFT 3
+#define PAGE_SIZE_MASK (0x3 << PAGE_SIZE_SHIFT)
+
+#define FLASH_TYPE_SPI_NOR 0x0
+#define FLASH_TYPE_SPI_NAND 0x1
+#define FLASH_TYPE_NAND 0x2
+#define FLASH_TYPE_UNKNOWN 0x3
+
+#define FLASH_TYPE_SEL_MASK (0x3 << 1)
+#define GET_SPI_FLASH_TYPE(_reg) (((_reg) >> 1) & 0x3)
+
+/*****************************************************************************/
+#define FMC_GLOBAL_CFG 0x04
+#define FMC_GLOBAL_CFG_WP_ENABLE BIT(6)
+#define FMC_GLOBAL_CFG_RANDOMIZER_EN (1 << 2)
+#define FLASH_TYPE_SEL_MASK (0x3 << 1)
+#define FMC_CFG_FLASH_SEL(_type) (((_type) & 0x3) << 1)
+
+#define FMC_GLOBAL_CFG_DTR_MODE BIT(11)
+/*****************************************************************************/
+#define FMC_SPI_TIMING_CFG 0x08
+#define TIMING_CFG_TCSH(nr) (((nr) & 0xf) << 8)
+#define TIMING_CFG_TCSS(nr) (((nr) & 0xf) << 4)
+#define TIMING_CFG_TSHSL(nr) ((nr) & 0xf)
+
+#define CS_HOLD_TIME 0x6
+#define CS_SETUP_TIME 0x6
+#define CS_DESELECT_TIME 0xf
+
+/*****************************************************************************/
+#define FMC_PND_PWIDTH_CFG 0x0c
+#define PWIDTH_CFG_RW_HCNT(_n) (((_n) & 0xf) << 8)
+#define PWIDTH_CFG_R_LCNT(_n) (((_n) & 0xf) << 4)
+#define PWIDTH_CFG_W_LCNT(_n) ((_n) & 0xf)
+
+#define RW_H_WIDTH (0xa)
+#define R_L_WIDTH (0xa)
+#define W_L_WIDTH (0xa)
+
+/*****************************************************************************/
+#define FMC_INT 0x18
+#define FMC_INT_AHB_OP BIT(7)
+#define FMC_INT_WR_LOCK BIT(6)
+#define FMC_INT_DMA_ERR BIT(5)
+#define FMC_INT_ERR_ALARM BIT(4)
+#define FMC_INT_ERR_INVALID BIT(3)
+#define FMC_INT_ERR_INVALID_MASK (0x8)
+#define FMC_INT_ERR_VALID BIT(2)
+#define FMC_INT_ERR_VALID_MASK (0x4)
+#define FMC_INT_OP_FAIL BIT(1)
+#define FMC_INT_OP_DONE BIT(0)
+
+/*****************************************************************************/
+#define FMC_INT_EN 0x1c
+#define FMC_INT_EN_AHB_OP BIT(7)
+#define FMC_INT_EN_WR_LOCK BIT(6)
+#define FMC_INT_EN_DMA_ERR BIT(5)
+#define FMC_INT_EN_ERR_ALARM BIT(4)
+#define FMC_INT_EN_ERR_INVALID BIT(3)
+#define FMC_INT_EN_ERR_VALID BIT(2)
+#define FMC_INT_EN_OP_FAIL BIT(1)
+#define FMC_INT_EN_OP_DONE BIT(0)
+
+/*****************************************************************************/
+#define FMC_INT_CLR 0x20
+#define FMC_INT_CLR_AHB_OP BIT(7)
+#define FMC_INT_CLR_WR_LOCK BIT(6)
+#define FMC_INT_CLR_DMA_ERR BIT(5)
+#define FMC_INT_CLR_ERR_ALARM BIT(4)
+#define FMC_INT_CLR_ERR_INVALID BIT(3)
+#define FMC_INT_CLR_ERR_VALID BIT(2)
+#define FMC_INT_CLR_OP_FAIL BIT(1)
+#define FMC_INT_CLR_OP_DONE BIT(0)
+
+#define FMC_INT_CLR_ALL 0xff
+
+/*****************************************************************************/
+#define FMC_CMD 0x24
+#define FMC_CMD_CMD2(_cmd) (((_cmd) & 0xff) << 8)
+#define FMC_CMD_CMD1(_cmd) ((_cmd) & 0xff)
+
+/*****************************************************************************/
+#define FMC_ADDRH 0x28
+#define FMC_ADDRH_SET(_addr) ((_addr) & 0xff)
+
+/*****************************************************************************/
+#define FMC_ADDRL 0x2c
+#define FMC_ADDRL_BLOCK_MASK(_page) ((_page) & 0xffffffc0)
+#define FMC_ADDRL_BLOCK_H_MASK(_page) (((_page) & 0xffff) << 16)
+#define FMC_ADDRL_BLOCK_L_MASK(_page) ((_page) & 0xffc0)
+
+#define READ_ID_ADDR 0x00
+#define PROTECT_ADDR 0xa0
+#define FEATURE_ADDR 0xb0
+#define STATUS_ADDR 0xc0
+/*****************************************************************************/
+#define FMC_OP_CFG 0x30
+#define OP_CFG_FM_CS(_cs) ((_cs) << 11)
+#define OP_CFG_FORCE_CS_EN(_en) ((_en) << 10)
+#define OP_CFG_MEM_IF_TYPE(_type) (((_type) & 0x7) << 7)
+#define OP_CFG_ADDR_NUM(_addr) (((_addr) & 0x7) << 4)
+#define OP_CFG_DUMMY_NUM(_dummy) ((_dummy) & 0xf)
+#define OP_CFG_OEN_EN (0x1 << 13)
+
+#define IF_TYPE_SHIFT 7
+#define IF_TYPE_MASK (0x7 << IF_TYPE_SHIFT)
+
+#define READ_ID_ADDR_NUM 1
+#define FEATURES_OP_ADDR_NUM 1
+#define STD_OP_ADDR_NUM 3
+
+/*****************************************************************************/
+#define FMC_SPI_OP_ADDR 0x34
+
+/*****************************************************************************/
+#define FMC_DATA_NUM 0x38
+#define FMC_DATA_NUM_CNT(_n) ((_n) & 0x3fff)
+
+#define SPI_NOR_SR_LEN 1 /* Status Register length */
+#define SPI_NOR_CR_LEN 1 /* Config Register length */
+#define FEATURES_DATA_LEN 1
+#define READ_OOB_BB_LEN 1
+
+#define PROTECT_BRWD_MASK BIT(7)
+#define PROTECT_BP3_MASK BIT(6)
+#define PROTECT_BP2_MASK BIT(5)
+#define PROTECT_BP1_MASK BIT(4)
+#define PROTECT_BP0_MASK BIT(3)
+
+#define ANY_BP_ENABLE(_val) ((PROTECT_BP3_MASK & _val) \
+ || (PROTECT_BP2_MASK & _val) \
+ || (PROTECT_BP1_MASK & _val) \
+ || (PROTECT_BP0_MASK & _val))
+
+#define ALL_BP_MASK (PROTECT_BP3_MASK \
+ | PROTECT_BP2_MASK \
+ | PROTECT_BP1_MASK \
+ | PROTECT_BP0_MASK)
+
+#define FEATURE_ECC_ENABLE (1 << 4)
+#define FEATURE_QE_ENABLE (1 << 0)
+
+/*****************************************************************************/
+#define FMC_OP 0x3c
+#define FMC_OP_DUMMY_EN BIT(8)
+#define FMC_OP_CMD1_EN BIT(7)
+#define FMC_OP_ADDR_EN BIT(6)
+#define FMC_OP_WRITE_DATA_EN BIT(5)
+#define FMC_OP_CMD2_EN BIT(4)
+#define FMC_OP_WAIT_READY_EN BIT(3)
+#define FMC_OP_READ_DATA_EN BIT(2)
+#define FMC_OP_READ_STATUS_EN BIT(1)
+#define FMC_OP_REG_OP_START BIT(0)
+
+/*****************************************************************************/
+#define FMC_DMA_LEN 0x40
+#define FMC_DMA_LEN_SET(_len) ((_len) & 0x0fffffff)
+
+/*****************************************************************************/
+#define FMC_DMA_AHB_CTRL 0x48
+#define FMC_DMA_AHB_CTRL_DMA_PP_EN BIT(3)
+#define FMC_DMA_AHB_CTRL_BURST16_EN BIT(2)
+#define FMC_DMA_AHB_CTRL_BURST8_EN BIT(1)
+#define FMC_DMA_AHB_CTRL_BURST4_EN BIT(0)
+
+#define ALL_BURST_ENABLE (FMC_DMA_AHB_CTRL_BURST16_EN \
+ | FMC_DMA_AHB_CTRL_BURST8_EN \
+ | FMC_DMA_AHB_CTRL_BURST4_EN)
+
+#define FMC_DMA_ADDR_OFFSET 4096
+
+/*****************************************************************************/
+#define FMC_DMA_SADDR_D0 0x4c
+
+/*****************************************************************************/
+#define FMC_DMA_SADDR_D1 0x50
+
+/*****************************************************************************/
+#define FMC_DMA_SADDR_D2 0x54
+
+/*****************************************************************************/
+#define FMC_DMA_SADDR_D3 0x58
+
+/*****************************************************************************/
+#define FMC_DMA_SADDR_OOB 0x5c
+
+#ifdef CONFIG_64BIT
+/*****************************************************************************/
+#define FMC_DMA_SADDRH_D0 0x200
+#define FMC_DMA_SADDRH_SHIFT 0x3LL
+#define FMC_DMA_SADDRH_MASK (FMC_DMA_SADDRH_SHIFT << 32)
+
+/*****************************************************************************/
+#define FMC_DMA_SADDRH_OOB 0x210
+#endif
+
+/*****************************************************************************/
+#define FMC_DMA_BLK_SADDR 0x60
+#define FMC_DMA_BLK_SADDR_SET(_addr) ((_addr) & 0xffffff)
+
+/*****************************************************************************/
+#define FMC_DMA_BLK_LEN 0x64
+#define FMC_DMA_BLK_LEN_SET(_len) ((_len) & 0xffff)
+
+/*****************************************************************************/
+#define FMC_OP_CTRL 0x68
+#define OP_CTRL_RD_OPCODE(code) (((code) & 0xff) << 16)
+#define OP_CTRL_WR_OPCODE(code) (((code) & 0xff) << 8)
+#define OP_CTRL_RD_OP_SEL(_op) (((_op) & 0x3) << 4)
+#define OP_CTRL_DMA_OP(_type) ((_type) << 2)
+#define OP_CTRL_RW_OP(op) ((op) << 1)
+#define OP_CTRL_DMA_OP_READY BIT(0)
+
+#define RD_OP_READ_ALL_PAGE 0x0
+#define RD_OP_READ_OOB 0x1
+#define RD_OP_BLOCK_READ 0x2
+
+#define RD_OP_SHIFT 4
+#define RD_OP_MASK (0x3 << RD_OP_SHIFT)
+
+#define OP_TYPE_DMA 0x0
+#define OP_TYPE_REG 0x1
+
+#define FMC_OP_READ 0x0
+#define FMC_OP_WRITE 0x1
+#define RW_OP_READ 0x0
+#define RW_OP_WRITE 0x1
+
+/*****************************************************************************/
+#define FMC_OP_PARA 0x70
+#define FMC_OP_PARA_RD_OOB_ONLY BIT(1)
+
+/*****************************************************************************/
+#define FMC_BOOT_SET 0x74
+#define FMC_BOOT_SET_DEVICE_ECC_EN BIT(3)
+#define FMC_BOOT_SET_BOOT_QUAD_EN BIT(1)
+
+/*****************************************************************************/
+#define FMC_STATUS 0xac
+
+/*****************************************************************************/
+#ifndef FMC_VERSION
+#define FMC_VERSION 0xbc
+#endif
+
+/* fmc IP version */
+#ifndef FMC_VER_100
+#define FMC_VER_100 (0x100)
+#endif
+
+/*****************************************************************************/
+/* DMA address align with 32 bytes. */
+#define FMC_DMA_ALIGN 32
+
+#define FMC_CHIP_DELAY 25
+/*****************************************************************************/
+#define FMC_ECC_ERR_NUM0_BUF0 0xc0
+#define GET_ECC_ERR_NUM(_i, _reg) (((_reg) >> ((_i) * 8)) & 0xff)
+
+#define DISABLE 0
+#define ENABLE 1
+
+/*****************************************************************************/
+#define FMC_REG_ADDRESS_LEN 0x200
+
+/*****************************************************************************/
+#define FMC_MAX_READY_WAIT_JIFFIES (HZ)
+
+#define MAX_SPI_NOR_ID_LEN 8
+#define MAX_NAND_ID_LEN 8
+#define MAX_SPI_NAND_ID_LEN 3
+
+#define GET_OP 0
+#define SET_OP 1
+
+#define STATUS_ECC_MASK (0x3 << 4)
+#define STATUS_P_FAIL_MASK (1 << 3)
+#define STATUS_E_FAIL_MASK (1 << 2)
+#define STATUS_WEL_MASK (1 << 1)
+#define STATUS_OIP_MASK (1 << 0)
+
+/*****************************************************************************/
+#define FMC_VERSION 0xbc
+
+/* fmc IP version */
+#define FMC_VER_100 (0x100)
+
+#define CONFIG_SPI_NAND_MAX_CHIP_NUM (1)
+
+#define CONFIG_FMC100_MAX_NAND_CHIP (1)
+
+/*****************************************************************************/
+#define GET_PAGE_INDEX(host) \
+ ((host->addr_value[0] >> 16) | (host->addr_value[1] << 16))
+/*****************************************************************************/
+#define FMC_MAX_CHIP_NUM 2
+
+extern unsigned char fmc_cs_user[];
+
+/*****************************************************************************/
+#define fmc_readl(_host, _reg) \
+ (readl((char *)_host->regbase + (_reg)))
+
+#define fmc_readb( _addr) \
+ (readb((void __iomem *)(_addr)))
+
+#define fmc_readw( _addr) \
+ (readw((void __iomem *)(_addr)))
+
+#define fmc_writel(_host, _reg, _value) \
+ (writel((u_int)(_value), ((char *)_host->regbase + (_reg))))
+
+#define fmc_writeb(_val, _addr) \
+ (writeb((u_int)(_val), ((char *)_addr)))
+
+/*****************************************************************************/
+#define FMC_WAIT_TIMEOUT 0x2000000
+
+#define FMC_CMD_WAIT_CPU_FINISH(_host) \
+ do { \
+ unsigned regval, timeout = FMC_WAIT_TIMEOUT * 2; \
+ do { \
+ regval = fmc_readl((_host), FMC_OP); \
+ --timeout; \
+ } while ((regval & FMC_OP_REG_OP_START) && timeout); \
+ if (!timeout) \
+ pr_info("Error: Wait cmd cpu finish timeout!\n"); \
+ } while (0)
+
+/*****************************************************************************/
+#define FMC_DMA_WAIT_INT_FINISH(_host) \
+ do { \
+ unsigned regval, timeout = FMC_WAIT_TIMEOUT; \
+ do { \
+ regval = fmc_readl((_host), FMC_INT); \
+ --timeout; \
+ } while ((!(regval & FMC_INT_OP_DONE) && timeout)); \
+ if (!timeout) \
+ pr_info("Error: Wait dma int finish timeout!\n"); \
+ } while (0)
+
+/*****************************************************************************/
+#define FMC_DMA_WAIT_CPU_FINISH(_host) \
+ do { \
+ unsigned regval, timeout = FMC_WAIT_TIMEOUT; \
+ do { \
+ regval = fmc_readl((_host), FMC_OP_CTRL); \
+ --timeout; \
+ } while ((regval & OP_CTRL_DMA_OP_READY) && timeout); \
+ if (!timeout) \
+ pr_info("Error: Wait dma cpu finish timeout!\n"); \
+ } while (0)
+
+/*****************************************************************************/
+#define BT_DBG 0 /* Boot init debug print */
+#define ER_DBG 0 /* Erase debug print */
+#define WR_DBG 0 /* Write debug print */
+#define RD_DBG 0 /* Read debug print */
+#define QE_DBG 0 /* Quad Enable debug print */
+#define OP_DBG 0 /* OP command debug print */
+#define DMA_DB 0 /* DMA read or write debug print */
+#define AC_DBG 0 /* 3-4byte Address Cycle */
+#define SR_DBG 0 /* Status Register debug print */
+#define CR_DBG 0 /* Config Register debug print */
+#define FT_DBG 0 /* Features debug print */
+#define WE_DBG 0 /* Write Enable debug print */
+#define BP_DBG 0 /* Block Protection debug print */
+#define EC_DBG 0 /* enable/disable ecc0 and randomizer */
+#define PM_DBG 0 /* power management debug */
+
+#define FMC_PR(_type, _fmt, arg...) \
+ do { \
+ if (_type) \
+ DB_MSG(_fmt, ##arg) \
+ } while (0)
+
+#define DB_MSG(_fmt, arg...) \
+ pr_info("%s(%d): " _fmt, __func__, __LINE__, ##arg);
+
+#define DB_BUG(fmt, args...) \
+ do { \
+ pr_info("%s(%d): BUG: " fmt, __FILE__, __LINE__, ##args); \
+ while (1) \
+ ; \
+ } while (0)
+
+/*****************************************************************************/
+enum fmc_iftype {
+ IF_TYPE_STD,
+ IF_TYPE_DUAL,
+ IF_TYPE_DIO,
+ IF_TYPE_QUAD,
+ IF_TYPE_QIO,
+};
+
+struct bsp_fmc {
+ void __iomem *regbase;
+ void __iomem *iobase;
+ struct clk *clk;
+ struct mutex lock;
+ void *buffer;
+ dma_addr_t dma_buffer;
+ unsigned int dma_len;
+};
+
+struct fmc_cmd_op {
+ unsigned char cs;
+ unsigned char cmd;
+ unsigned char l_cmd;
+ unsigned char addr_h;
+ unsigned int addr_l;
+ unsigned int data_no;
+ unsigned short option;
+ unsigned short op_cfg;
+};
+
+extern struct mutex fmc_switch_mutex;
+
+#endif /*__BSP_FMC_H*/
diff -urN linux-4.9.37/include/linux/mmc/card.h linux-4.9.y/include/linux/mmc/card.h
--- linux-4.9.37/include/linux/mmc/card.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/include/linux/mmc/card.h 2021-06-07 13:01:34.000000000 +0300
@@ -14,6 +14,8 @@
#include <linux/mmc/core.h>
#include <linux/mod_devicetable.h>
+#define MMC_CARD_CMDQ_BLK_SIZE 512
+
struct mmc_cid {
unsigned int manfid;
char prod_name[8];
@@ -84,6 +86,7 @@
unsigned int hpi_cmd; /* cmd used as HPI */
bool bkops; /* background support bit */
bool man_bkops_en; /* manual bkops enable bit */
+ bool auto_bkops_en; /* auto bkops enable bit */
unsigned int data_sector_size; /* 512 bytes or 4KB */
unsigned int data_tag_unit_size; /* DATA TAG UNIT size */
unsigned int boot_ro_lock; /* ro lock support */
@@ -119,6 +122,8 @@
u8 raw_pwr_cl_ddr_200_360; /* 253 */
u8 raw_bkops_status; /* 246 */
u8 raw_sectors[4]; /* 212 - 4 bytes */
+ u8 cmdq_depth; /* 307 */
+ u8 cmdq_support; /* 308 */
unsigned int feature_support;
#define MMC_DISCARD_FEATURE BIT(0) /* CMD38 feature */
@@ -264,6 +269,8 @@
#define MMC_CARD_REMOVED (1<<4) /* card has been removed */
#define MMC_STATE_DOING_BKOPS (1<<5) /* card is doing BKOPS */
#define MMC_STATE_SUSPENDED (1<<6) /* card is suspended */
+#define MMC_STATE_CMDQ (1<<7) /* card is in cmd queue mode */
+
unsigned int quirks; /* card quirks */
#define MMC_QUIRK_LENIENT_FN0 (1<<0) /* allow SDIO FN0 writes outside of the VS CCCR range */
#define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1) /* use func->cur_blksize */
@@ -281,7 +288,8 @@
#define MMC_QUIRK_BROKEN_IRQ_POLLING (1<<11) /* Polling SDIO_CCCR_INTx could create a fake interrupt */
#define MMC_QUIRK_TRIM_BROKEN (1<<12) /* Skip trim */
#define MMC_QUIRK_BROKEN_HPI (1<<13) /* Disable broken HPI support */
-
+/* Make sure CMDQ is empty before queuing DCMD */
+#define MMC_QUIRK_CMDQ_EMPTY_BEFORE_DCMD (1 << 14)
unsigned int erase_size; /* erase size in sectors */
unsigned int erase_shift; /* if erase unit is power 2 */
@@ -316,6 +324,8 @@
struct dentry *debugfs_root;
struct mmc_part part[MMC_NUM_PHY_PARTITION]; /* physical partitions */
unsigned int nr_parts;
+ unsigned int part_curr;
+ bool cmdq_init;
};
/*
@@ -453,6 +463,7 @@
#define mmc_card_removed(c) ((c) && ((c)->state & MMC_CARD_REMOVED))
#define mmc_card_doing_bkops(c) ((c)->state & MMC_STATE_DOING_BKOPS)
#define mmc_card_suspended(c) ((c)->state & MMC_STATE_SUSPENDED)
+#define mmc_card_cmdq(c) ((c)->state & MMC_STATE_CMDQ)
#define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT)
#define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
@@ -463,6 +474,8 @@
#define mmc_card_clr_doing_bkops(c) ((c)->state &= ~MMC_STATE_DOING_BKOPS)
#define mmc_card_set_suspended(c) ((c)->state |= MMC_STATE_SUSPENDED)
#define mmc_card_clr_suspended(c) ((c)->state &= ~MMC_STATE_SUSPENDED)
+#define mmc_card_set_cmdq(c) ((c)->state |= MMC_STATE_CMDQ)
+#define mmc_card_clr_cmdq(c) ((c)->state &= ~MMC_STATE_CMDQ)
/*
* Quirk add/remove for MMC products.
@@ -538,6 +551,16 @@
return c->quirks & MMC_QUIRK_BROKEN_HPI;
}
+static inline bool mmc_card_configured_manual_bkops(const struct mmc_card *c)
+{
+ return c->ext_csd.man_bkops_en;
+}
+
+static inline bool mmc_card_configured_auto_bkops(const struct mmc_card *c)
+{
+ return c->ext_csd.auto_bkops_en;
+}
+
#define mmc_card_name(c) ((c)->cid.prod_name)
#define mmc_card_id(c) (dev_name(&(c)->dev))
diff -urN linux-4.9.37/include/linux/mmc/core.h linux-4.9.y/include/linux/mmc/core.h
--- linux-4.9.37/include/linux/mmc/core.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/include/linux/mmc/core.h 2021-06-07 13:01:34.000000000 +0300
@@ -142,10 +142,26 @@
/* Allow other commands during this ongoing data transfer or busy wait */
bool cap_cmd_during_tfr;
+ struct mmc_cmdq_req *cmdq_req;
+ struct request *req;
};
struct mmc_card;
struct mmc_async_req;
+struct mmc_cmdq_req;
+
+extern int mmc_cmdq_discard_queue(struct mmc_host *host, u32 tasks);
+extern int mmc_cmdq_halt(struct mmc_host *host, bool enable);
+extern int mmc_cmdq_halt_on_empty_queue(struct mmc_host *host);
+extern void mmc_cmdq_post_req(struct mmc_host *host, int tag, int err);
+extern int mmc_cmdq_start_req(struct mmc_host *host,
+ struct mmc_cmdq_req *cmdq_req);
+extern int mmc_cmdq_prepare_flush(struct mmc_command *cmd);
+extern int mmc_cmdq_wait_for_dcmd(struct mmc_host *host,
+ struct mmc_cmdq_req *cmdq_req);
+extern int mmc_cmdq_erase(struct mmc_cmdq_req *cmdq_req,
+ struct mmc_card *card, unsigned int from, unsigned int nr,
+ unsigned int arg);
extern int mmc_stop_bkops(struct mmc_card *);
extern int mmc_read_bkops_status(struct mmc_card *);
@@ -161,6 +177,9 @@
extern int mmc_wait_for_app_cmd(struct mmc_host *, struct mmc_card *,
struct mmc_command *, int);
extern void mmc_start_bkops(struct mmc_card *card, bool from_exception);
+extern int __mmc_switch_cmdq_mode(struct mmc_command *cmd, u8 set, u8 index,
+ u8 value, unsigned int timeout_ms,
+ bool use_busy_signal, bool ignore_timeout);
extern int mmc_switch(struct mmc_card *, u8, u8, u8, unsigned int);
extern int mmc_send_tuning(struct mmc_host *host, u32 opcode, int *cmd_error);
extern int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd);
@@ -190,6 +209,7 @@
extern int mmc_set_blockcount(struct mmc_card *card, unsigned int blockcount,
bool is_rel_write);
extern int mmc_hw_reset(struct mmc_host *host);
+extern int mmc_cmdq_hw_reset(struct mmc_host *host);
extern int mmc_can_reset(struct mmc_card *card);
extern void mmc_set_data_timeout(struct mmc_data *, const struct mmc_card *);
diff -urN linux-4.9.37/include/linux/mmc/host.h linux-4.9.y/include/linux/mmc/host.h
--- linux-4.9.37/include/linux/mmc/host.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/include/linux/mmc/host.h 2021-06-07 13:01:34.000000000 +0300
@@ -82,6 +82,17 @@
bool enhanced_strobe; /* hs400es selection */
};
+struct mmc_cmdq_host_ops {
+ int (*init)(struct mmc_host *host);
+ int (*enable)(struct mmc_host *host);
+ void (*disable)(struct mmc_host *host, bool soft);
+ int (*request)(struct mmc_host *host, struct mmc_request *mrq);
+ void (*post_req)(struct mmc_host *host, int tag, int err);
+ int (*halt)(struct mmc_host *host, bool halt);
+ void (*reset)(struct mmc_host *host, bool soft);
+ void (*dumpstate)(struct mmc_host *host);
+};
+
struct mmc_host_ops {
/*
* It is optional for the host to implement pre_req and post_req in
@@ -161,11 +172,37 @@
*/
int (*multi_io_quirk)(struct mmc_card *card,
unsigned int direction, int blk_size);
+ void (*notify_halt)(struct mmc_host *mmc, bool halt);
+ int (*card_info_save)(struct mmc_host *host);
};
struct mmc_card;
struct device;
+struct mmc_cmdq_req {
+ unsigned int cmd_flags;
+ u32 blk_addr;
+ /* active mmc request */
+ struct mmc_request mrq;
+ struct mmc_data data;
+ struct mmc_command cmd;
+#define DCMD (1 << 0)
+#define QBR (1 << 1)
+#define DIR (1 << 2)
+#define PRIO (1 << 3)
+#define REL_WR (1 << 4)
+#define DAT_TAG (1 << 5)
+#define FORCED_PRG (1 << 6)
+ unsigned int cmdq_req_flags;
+
+ unsigned int resp_idx;
+ unsigned int resp_arg;
+ unsigned int dev_pend_tasks;
+ bool resp_err;
+ int tag; /* used for command queuing */
+ u8 ctx_id;
+};
+
struct mmc_async_req {
/* active mmc request */
struct mmc_request *mrq;
@@ -192,6 +229,33 @@
void *handler_priv;
};
+
+/**
+ * mmc_cmdq_context_info - describes the contexts of cmdq
+ * @active_reqs requests being processed
+ * @data_active_reqs data requests being processed
+ * @curr_state state of cmdq engine
+ * @cmdq_ctx_lock acquire this before accessing this structure
+ * @queue_empty_wq workqueue for waiting for all
+ * the outstanding requests to be completed
+ * @wait waiting for all conditions described in
+ * mmc_cmdq_ready_wait to be satisified before
+ * issuing the new request to LLD.
+ */
+struct mmc_cmdq_context_info {
+ unsigned long active_reqs; /* in-flight requests */
+ unsigned long data_active_reqs; /* in-flight data requests */
+ unsigned long curr_state;
+#define CMDQ_STATE_ERR 0
+#define CMDQ_STATE_DCMD_ACTIVE 1
+#define CMDQ_STATE_HALT 2
+#define CMDQ_STATE_CQ_DISABLE 3
+#define CMDQ_STATE_REQ_TIMED_OUT 4
+ wait_queue_head_t queue_empty_wq;
+ wait_queue_head_t wait;
+ int active_small_sector_read_reqs;
+};
+
/**
* mmc_context_info - synchronization details for mmc context
* @is_done_rcv wake up reason was done request
@@ -221,10 +285,17 @@
struct device class_dev;
int index;
const struct mmc_host_ops *ops;
+ const struct mmc_cmdq_host_ops *cmdq_ops;
struct mmc_pwrseq *pwrseq;
unsigned int f_min;
unsigned int f_max;
unsigned int f_init;
+ unsigned int type;
+#define MMC_HOST_TYPE_MMC 0 /* MMC card */
+#define MMC_HOST_TYPE_SD 1 /* SD card */
+#define MMC_HOST_TYPE_SDIO 2 /* SDIO card */
+#define MMC_HOST_TYPE_SD_COMBO 3 /* SD combo (IO+mem) card */
+
u32 ocr_avail;
u32 ocr_avail_sdio; /* SDIO-specific OCR */
u32 ocr_avail_sd; /* SD-specific OCR */
@@ -312,6 +383,7 @@
#define MMC_CAP2_HS400_ES (1 << 20) /* Host supports enhanced strobe */
#define MMC_CAP2_NO_SD (1 << 21) /* Do not send SD commands during initialization */
#define MMC_CAP2_NO_MMC (1 << 22) /* Do not send (e)MMC commands during initialization */
+#define MMC_CAP2_CMD_QUEUE (1 << 23) /* support eMMC command queue */
mmc_pm_flag_t pm_caps; /* supported pm features */
@@ -359,6 +431,11 @@
struct delayed_work detect;
int detect_change; /* card detect flag */
+ u32 card_status;
+#define MMC_CARD_UNINIT 0
+#define MMC_CARD_INIT 1
+#define MMC_CARD_INIT_FAIL 2
+
struct mmc_slot slot;
const struct mmc_bus_ops *bus_ops; /* current bus driver */
@@ -397,6 +474,20 @@
int dsr_req; /* DSR value is valid */
u32 dsr; /* optional driver stage (DSR) value */
+ struct mmc_cmdq_context_info cmdq_ctx;
+ int num_cq_slots;
+ int dcmd_cq_slot;
+ u32 cmdq_thist_enabled;
+ /*
+ * several cmdq supporting host controllers are extensions
+ * of legacy controllers. This variable can be used to store
+ * a reference to the cmdq extension of the existing host
+ * controller.
+ */
+ void *cmdq_private;
+ struct mmc_request *err_mrq;
+ struct timeval start;
+ struct timeval end;
unsigned long private[0] ____cacheline_aligned;
};
@@ -411,6 +502,11 @@
return (void *)host->private;
}
+static inline void *mmc_cmdq_private(struct mmc_host *host)
+{
+ return host->cmdq_private;
+}
+
#define mmc_host_is_spi(host) ((host)->caps & MMC_CAP_SPI)
#define mmc_dev(x) ((x)->parent)
@@ -500,6 +596,36 @@
return host->caps2 & MMC_CAP2_PACKED_WR;
}
+static inline void mmc_host_set_halt(struct mmc_host *host)
+{
+ set_bit(CMDQ_STATE_HALT, &host->cmdq_ctx.curr_state);
+}
+
+static inline void mmc_host_clr_halt(struct mmc_host *host)
+{
+ clear_bit(CMDQ_STATE_HALT, &host->cmdq_ctx.curr_state);
+}
+
+static inline int mmc_host_halt(struct mmc_host *host)
+{
+ return test_bit(CMDQ_STATE_HALT, &host->cmdq_ctx.curr_state);
+}
+
+static inline void mmc_host_set_cq_disable(struct mmc_host *host)
+{
+ set_bit(CMDQ_STATE_CQ_DISABLE, &host->cmdq_ctx.curr_state);
+}
+
+static inline void mmc_host_clr_cq_disable(struct mmc_host *host)
+{
+ clear_bit(CMDQ_STATE_CQ_DISABLE, &host->cmdq_ctx.curr_state);
+}
+
+static inline int mmc_host_cq_disable(struct mmc_host *host)
+{
+ return test_bit(CMDQ_STATE_CQ_DISABLE, &host->cmdq_ctx.curr_state);
+}
+
static inline int mmc_card_hs(struct mmc_card *card)
{
return card->host->ios.timing == MMC_TIMING_SD_HS ||
diff -urN linux-4.9.37/include/linux/mmc/mmc.h linux-4.9.y/include/linux/mmc/mmc.h
--- linux-4.9.37/include/linux/mmc/mmc.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/include/linux/mmc/mmc.h 2021-06-07 13:01:34.000000000 +0300
@@ -84,6 +84,11 @@
#define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */
#define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1 */
+/* class 11 */
+#define MMC_CMDQ_TASK_MGMT 48 /* ac [31:0] task ID R1b */
+#define DISCARD_QUEUE 0x1
+#define DISCARD_TASK 0x2
+
static inline bool mmc_op_multi(u32 opcode)
{
return opcode == MMC_WRITE_MULTIPLE_BLOCK ||
@@ -272,6 +277,7 @@
* EXT_CSD fields
*/
+#define EXT_CSD_CMDQ 15 /* R/W */
#define EXT_CSD_FLUSH_CACHE 32 /* W */
#define EXT_CSD_CACHE_CTRL 33 /* R/W */
#define EXT_CSD_POWER_OFF_NOTIFICATION 34 /* R/W */
@@ -331,6 +337,9 @@
#define EXT_CSD_CACHE_SIZE 249 /* RO, 4 bytes */
#define EXT_CSD_PWR_CL_DDR_200_360 253 /* RO */
#define EXT_CSD_FIRMWARE_VERSION 254 /* RO, 8 bytes */
+#define EXT_CSD_CMDQ_DEPTH 307 /* RO */
+#define EXT_CSD_CMDQ_SUPPORT 308 /* RO */
+
#define EXT_CSD_SUPPORTED_MODE 493 /* RO */
#define EXT_CSD_TAG_UNIT_SIZE 498 /* RO */
#define EXT_CSD_DATA_TAG_SUPPORT 499 /* RO */
@@ -436,6 +445,7 @@
* BKOPS modes
*/
#define EXT_CSD_MANUAL_BKOPS_MASK 0x01
+#define EXT_CSD_AUTO_BKOPS_MASK 0x02
/*
* MMC_SWITCH access modes
diff -urN linux-4.9.37/include/linux/mm_types.h linux-4.9.y/include/linux/mm_types.h
--- linux-4.9.37/include/linux/mm_types.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/include/linux/mm_types.h 2021-06-07 13:01:34.000000000 +0300
@@ -12,6 +12,7 @@
#include <linux/cpumask.h>
#include <linux/uprobes.h>
#include <linux/page-flags-layout.h>
+#include <linux/percpu.h>
#include <linux/workqueue.h>
#include <asm/page.h>
#include <asm/mmu.h>
diff -urN linux-4.9.37/include/linux/mtd/nand.h linux-4.9.y/include/linux/mtd/nand.h
--- linux-4.9.37/include/linux/mtd/nand.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/include/linux/mtd/nand.h 2021-06-07 13:01:34.000000000 +0300
@@ -80,6 +80,7 @@
#define NAND_CMD_READOOB 0x50
#define NAND_CMD_ERASE1 0x60
#define NAND_CMD_STATUS 0x70
+#define NAND_CMD_STATUS_MULTI 0x71
#define NAND_CMD_SEQIN 0x80
#define NAND_CMD_RNDIN 0x85
#define NAND_CMD_READID 0x90
@@ -87,6 +88,7 @@
#define NAND_CMD_PARAM 0xec
#define NAND_CMD_GET_FEATURES 0xee
#define NAND_CMD_SET_FEATURES 0xef
+#define NAND_CMD_SYNC_RESET 0xfc
#define NAND_CMD_RESET 0xff
#define NAND_CMD_LOCK 0x2a
@@ -925,9 +927,18 @@
#define NAND_MFR_AMD 0x01
#define NAND_MFR_MACRONIX 0xc2
#define NAND_MFR_EON 0x92
+#define NAND_MFR_WINBOND 0xef
+#define NAND_MFR_ATO 0x9b
+#define NAND_MFR_MXIC 0xc2
+#define NAND_MFR_ALL_FLASH 0xc1
+#define NAND_MFR_PARAGON 0xa1
#define NAND_MFR_SANDISK 0x45
#define NAND_MFR_INTEL 0x89
#define NAND_MFR_ATO 0x9b
+#define NAND_MFR_GD_ESMT 0xc8
+#define NAND_MFR_HEYANGTEK 0xc9
+#define NAND_MFR_DOSILICON 0xe5
+#define NAND_MFR_FIDELIX 0xf8
/* The maximum expected count of bytes in the NAND ID sequence */
#define NAND_MAX_ID_LEN 8
diff -urN linux-4.9.37/include/linux/mtd/spi-nor.h linux-4.9.y/include/linux/mtd/spi-nor.h
--- linux-4.9.37/include/linux/mtd/spi-nor.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/include/linux/mtd/spi-nor.h 2021-06-07 13:01:34.000000000 +0300
@@ -12,7 +12,6 @@
#include <linux/bitops.h>
#include <linux/mtd/cfi.h>
-#include <linux/mtd/mtd.h>
/*
* Manufacturer IDs
@@ -21,13 +20,53 @@
* Sometimes these are the same as CFI IDs, but sometimes they aren't.
*/
#define SNOR_MFR_ATMEL CFI_MFR_ATMEL
-#define SNOR_MFR_GIGADEVICE 0xc8
#define SNOR_MFR_INTEL CFI_MFR_INTEL
#define SNOR_MFR_MICRON CFI_MFR_ST /* ST Micro <--> Micron */
#define SNOR_MFR_MACRONIX CFI_MFR_MACRONIX
#define SNOR_MFR_SPANSION CFI_MFR_AMD
#define SNOR_MFR_SST CFI_MFR_SST
-#define SNOR_MFR_WINBOND 0xef /* Also used by some Spansion */
+#define SNOR_MFR_EON CFI_MFR_EON
+#define SNOR_MFR_WINBOND 0xef
+#define SNOR_MFR_ESMT 0x8c
+#define SNOR_MFR_GD 0xc8
+#define SNOR_MFR_XTX 0x0b
+#define SNOR_MFR_PUYA 0x85
+#define SNOR_MFR_ISSI 0x9d
+
+/* Flash set the RESET# from */
+#define SPI_NOR_SR_RST_MASK BIT(7)
+#define SPI_NOR_GET_RST(val) (((val) & SPI_NOR_SR_RST_MASK) >> 7)
+#define SPI_NOR_SET_RST(val) ((val) | SPI_NOR_SR_RST_MASK)
+
+/* Flash block protect */
+#ifdef CONFIG_GOKE_SPI_BLOCK_PROTECT
+#define _2M (0x200000UL)
+#define _4M (0x400000UL)
+#define _8M (0x800000UL)
+#define _16M (0x1000000UL)
+#define _32M (0x2000000UL)
+
+#define BP_NUM_3 3
+#define BP_NUM_4 4
+
+#define DEBUG_SPI_NOR_BP 0
+
+#define SPI_NOR_SR_SRWD_SHIFT 7
+#define SPI_NOR_SR_SRWD_MASK (1 << SPI_NOR_SR_SRWD_SHIFT)
+
+#define SPI_NOR_SR_BP0_SHIFT 2
+#define SPI_NOR_SR_BP_WIDTH_4 0xf
+#define SPI_NOR_SR_BP_MASK_4 (SPI_NOR_SR_BP_WIDTH_4 << SPI_NOR_SR_BP0_SHIFT)
+
+#define SPI_NOR_SR_BP_WIDTH_3 0x7
+#define SPI_NOR_SR_BP_MASK_3 (SPI_NOR_SR_BP_WIDTH_3 << SPI_NOR_SR_BP0_SHIFT)
+
+#define SPI_NOR_SR_TB_SHIFT 3
+#define SPI_NOR_SR_TB_MASK (1 << SPI_NOR_SR_TB_SHIFT)
+
+#define LOCK_LEVEL_MAX(bp_num) (((0x01) << bp_num) - 1)
+
+#endif /* CONFIG_SPI_BLOCK_PROTECT */
/*
* Note on opcode nomenclature: some opcodes have a format like
@@ -40,27 +79,42 @@
/* Flash opcodes. */
#define SPINOR_OP_WREN 0x06 /* Write enable */
#define SPINOR_OP_RDSR 0x05 /* Read status register */
+#define SPINOR_OP_RDSR2 0x35 /* Read Status Register-2 */
+#define SPINOR_OP_RDSR3 0x15 /* Read Status Register-3 */
#define SPINOR_OP_WRSR 0x01 /* Write status register 1 byte */
+#define SPINOR_OP_WRSR2 0x31 /* Write Status Register-2 1 byte*/
+#define SPINOR_OP_WRSR3 0x11 /* Write Status Register-3 1 byte*/
#define SPINOR_OP_READ 0x03 /* Read data bytes (low frequency) */
#define SPINOR_OP_READ_FAST 0x0b /* Read data bytes (high frequency) */
-#define SPINOR_OP_READ_1_1_2 0x3b /* Read data bytes (Dual SPI) */
-#define SPINOR_OP_READ_1_1_4 0x6b /* Read data bytes (Quad SPI) */
+#define SPINOR_OP_READ_1_1_2 0x3b /* Read data bytes (Dual Output SPI) */
+#define SPINOR_OP_READ_1_2_2 0xbb /* Read data bytes (Dual I/O SPI) */
+#define SPINOR_OP_READ_1_1_4 0x6b /* Read data bytes (Quad Output SPI) */
+#define SPINOR_OP_READ_1_4_4 0xeb /* Read data bytes (Quad I/O SPI) */
#define SPINOR_OP_PP 0x02 /* Page program (up to 256 bytes) */
+#define SPINOR_OP_PP_1_1_4 0x32 /* Quad page program */
+#define SPINOR_OP_PP_1_4_4 0x38 /* Quad page program */
#define SPINOR_OP_BE_4K 0x20 /* Erase 4KiB block */
#define SPINOR_OP_BE_4K_PMC 0xd7 /* Erase 4KiB block on PMC chips */
#define SPINOR_OP_BE_32K 0x52 /* Erase 32KiB block */
#define SPINOR_OP_CHIP_ERASE 0xc7 /* Erase whole flash chip */
#define SPINOR_OP_SE 0xd8 /* Sector erase (usually 64KiB) */
#define SPINOR_OP_RDID 0x9f /* Read JEDEC ID */
+#define SPINOR_OP_RDSFDP 0x5a /* Read SFDP */
#define SPINOR_OP_RDCR 0x35 /* Read configuration register */
#define SPINOR_OP_RDFSR 0x70 /* Read flag status register */
/* 4-byte address opcodes - used on Spansion and some Macronix flashes. */
-#define SPINOR_OP_READ4 0x13 /* Read data bytes (low frequency) */
-#define SPINOR_OP_READ4_FAST 0x0c /* Read data bytes (high frequency) */
-#define SPINOR_OP_READ4_1_1_2 0x3c /* Read data bytes (Dual SPI) */
-#define SPINOR_OP_READ4_1_1_4 0x6c /* Read data bytes (Quad SPI) */
+#define SPINOR_OP_READ_4B 0x13 /* Read data bytes (low frequency) */
+#define SPINOR_OP_READ_FAST_4B 0x0c /* Read data bytes (high frequency) */
+#define SPINOR_OP_READ_1_1_2_4B 0x3c /* Read data bytes (Dual Output SPI) */
+#define SPINOR_OP_READ_1_2_2_4B 0xbc /* Read data bytes (Dual I/O SPI) */
+#define SPINOR_OP_READ_1_1_4_4B 0x6c /* Read data bytes (Quad Output SPI) */
+#define SPINOR_OP_READ_1_4_4_4B 0xec /* Read data bytes (Quad I/O SPI) */
#define SPINOR_OP_PP_4B 0x12 /* Page program (up to 256 bytes) */
+#define SPINOR_OP_PP_1_1_4_4B 0x34 /* Quad page program */
+#define SPINOR_OP_PP_1_4_4_4B 0x3e /* Quad page program */
+#define SPINOR_OP_BE_4K_4B 0x21 /* Erase 4KiB block */
+#define SPINOR_OP_BE_32K_4B 0x5c /* Erase 32KiB block */
#define SPINOR_OP_SE_4B 0xdc /* Sector erase (usually 64KiB) */
/* Used for SST flashes only. */
@@ -73,12 +127,20 @@
#define SPINOR_OP_EX4B 0xe9 /* Exit 4-byte mode */
/* Used for Spansion flashes only. */
+#define SPINOR_OP_BRRD 0x16 /* Bank register write */
#define SPINOR_OP_BRWR 0x17 /* Bank register write */
+/* Used for GigaDevice flashes only. */
+#define SPINOR_OP_WRCR 0x31 /* Config register write */
+
/* Used for Micron flashes only. */
#define SPINOR_OP_RD_EVCR 0x65 /* Read EVCR register */
#define SPINOR_OP_WD_EVCR 0x61 /* Write EVCR register */
+/* Software reset code */
+#define SPINOR_ENABLE_RESET 0x66 /* Enable reset */
+#define SPINOR_OP_RESET 0x99 /* Reset */
+
/* Status Register bits. */
#define SR_WIP BIT(0) /* Write in progress */
#define SR_WEL BIT(1) /* Write enable latch */
@@ -90,8 +152,9 @@
#define SR_SRWD BIT(7) /* SR write protect */
#define SR_QUAD_EN_MX BIT(6) /* Macronix Quad I/O */
-
+#define CR_DUMMY_CYCLE (0x03 << 6) /* Macronix dummy cycle bits */
/* Enhanced Volatile Configuration Register bits */
+#define EVCR_DUAL_EN_MICRON BIT(6) /* Micron Dual I/O */
#define EVCR_QUAD_EN_MICRON BIT(7) /* Micron Quad I/O */
/* Flag Status Register bits */
@@ -99,12 +162,109 @@
/* Configuration Register bits. */
#define CR_QUAD_EN_SPAN BIT(1) /* Spansion Quad I/O */
+#define QUAD_EN_ISSI BIT(6)
+/* Status Register bits. */
+#define SR_QUAD_EN_XTX BIT(1)
+
+/* Supported modes */
+enum spi_nor_mode_index {
+ /* Sorted by ascending priority order */
+ SNOR_MIDX_SLOW = 0,
+ SNOR_MIDX_1_1_1,
+ SNOR_MIDX_1_1_2,
+ SNOR_MIDX_1_2_2,
+ SNOR_MIDX_1_1_4,
+ SNOR_MIDX_1_4_4,
+
+ SNOR_MIDX_MAX
+};
+
+#define SNOR_MODE_SLOW BIT(SNOR_MIDX_SLOW)
+#define SNOR_MODE_1_1_1 BIT(SNOR_MIDX_1_1_1)
+#define SNOR_MODE_1_1_2 BIT(SNOR_MIDX_1_1_2)
+#define SNOR_MODE_1_2_2 BIT(SNOR_MIDX_1_2_2)
+#define SNOR_MODE_1_1_4 BIT(SNOR_MIDX_1_1_4)
+#define SNOR_MODE_1_4_4 BIT(SNOR_MIDX_1_4_4)
+
+struct spi_nor_modes {
+ u32 rd_modes; /* supported SPI modes for (Fast) Read */
+ u32 wr_modes; /* supported SPI modes for Page Program */
+};
+
+struct spi_nor_read_op {
+ u8 num_mode_clocks;
+ u8 num_wait_states;
+ u8 opcode;
+};
-enum read_mode {
- SPI_NOR_NORMAL = 0,
- SPI_NOR_FAST,
- SPI_NOR_DUAL,
- SPI_NOR_QUAD,
+#define SNOR_OP_READ(_num_mode_clocks, _num_wait_states, _opcode) \
+ { \
+ .num_mode_clocks = _num_mode_clocks, \
+ .num_wait_states = _num_wait_states, \
+ .opcode = _opcode, \
+ }
+
+struct spi_nor_erase_type {
+ u8 size; /* specifies 'N' so erase size = 2^N */
+ u8 opcode;
+};
+
+#define SNOR_OP_ERASE(_size, _opcode) { .size = _size, .opcode = _opcode }
+#define SNOR_OP_ERASE_64K(_opcode) SNOR_OP_ERASE(0x10, _opcode)
+#define SNOR_OP_ERASE_32K(_opcode) SNOR_OP_ERASE(0x0f, _opcode)
+#define SNOR_OP_ERASE_4K(_opcode) SNOR_OP_ERASE(0x0c, _opcode)
+
+struct spi_nor;
+
+#define SNOR_MAX_ERASE_TYPES 4
+
+struct spi_nor_basic_flash_parameter {
+ /* Fast Read settings */
+ u32 rd_modes;
+ struct spi_nor_read_op reads[SNOR_MIDX_MAX];
+
+ /* Page Program settings */
+ u32 wr_modes;
+ u8 page_programs[SNOR_MIDX_MAX];
+
+ /* Sector Erase settings */
+ struct spi_nor_erase_type erase_types[SNOR_MAX_ERASE_TYPES];
+
+ int (*enable_quad_io)(struct spi_nor *nor);
+};
+
+#define SNOR_PROTO_CODE_OFF 8
+#define SNOR_PROTO_CODE_MASK GENMASK(11, 8)
+#define SNOR_PROTO_CODE_TO_PROTO(code) \
+ (((code) << SNOR_PROTO_CODE_OFF) & SNOR_PROTO_CODE_MASK)
+#define SNOR_PROTO_CODE_FROM_PROTO(proto) \
+ ((((u32)(proto)) & SNOR_PROTO_CODE_MASK) >> SNOR_PROTO_CODE_OFF)
+
+#define SNOR_PROTO_ADDR_OFF 4
+#define SNOR_PROTO_ADDR_MASK GENMASK(7, 4)
+#define SNOR_PROTO_ADDR_TO_PROTO(addr) \
+ (((addr) << SNOR_PROTO_ADDR_OFF) & SNOR_PROTO_ADDR_MASK)
+#define SNOR_PROTO_ADDR_FROM_PROTO(proto) \
+ ((((u32)(proto)) & SNOR_PROTO_ADDR_MASK) >> SNOR_PROTO_ADDR_OFF)
+
+#define SNOR_PROTO_DATA_OFF 0
+#define SNOR_PROTO_DATA_MASK GENMASK(3, 0)
+#define SNOR_PROTO_DATA_TO_PROTO(data) \
+ (((data) << SNOR_PROTO_DATA_OFF) & SNOR_PROTO_DATA_MASK)
+#define SNOR_PROTO_DATA_FROM_PROTO(proto) \
+ ((((u32)(proto)) & SNOR_PROTO_DATA_MASK) >> SNOR_PROTO_DATA_OFF)
+
+#define SNOR_PROTO(code, addr, data) \
+ (SNOR_PROTO_CODE_TO_PROTO(code) | \
+ SNOR_PROTO_ADDR_TO_PROTO(addr) | \
+ SNOR_PROTO_DATA_TO_PROTO(data))
+
+enum spi_nor_protocol {
+ SNOR_PROTO_1_1_1 = SNOR_PROTO(1, 1, 1), /* SPI */
+ SNOR_PROTO_1_1_2 = SNOR_PROTO(1, 1, 2), /* Dual Output */
+ SNOR_PROTO_1_2_2 = SNOR_PROTO(1, 2, 2), /* Dual IO */
+ SNOR_PROTO_1_1_4 = SNOR_PROTO(1, 1, 4), /* Quad Output */
+ SNOR_PROTO_1_4_4 = SNOR_PROTO(1, 4, 4), /* Quad IO */
};
#define SPI_NOR_MAX_CMD_SIZE 8
@@ -121,20 +281,26 @@
SNOR_F_HAS_SR_TB = BIT(1),
};
+struct mtd_info;
+
/**
* struct spi_nor - Structure for defining a the SPI NOR layer
* @mtd: point to a mtd_info structure
* @lock: the lock for the read/write/erase/lock/unlock operations
* @dev: point to a spi device, or a spi nor controller device.
+ * @flash_node: point to a device node describing this flash instance.
* @page_size: the page size of the SPI NOR
* @addr_width: number of address bytes
* @erase_opcode: the opcode for erasing a sector
* @read_opcode: the read opcode
* @read_dummy: the dummy needed by the read operation
* @program_opcode: the program opcode
- * @flash_read: the mode of the read
* @sst_write_second: used by the SST write operation
* @flags: flag options for the current SPI-NOR (SNOR_F_*)
+ * @erase_proto: the SPI protocol used by erase operations
+ * @read_proto: the SPI protocol used by read operations
+ * @write_proto: the SPI protocol used by write operations
+ * @reg_proto the SPI protocol used by read_reg/write_reg operations
* @cmd_buf: used by the write_reg
* @prepare: [OPTIONAL] do some preparations for the
* read/write/erase/lock/unlock operations
@@ -157,13 +323,16 @@
struct mtd_info mtd;
struct mutex lock;
struct device *dev;
+ struct device_node *flash_node;
u32 page_size;
u8 addr_width;
u8 erase_opcode;
u8 read_opcode;
u8 read_dummy;
u8 program_opcode;
- enum read_mode flash_read;
+ enum spi_nor_protocol erase_proto;
+ enum spi_nor_protocol read_proto;
+ enum spi_nor_protocol write_proto;
bool sst_write_second;
u32 flags;
u8 cmd_buf[SPI_NOR_MAX_CMD_SIZE];
@@ -183,6 +352,12 @@
int (*flash_unlock)(struct spi_nor *nor, loff_t ofs, uint64_t len);
int (*flash_is_locked)(struct spi_nor *nor, loff_t ofs, uint64_t len);
+#ifdef CONFIG_GOKE_SPI_BLOCK_PROTECT
+ unsigned int end_addr;
+ unsigned int lock_level_max;
+ unsigned char level;
+#endif
+ u32 clkrate;
void *priv;
};
@@ -201,7 +376,7 @@
* spi_nor_scan() - scan the SPI NOR
* @nor: the spi_nor structure
* @name: the chip type name
- * @mode: the read mode supported by the driver
+ * @modes: the SPI modes supported by the controller driver
*
* The drivers can use this fuction to scan the SPI NOR.
* In the scanning, it will try to get all the necessary information to
@@ -211,6 +386,12 @@
*
* Return: 0 for success, others for failure.
*/
-int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode);
+int spi_nor_scan(struct spi_nor *nor, const char *name,
+ struct spi_nor_modes *modes);
+void spi_nor_driver_shutdown(struct spi_nor *nor);
+#ifdef CONFIG_PM
+int spi_nor_suspend(struct spi_nor *nor, pm_message_t state);
+int spi_nor_resume(struct spi_nor *nor);
+#endif
#endif
diff -urN linux-4.9.37/include/linux/nospec.h linux-4.9.y/include/linux/nospec.h
--- linux-4.9.37/include/linux/nospec.h 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/include/linux/nospec.h 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright(c) 2018 Linus Torvalds. All rights reserved.
+// Copyright(c) 2018 Alexei Starovoitov. All rights reserved.
+// Copyright(c) 2018 Intel Corporation. All rights reserved.
+
+#ifndef _LINUX_NOSPEC_H
+#define _LINUX_NOSPEC_H
+
+/**
+ * array_index_mask_nospec() - generate a ~0 mask when index < size, 0 otherwise
+ * @index: array element index
+ * @size: number of elements in array
+ *
+ * When @index is out of bounds (@index >= @size), the sign bit will be
+ * set. Extend the sign bit to all bits and invert, giving a result of
+ * zero for an out of bounds index, or ~0 if within bounds [0, @size).
+ */
+#ifndef array_index_mask_nospec
+static inline unsigned long array_index_mask_nospec(unsigned long index,
+ unsigned long size)
+{
+ /*
+ * Warn developers about inappropriate array_index_nospec() usage.
+ *
+ * Even if the CPU speculates past the WARN_ONCE branch, the
+ * sign bit of @index is taken into account when generating the
+ * mask.
+ *
+ * This warning is compiled out when the compiler can infer that
+ * @index and @size are less than LONG_MAX.
+ */
+ if (WARN_ONCE(index > LONG_MAX || size > LONG_MAX,
+ "array_index_nospec() limited to range of [0, LONG_MAX]\n"))
+ return 0;
+
+ /*
+ * Always calculate and emit the mask even if the compiler
+ * thinks the mask is not needed. The compiler does not take
+ * into account the value of @index under speculation.
+ */
+ OPTIMIZER_HIDE_VAR(index);
+ return ~(long)(index | (size - 1UL - index)) >> (BITS_PER_LONG - 1);
+}
+#endif
+
+/*
+ * array_index_nospec - sanitize an array index after a bounds check
+ *
+ * For a code sequence like:
+ *
+ * if (index < size) {
+ * index = array_index_nospec(index, size);
+ * val = array[index];
+ * }
+ *
+ * ...if the CPU speculates past the bounds check then
+ * array_index_nospec() will clamp the index within the range of [0,
+ * size).
+ */
+#define array_index_nospec(index, size) \
+ ({ \
+ typeof(index) _i = (index); \
+ typeof(size) _s = (size); \
+ unsigned long _mask = array_index_mask_nospec(_i, _s); \
+ \
+ BUILD_BUG_ON(sizeof(_i) > sizeof(long)); \
+ BUILD_BUG_ON(sizeof(_s) > sizeof(long)); \
+ \
+ _i &= _mask; \
+ _i; \
+ })
+#endif /* _LINUX_NOSPEC_H */
diff -urN linux-4.9.37/include/linux/phy.h linux-4.9.y/include/linux/phy.h
--- linux-4.9.37/include/linux/phy.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/include/linux/phy.h 2021-06-07 13:01:34.000000000 +0300
@@ -829,6 +829,10 @@
int phy_register_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask,
int (*run)(struct phy_device *));
+int phy_unregister_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask);
+int phy_unregister_fixup_for_id(const char *bus_id);
+int phy_unregister_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask);
+
int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable);
int phy_get_eee_err(struct phy_device *phydev);
int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_eee *data);
diff -urN linux-4.9.37/include/linux/psci.h linux-4.9.y/include/linux/psci.h
--- linux-4.9.37/include/linux/psci.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/include/linux/psci.h 2021-06-07 13:01:34.000000000 +0300
@@ -25,7 +25,14 @@
int psci_cpu_init_idle(unsigned int cpu);
int psci_cpu_suspend_enter(unsigned long index);
+enum psci_conduit {
+ PSCI_CONDUIT_NONE,
+ PSCI_CONDUIT_SMC,
+ PSCI_CONDUIT_HVC,
+};
+
struct psci_operations {
+ u32 (*get_version)(void);
int (*cpu_suspend)(u32 state, unsigned long entry_point);
int (*cpu_off)(u32 state);
int (*cpu_on)(unsigned long cpuid, unsigned long entry_point);
@@ -33,6 +40,7 @@
int (*affinity_info)(unsigned long target_affinity,
unsigned long lowest_affinity_level);
int (*migrate_info_type)(void);
+ enum psci_conduit conduit;
};
extern struct psci_operations psci_ops;
diff -urN linux-4.9.37/include/linux/sched.h linux-4.9.y/include/linux/sched.h
--- linux-4.9.37/include/linux/sched.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/include/linux/sched.h 2021-06-07 13:01:34.000000000 +0300
@@ -24,6 +24,7 @@
#include <linux/cpumask.h>
#include <linux/errno.h>
#include <linux/nodemask.h>
+#include <linux/percpu.h>
#include <linux/mm_types.h>
#include <linux/preempt.h>
@@ -38,7 +39,6 @@
#include <linux/compiler.h>
#include <linux/completion.h>
#include <linux/pid.h>
-#include <linux/percpu.h>
#include <linux/topology.h>
#include <linux/seccomp.h>
#include <linux/rcupdate.h>
diff -urN linux-4.9.37/include/linux/spi/spi.h linux-4.9.y/include/linux/spi/spi.h
--- linux-4.9.37/include/linux/spi/spi.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/include/linux/spi/spi.h 2021-06-07 13:01:34.000000000 +0300
@@ -233,6 +233,8 @@
* @remove: Unbinds this driver from the spi device
* @shutdown: Standard shutdown callback used during system state
* transitions such as powerdown/halt and kexec
+ * @suspend: Standard suspend callback used during system state transitions
+ * @resume: Standard resume callback used during system state transitions
* @driver: SPI device drivers should initialize the name and owner
* field of this structure.
*
@@ -253,6 +255,8 @@
int (*probe)(struct spi_device *spi);
int (*remove)(struct spi_device *spi);
void (*shutdown)(struct spi_device *spi);
+ int (*suspend)(struct spi_device *spi, pm_message_t mesg);
+ int (*resume)(struct spi_device *spi);
struct device_driver driver;
};
@@ -442,6 +446,7 @@
#define SPI_MASTER_NO_TX BIT(2) /* can't do buffer write */
#define SPI_MASTER_MUST_RX BIT(3) /* requires rx */
#define SPI_MASTER_MUST_TX BIT(4) /* requires tx */
+ bool slave;
/*
* on some hardware transfer / message size may be constrained
diff -urN linux-4.9.37/include/linux/tcp.h linux-4.9.y/include/linux/tcp.h
--- linux-4.9.37/include/linux/tcp.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/include/linux/tcp.h 2021-06-07 13:01:34.000000000 +0300
@@ -432,4 +432,7 @@
tp->saved_syn = NULL;
}
+int tcp_skb_shift(struct sk_buff *to, struct sk_buff *from, int pcount,
+ int shiftlen);
+
#endif /* _LINUX_TCP_H */
diff -urN linux-4.9.37/include/linux/usb/usbnet.h linux-4.9.y/include/linux/usb/usbnet.h
--- linux-4.9.37/include/linux/usb/usbnet.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/include/linux/usb/usbnet.h 2021-06-07 13:01:34.000000000 +0300
@@ -204,6 +204,7 @@
};
extern int usbnet_generic_cdc_bind(struct usbnet *, struct usb_interface *);
+extern int usbnet_ether_cdc_bind(struct usbnet *dev, struct usb_interface *intf);
extern int usbnet_cdc_bind(struct usbnet *, struct usb_interface *);
extern void usbnet_cdc_unbind(struct usbnet *, struct usb_interface *);
extern void usbnet_cdc_status(struct usbnet *, struct urb *);
diff -urN linux-4.9.37/include/net/netns/ipv4.h linux-4.9.y/include/net/netns/ipv4.h
--- linux-4.9.37/include/net/netns/ipv4.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/include/net/netns/ipv4.h 2021-06-07 13:01:34.000000000 +0300
@@ -94,6 +94,7 @@
#endif
int sysctl_tcp_mtu_probing;
int sysctl_tcp_base_mss;
+ int sysctl_tcp_min_snd_mss;
int sysctl_tcp_probe_threshold;
u32 sysctl_tcp_probe_interval;
diff -urN linux-4.9.37/include/net/tcp.h linux-4.9.y/include/net/tcp.h
--- linux-4.9.37/include/net/tcp.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/include/net/tcp.h 2021-06-07 13:01:34.000000000 +0300
@@ -53,6 +53,8 @@
#define MAX_TCP_HEADER (128 + MAX_HEADER)
#define MAX_TCP_OPTION_SPACE 40
+#define TCP_MIN_SND_MSS 48
+#define TCP_MIN_GSO_SIZE (TCP_MIN_SND_MSS - MAX_TCP_OPTION_SPACE)
/*
* Never offer a window over 32767 without using window scaling. Some
diff -urN linux-4.9.37/include/uapi/linux/i2c-dev.h linux-4.9.y/include/uapi/linux/i2c-dev.h
--- linux-4.9.37/include/uapi/linux/i2c-dev.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/include/uapi/linux/i2c-dev.h 2021-06-07 13:01:34.000000000 +0300
@@ -50,6 +50,9 @@
#define I2C_PEC 0x0708 /* != 0 to use PEC with SMBus */
#define I2C_SMBUS 0x0720 /* SMBus transfer */
+#define I2C_16BIT_REG 0x0709 /* 16BIT REG WIDTH */
+#define I2C_16BIT_DATA 0x070a /* 16BIT DATA WIDTH */
+#define I2C_DMA 0x070b /* DMA mode */
/* This is the structure as used in the I2C_SMBUS ioctl call */
diff -urN linux-4.9.37/include/uapi/linux/i2c.h linux-4.9.y/include/uapi/linux/i2c.h
--- linux-4.9.37/include/uapi/linux/i2c.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/include/uapi/linux/i2c.h 2021-06-07 13:01:34.000000000 +0300
@@ -71,12 +71,19 @@
#define I2C_M_RD 0x0001 /* read data, from slave to master */
/* I2C_M_RD is guaranteed to be 0x0001! */
#define I2C_M_TEN 0x0010 /* this is a ten bit chip address */
+#define I2C_M_NOSTART 0x4000 /* if I2C_FUNC_PROTOCOL_MANGLING */
+#define I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */
+#define I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_RECV_LEN 0x0400 /* length will be first received byte */
#define I2C_M_NO_RD_ACK 0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_NOSTART 0x4000 /* if I2C_FUNC_NOSTART */
#define I2C_M_STOP 0x8000 /* if I2C_FUNC_PROTOCOL_MANGLING */
+#define I2C_M_RECV_LEN 0x0400 /* length will be first received byte */
+#define I2C_M_16BIT_REG 0x0002 /* indicate reg bit-width is 16bit */
+#define I2C_M_16BIT_DATA 0x0008 /* indicate data bit-width is 16bit */
+#define I2C_M_DMA 0x0004 /* indicate use dma mode */
__u16 len; /* msg length */
__u8 *buf; /* pointer to msg data */
};
diff -urN linux-4.9.37/include/uapi/linux/jffs2.h linux-4.9.y/include/uapi/linux/jffs2.h
--- linux-4.9.37/include/uapi/linux/jffs2.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/include/uapi/linux/jffs2.h 2021-06-07 13:01:34.000000000 +0300
@@ -46,6 +46,7 @@
#define JFFS2_COMPR_DYNRUBIN 0x05
#define JFFS2_COMPR_ZLIB 0x06
#define JFFS2_COMPR_LZO 0x07
+#define JFFS2_COMPR_LZMA 0x08
/* Compatibility flags. */
#define JFFS2_COMPAT_MASK 0xc000 /* What do to if an unknown nodetype is found */
#define JFFS2_NODE_ACCURATE 0x2000
diff -urN linux-4.9.37/include/uapi/linux/msdos_fs.h linux-4.9.y/include/uapi/linux/msdos_fs.h
--- linux-4.9.37/include/uapi/linux/msdos_fs.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/include/uapi/linux/msdos_fs.h 2021-06-07 13:01:34.000000000 +0300
@@ -95,7 +95,23 @@
unsigned short d_reclen;
char d_name[256]; /* We must not include limits.h! */
};
+#ifdef CONFIG_GOKE_MC
+struct fat_direntall {
+ unsigned long d_ino;
+ unsigned long d_off;
+ unsigned char d_type;
+ u64 d_size;
+ char d_createtime[8];
+ unsigned short d_reclen;
+ char d_name[1];
+};
+struct fat_direntall_buf {
+ int d_count;
+ int d_usecount;
+ struct fat_direntall direntall;
+};
+#endif
/*
* ioctl commands
*/
@@ -106,7 +122,9 @@
#define FAT_IOCTL_SET_ATTRIBUTES _IOW('r', 0x11, __u32)
/*Android kernel has used 0x12, so we use 0x13*/
#define FAT_IOCTL_GET_VOLUME_ID _IOR('r', 0x13, __u32)
-
+#ifdef CONFIG_GOKE_MC
+#define VFAT_IOCTL_READDIR_ALL _IOR('r', 0x14, struct fat_direntall_buf)
+#endif
struct fat_boot_sector {
__u8 ignored[3]; /* Boot strap short or near jump */
__u8 system_id[8]; /* Name - can be used to special case
diff -urN linux-4.9.37/include/uapi/linux/psci.h linux-4.9.y/include/uapi/linux/psci.h
--- linux-4.9.37/include/uapi/linux/psci.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/include/uapi/linux/psci.h 2021-06-07 13:01:34.000000000 +0300
@@ -87,6 +87,9 @@
(((ver) & PSCI_VERSION_MAJOR_MASK) >> PSCI_VERSION_MAJOR_SHIFT)
#define PSCI_VERSION_MINOR(ver) \
((ver) & PSCI_VERSION_MINOR_MASK)
+#define PSCI_VERSION(maj, min) \
+ ((((maj) << PSCI_VERSION_MAJOR_SHIFT) & PSCI_VERSION_MAJOR_MASK) | \
+ ((min) & PSCI_VERSION_MINOR_MASK))
/* PSCI features decoding (>=1.0) */
#define PSCI_1_0_FEATURES_CPU_SUSPEND_PF_SHIFT 1
diff -urN linux-4.9.37/include/uapi/linux/snmp.h linux-4.9.y/include/uapi/linux/snmp.h
--- linux-4.9.37/include/uapi/linux/snmp.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/include/uapi/linux/snmp.h 2021-06-07 13:01:34.000000000 +0300
@@ -281,6 +281,7 @@
LINUX_MIB_TCPKEEPALIVE, /* TCPKeepAlive */
LINUX_MIB_TCPMTUPFAIL, /* TCPMTUPFail */
LINUX_MIB_TCPMTUPSUCCESS, /* TCPMTUPSuccess */
+ LINUX_MIB_TCPWQUEUETOOBIG, /* TCPWqueueTooBig */
__LINUX_MIB_MAX
};
diff -urN linux-4.9.37/include/uapi/linux/usb/ch9.h linux-4.9.y/include/uapi/linux/usb/ch9.h
--- linux-4.9.37/include/uapi/linux/usb/ch9.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/include/uapi/linux/usb/ch9.h 2021-06-07 13:01:34.000000000 +0300
@@ -423,6 +423,14 @@
#define USB_ENDPOINT_XFER_INT 3
#define USB_ENDPOINT_MAX_ADJUSTABLE 0x80
+#define USB_EP_MAXP_MULT_SHIFT 11
+#define USB_EP_MAXP_MULT_MASK (3 << USB_EP_MAXP_MULT_SHIFT)
+#define USB_EP_MAXP_MULT(m) \
+ (((m) & USB_EP_MAXP_MULT_MASK) >> USB_EP_MAXP_MULT_SHIFT)
+
+
+#define USB_ENDPOINT_MAXP_MASK 0x07ff
+
/* The USB 3.0 spec redefines bits 5:4 of bmAttributes as interrupt ep type. */
#define USB_ENDPOINT_INTRTYPE 0x30
#define USB_ENDPOINT_INTR_PERIODIC (0 << 4)
@@ -623,11 +631,25 @@
* usb_endpoint_maxp - get endpoint's max packet size
* @epd: endpoint to be checked
*
- * Returns @epd's max packet
+ * Returns @epd's max packet bits [10:0]
*/
static inline int usb_endpoint_maxp(const struct usb_endpoint_descriptor *epd)
{
- return __le16_to_cpu(epd->wMaxPacketSize);
+ return __le16_to_cpu(epd->wMaxPacketSize) & USB_ENDPOINT_MAXP_MASK;
+}
+
+/**
+ * usb_endpoint_maxp_mult - get endpoint's transactional opportunities
+ * @epd: endpoint to be checked
+ *
+ * Return @epd's wMaxPacketSize[12:11] + 1
+ */
+static inline int
+usb_endpoint_maxp_mult(const struct usb_endpoint_descriptor *epd)
+{
+ int maxp = __le16_to_cpu(epd->wMaxPacketSize);
+
+ return USB_EP_MAXP_MULT(maxp) + 1;
}
static inline int usb_endpoint_interrupt_type(
diff -urN linux-4.9.37/include/uapi/linux/usb/video.h linux-4.9.y/include/uapi/linux/usb/video.h
--- linux-4.9.37/include/uapi/linux/usb/video.h 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/include/uapi/linux/usb/video.h 2021-06-07 13:01:34.000000000 +0300
@@ -303,7 +303,7 @@
__u8 iProcessing;
} __attribute__((__packed__));
-#define UVC_DT_PROCESSING_UNIT_SIZE(n) (9+(n))
+#define UVC_DT_PROCESSING_UNIT_SIZE(n) (10+(n))
/* 3.7.2.6. Extension Unit Descriptor */
struct uvc_extension_unit_descriptor {
@@ -340,6 +340,8 @@
__u8 iExtension; \
} __attribute__ ((packed))
+DECLARE_UVC_EXTENSION_UNIT_DESCRIPTOR(1,2);
+
/* 3.8.2.2. Video Control Interrupt Endpoint Descriptor */
struct uvc_control_endpoint_descriptor {
__u8 bLength;
@@ -565,5 +567,64 @@
__u32 dwFrameInterval[n]; \
} __attribute__ ((packed))
+
+/* 3.1.1 Frame Based Payload Video Format Descriptor */
+struct uvc_frame_based_format_desc {
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __u8 bDescriptorSubType;
+ __u8 bFormatIndex;
+ __u8 bNumFrameDescriptors;
+ __u8 guidFormat[16];
+ __u8 bBitsPerPixel;
+ __u8 bDefaultFrameIndex;
+ __u8 bAspectRatioX;
+ __u8 bAspectRatioY;
+ __u8 bmInterfaceFlags;
+ __u8 bCopyProtect;
+ __u8 bVariableSize;
+} __attribute__((__packed__));
+
+#define UVC_DT_FRAME_BASED_FORMAT_SIZE 28
+
+/* 3.1.2 Frame Based Payload Frame Descriptor */
+struct uvc_frame_based_frame_desc {
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __u8 bDescriptorSubType;
+ __u8 bFrameIndex;
+ __u8 bmCapabilities;
+ __u16 wWidth;
+ __u16 wHeight;
+ __u32 dwMinBitRate;
+ __u32 dwMaxBitRate;
+ __u32 dwDefaultFrameInterval;
+ __u8 bFrameIntervalType;
+ __u32 dwBytesPerLine;
+ __u32 dwFrameInterval[];
+} __attribute__((__packed__));
+
+#define UVC_DT_FRAME_BASED_FRAME_SIZE(n) (26+4*(n))
+
+#define UVC_FRAME_BASED(n) \
+ uvc_frame_based_desc##n
+
+#define DECLARE_UVC_FRAME_BASED(n) \
+struct UVC_FRAME_BASED(n) { \
+ __u8 bLength; \
+ __u8 bDescriptorType; \
+ __u8 bDescriptorSubType; \
+ __u8 bFrameIndex; \
+ __u8 bmCapabilities; \
+ __u16 wWidth; \
+ __u16 wHeight; \
+ __u32 dwMinBitRate; \
+ __u32 dwMaxBitRate; \
+ __u32 dwDefaultFrameInterval; \
+ __u8 bFrameIntervalType; \
+ __u32 dwBytesPerLine; \
+ __u32 dwFrameInterval[n]; \
+} __attribute__ ((packed))
+
#endif /* __LINUX_USB_VIDEO_H */
diff -urN linux-4.9.37/kernel/debug/kdb/.gitignore linux-4.9.y/kernel/debug/kdb/.gitignore
--- linux-4.9.37/kernel/debug/kdb/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/kernel/debug/kdb/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-gen-kdb_cmds.c
diff -urN linux-4.9.37/kernel/.gitignore linux-4.9.y/kernel/.gitignore
--- linux-4.9.37/kernel/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/kernel/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,7 +0,0 @@
-#
-# Generated files
-#
-config_data.h
-config_data.gz
-timeconst.h
-hz.bc
diff -urN linux-4.9.37/kernel/sched/cputime.c linux-4.9.y/kernel/sched/cputime.c
--- linux-4.9.37/kernel/sched/cputime.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/kernel/sched/cputime.c 2021-06-07 13:01:34.000000000 +0300
@@ -75,6 +75,9 @@
u64 *cpustat = kcpustat_this_cpu->cpustat;
cputime_t irq_cputime;
+ if (nsecs_to_cputime64(irqtime) <= cpustat[idx])
+ return 0;
+
irq_cputime = nsecs_to_cputime64(irqtime) - cpustat[idx];
irq_cputime = min(irq_cputime, maxtime);
cpustat[idx] += irq_cputime;
diff -urN linux-4.9.37/lib/.gitignore linux-4.9.y/lib/.gitignore
--- linux-4.9.37/lib/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/lib/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,6 +0,0 @@
-#
-# Generated files
-#
-gen_crc32table
-crc32table.h
-oid_registry_data.c
diff -urN linux-4.9.37/lib/Kconfig linux-4.9.y/lib/Kconfig
--- linux-4.9.37/lib/Kconfig 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/lib/Kconfig 2021-06-07 13:01:34.000000000 +0300
@@ -241,6 +241,12 @@
source "lib/xz/Kconfig"
+config LZMA_COMPRESS
+ tristate
+
+config LZMA_DECOMPRESS
+ tristate
+
#
# These all provide a common interface (hence the apparent duplication with
# ZLIB_INFLATE; DECOMPRESS_GZIP is just a wrapper.)
@@ -278,7 +284,7 @@
#
config REED_SOLOMON
tristate
-
+
config REED_SOLOMON_ENC8
bool
diff -urN linux-4.9.37/lib/lzma/LzFind.c linux-4.9.y/lib/lzma/LzFind.c
--- linux-4.9.37/lib/lzma/LzFind.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/lib/lzma/LzFind.c 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,711 @@
+/* LzFind.c -- Match finder for LZ algorithms
+2009-04-22 : Igor Pavlov : Public domain */
+
+#include <string.h>
+
+#include "LzFind.h"
+#include "LzHash.h"
+
+#define kEmptyHashValue 0
+#define kMaxValForNormalize ((UInt32)0xFFFFFFFF)
+#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */
+#define kNormalizeMask (~(kNormalizeStepMin - 1))
+#define kMaxHistorySize ((UInt32)3 << 30)
+
+#define kStartMaxLen 3
+
+static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc)
+{
+ if (!p->directInput) {
+ alloc->Free(alloc, p->bufferBase);
+ p->bufferBase = 0;
+ }
+}
+
+/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */
+
+static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc)
+{
+ UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv;
+ if (p->directInput) {
+ p->blockSize = blockSize;
+ return 1;
+ }
+ if (p->bufferBase == 0 || p->blockSize != blockSize) {
+ LzInWindow_Free(p, alloc);
+ p->blockSize = blockSize;
+ p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize);
+ }
+ return (p->bufferBase != 0);
+}
+
+Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p)
+{
+ return p->buffer;
+}
+
+Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index)
+{
+ return p->buffer[index];
+}
+
+UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p)
+{
+ return p->streamPos - p->pos;
+}
+
+void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue)
+{
+ p->posLimit -= subValue;
+ p->pos -= subValue;
+ p->streamPos -= subValue;
+}
+
+static void MatchFinder_ReadBlock(CMatchFinder *p)
+{
+ if (p->streamEndWasReached || p->result != SZ_OK)
+ return;
+ if (p->directInput) {
+ UInt32 curSize = 0xFFFFFFFF - p->streamPos;
+ if (curSize > p->directInputRem)
+ curSize = (UInt32)p->directInputRem;
+ p->directInputRem -= curSize;
+ p->streamPos += curSize;
+ if (p->directInputRem == 0)
+ p->streamEndWasReached = 1;
+ return;
+ }
+ for (;;) {
+ Byte *dest = p->buffer + (p->streamPos - p->pos);
+ size_t size = (p->bufferBase + p->blockSize - dest);
+ if (size == 0)
+ return;
+ p->result = p->stream->Read(p->stream, dest, &size);
+ if (p->result != SZ_OK)
+ return;
+ if (size == 0) {
+ p->streamEndWasReached = 1;
+ return;
+ }
+ p->streamPos += (UInt32)size;
+ if (p->streamPos - p->pos > p->keepSizeAfter)
+ return;
+ }
+}
+
+void MatchFinder_MoveBlock(CMatchFinder *p)
+{
+ memmove(p->bufferBase, p->buffer - p->keepSizeBefore,
+ (size_t)(p->streamPos - p->pos + p->keepSizeBefore));
+ p->buffer = p->bufferBase + p->keepSizeBefore;
+}
+
+int MatchFinder_NeedMove(CMatchFinder *p)
+{
+ if (p->directInput)
+ return 0;
+ /* if (p->streamEndWasReached) return 0; */
+ return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter);
+}
+
+void MatchFinder_ReadIfRequired(CMatchFinder *p)
+{
+ if (p->streamEndWasReached)
+ return;
+ if (p->keepSizeAfter >= p->streamPos - p->pos)
+ MatchFinder_ReadBlock(p);
+}
+
+static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p)
+{
+ if (MatchFinder_NeedMove(p))
+ MatchFinder_MoveBlock(p);
+ MatchFinder_ReadBlock(p);
+}
+
+static void MatchFinder_SetDefaultSettings(CMatchFinder *p)
+{
+ p->cutValue = 32;
+ p->btMode = 1;
+ p->numHashBytes = 4;
+ p->bigHash = 0;
+}
+
+#define kCrcPoly 0xEDB88320
+
+void MatchFinder_Construct(CMatchFinder *p)
+{
+ UInt32 i;
+ p->bufferBase = 0;
+ p->directInput = 0;
+ p->hash = 0;
+ MatchFinder_SetDefaultSettings(p);
+
+ for (i = 0; i < 256; i++) {
+ UInt32 r = i;
+ int j;
+ for (j = 0; j < 8; j++)
+ r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
+ p->crc[i] = r;
+ }
+}
+
+static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc)
+{
+ alloc->Free(alloc, p->hash);
+ p->hash = 0;
+}
+
+void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc)
+{
+ MatchFinder_FreeThisClassMemory(p, alloc);
+ LzInWindow_Free(p, alloc);
+}
+
+static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc)
+{
+ size_t sizeInBytes = (size_t)num * sizeof(CLzRef);
+ if (sizeInBytes / sizeof(CLzRef) != num)
+ return 0;
+ return (CLzRef *)alloc->Alloc(alloc, sizeInBytes);
+}
+
+int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
+ UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
+ ISzAlloc *alloc)
+{
+ UInt32 sizeReserv;
+ if (historySize > kMaxHistorySize) {
+ MatchFinder_Free(p, alloc);
+ return 0;
+ }
+ sizeReserv = historySize >> 1;
+ if (historySize > ((UInt32)2 << 30))
+ sizeReserv = historySize >> 2;
+ sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19);
+
+ p->keepSizeBefore = historySize + keepAddBufferBefore + 1;
+ p->keepSizeAfter = matchMaxLen + keepAddBufferAfter;
+ /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */
+ if (LzInWindow_Create(p, sizeReserv, alloc)) {
+ UInt32 newCyclicBufferSize = historySize + 1;
+ UInt32 hs;
+ p->matchMaxLen = matchMaxLen;
+ {
+ p->fixedHashSize = 0;
+ if (p->numHashBytes == 2) {
+ hs = (1 << 16) - 1;
+ } else {
+ hs = historySize - 1;
+ hs |= (hs >> 1);
+ hs |= (hs >> 2);
+ hs |= (hs >> 4);
+ hs |= (hs >> 8);
+ hs >>= 1;
+ hs |= 0xFFFF; /* don't change it! It's required for Deflate */
+ if (hs > (1 << 24)) {
+ if (p->numHashBytes == 3)
+ hs = (1 << 24) - 1;
+ else
+ hs >>= 1;
+ }
+ }
+ p->hashMask = hs;
+ hs++;
+ if (p->numHashBytes > 2)
+ p->fixedHashSize += kHash2Size;
+ if (p->numHashBytes > 3)
+ p->fixedHashSize += kHash3Size;
+ if (p->numHashBytes > 4)
+ p->fixedHashSize += kHash4Size;
+ hs += p->fixedHashSize;
+ }
+
+ {
+ UInt32 prevSize = p->hashSizeSum + p->numSons;
+ UInt32 newSize;
+ p->historySize = historySize;
+ p->hashSizeSum = hs;
+ p->cyclicBufferSize = newCyclicBufferSize;
+ p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize);
+ newSize = p->hashSizeSum + p->numSons;
+ if (p->hash != 0 && prevSize == newSize)
+ return 1;
+ MatchFinder_FreeThisClassMemory(p, alloc);
+ p->hash = AllocRefs(newSize, alloc);
+ if (p->hash != 0) {
+ p->son = p->hash + p->hashSizeSum;
+ return 1;
+ }
+ }
+ }
+ MatchFinder_Free(p, alloc);
+ return 0;
+}
+
+static void MatchFinder_SetLimits(CMatchFinder *p)
+{
+ UInt32 limit = kMaxValForNormalize - p->pos;
+ UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos;
+ if (limit2 < limit)
+ limit = limit2;
+ limit2 = p->streamPos - p->pos;
+ if (limit2 <= p->keepSizeAfter) {
+ if (limit2 > 0)
+ limit2 = 1;
+ } else
+ limit2 -= p->keepSizeAfter;
+ if (limit2 < limit)
+ limit = limit2;
+ {
+ UInt32 lenLimit = p->streamPos - p->pos;
+ if (lenLimit > p->matchMaxLen)
+ lenLimit = p->matchMaxLen;
+ p->lenLimit = lenLimit;
+ }
+ p->posLimit = p->pos + limit;
+}
+
+void MatchFinder_Init(CMatchFinder *p)
+{
+ UInt32 i;
+ for (i = 0; i < p->hashSizeSum; i++)
+ p->hash[i] = kEmptyHashValue;
+ p->cyclicBufferPos = 0;
+ p->buffer = p->bufferBase;
+ p->pos = p->streamPos = p->cyclicBufferSize;
+ p->result = SZ_OK;
+ p->streamEndWasReached = 0;
+ MatchFinder_ReadBlock(p);
+ MatchFinder_SetLimits(p);
+}
+
+static UInt32 MatchFinder_GetSubValue(CMatchFinder *p)
+{
+ return (p->pos - p->historySize - 1) & kNormalizeMask;
+}
+
+void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems)
+{
+ UInt32 i;
+ for (i = 0; i < numItems; i++) {
+ UInt32 value = items[i];
+ if (value <= subValue)
+ value = kEmptyHashValue;
+ else
+ value -= subValue;
+ items[i] = value;
+ }
+}
+
+static void MatchFinder_Normalize(CMatchFinder *p)
+{
+ UInt32 subValue = MatchFinder_GetSubValue(p);
+ MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons);
+ MatchFinder_ReduceOffsets(p, subValue);
+}
+
+static void MatchFinder_CheckLimits(CMatchFinder *p)
+{
+ if (p->pos == kMaxValForNormalize)
+ MatchFinder_Normalize(p);
+ if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos)
+ MatchFinder_CheckAndMoveAndRead(p);
+ if (p->cyclicBufferPos == p->cyclicBufferSize)
+ p->cyclicBufferPos = 0;
+ MatchFinder_SetLimits(p);
+}
+
+static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
+ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
+ UInt32 *distances, UInt32 maxLen)
+{
+ son[_cyclicBufferPos] = curMatch;
+ for (;;) {
+ UInt32 delta = pos - curMatch;
+ if (cutValue-- == 0 || delta >= _cyclicBufferSize)
+ return distances;
+ {
+ const Byte *pb = cur - delta;
+ curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)];
+ if (pb[maxLen] == cur[maxLen] && *pb == *cur) {
+ UInt32 len = 0;
+ while (++len != lenLimit)
+ if (pb[len] != cur[len])
+ break;
+ if (maxLen < len) {
+ *distances++ = maxLen = len;
+ *distances++ = delta - 1;
+ if (len == lenLimit)
+ return distances;
+ }
+ }
+ }
+ }
+}
+
+UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
+ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
+ UInt32 *distances, UInt32 maxLen)
+{
+ CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
+ CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
+ UInt32 len0 = 0, len1 = 0;
+ for (;;) {
+ UInt32 delta = pos - curMatch;
+ if (cutValue-- == 0 || delta >= _cyclicBufferSize) {
+ *ptr0 = *ptr1 = kEmptyHashValue;
+ return distances;
+ }
+ {
+ CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
+ const Byte *pb = cur - delta;
+ UInt32 len = (len0 < len1 ? len0 : len1);
+ if (pb[len] == cur[len]) {
+ if (++len != lenLimit && pb[len] == cur[len])
+ while (++len != lenLimit)
+ if (pb[len] != cur[len])
+ break;
+ if (maxLen < len) {
+ *distances++ = maxLen = len;
+ *distances++ = delta - 1;
+ if (len == lenLimit) {
+ *ptr1 = pair[0];
+ *ptr0 = pair[1];
+ return distances;
+ }
+ }
+ }
+ if (pb[len] < cur[len]) {
+ *ptr1 = curMatch;
+ ptr1 = pair + 1;
+ curMatch = *ptr1;
+ len1 = len;
+ } else {
+ *ptr0 = curMatch;
+ ptr0 = pair;
+ curMatch = *ptr0;
+ len0 = len;
+ }
+ }
+ }
+}
+
+static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
+ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue)
+{
+ CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
+ CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
+ UInt32 len0 = 0, len1 = 0;
+ for (;;) {
+ UInt32 delta = pos - curMatch;
+ if (cutValue-- == 0 || delta >= _cyclicBufferSize) {
+ *ptr0 = *ptr1 = kEmptyHashValue;
+ return;
+ }
+ {
+ CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
+ const Byte *pb = cur - delta;
+ UInt32 len = (len0 < len1 ? len0 : len1);
+ if (pb[len] == cur[len]) {
+ while (++len != lenLimit)
+ if (pb[len] != cur[len])
+ break;
+ {
+ if (len == lenLimit) {
+ *ptr1 = pair[0];
+ *ptr0 = pair[1];
+ return;
+ }
+ }
+ }
+ if (pb[len] < cur[len]) {
+ *ptr1 = curMatch;
+ ptr1 = pair + 1;
+ curMatch = *ptr1;
+ len1 = len;
+ } else {
+ *ptr0 = curMatch;
+ ptr0 = pair;
+ curMatch = *ptr0;
+ len0 = len;
+ }
+ }
+ }
+}
+
+#define MOVE_POS \
+ ++p->cyclicBufferPos; \
+ p->buffer++; \
+ if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p);
+
+#define MOVE_POS_RET MOVE_POS return offset;
+
+static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; }
+
+#define GET_MATCHES_HEADER2(minLen, ret_op) \
+ UInt32 lenLimit; UInt32 hashValue = 0; const Byte *cur; UInt32 curMatch; \
+ lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \
+ cur = p->buffer;
+
+#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0)
+#define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue)
+
+#define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue
+
+#define GET_MATCHES_FOOTER(offset, maxLen) \
+ offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \
+ distances + offset, maxLen) - distances); MOVE_POS_RET;
+
+#define SKIP_FOOTER \
+ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;
+
+static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+ UInt32 offset;
+ GET_MATCHES_HEADER(2)
+ HASH2_CALC;
+ curMatch = p->hash[hashValue];
+ p->hash[hashValue] = p->pos;
+ offset = 0;
+ GET_MATCHES_FOOTER(offset, 1)
+}
+
+UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+ UInt32 offset;
+ GET_MATCHES_HEADER(3)
+ HASH_ZIP_CALC;
+ curMatch = p->hash[hashValue];
+ p->hash[hashValue] = p->pos;
+ offset = 0;
+ GET_MATCHES_FOOTER(offset, 2)
+}
+
+static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+ UInt32 hash2Value = 0, delta2, maxLen, offset;
+ GET_MATCHES_HEADER(3)
+
+ HASH3_CALC;
+
+ delta2 = p->pos - p->hash[hash2Value];
+ curMatch = p->hash[kFix3HashSize + hashValue];
+
+ p->hash[hash2Value] =
+ p->hash[kFix3HashSize + hashValue] = p->pos;
+
+
+ maxLen = 2;
+ offset = 0;
+ if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) {
+ for (; maxLen != lenLimit; maxLen++)
+ if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
+ break;
+ distances[0] = maxLen;
+ distances[1] = delta2 - 1;
+ offset = 2;
+ if (maxLen == lenLimit) {
+ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
+ MOVE_POS_RET;
+ }
+ }
+ GET_MATCHES_FOOTER(offset, maxLen)
+}
+
+static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+ UInt32 hash2Value = 0, hash3Value = 0, delta2, delta3, maxLen, offset;
+ GET_MATCHES_HEADER(4)
+
+ HASH4_CALC;
+
+ delta2 = p->pos - p->hash[ hash2Value];
+ delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];
+ curMatch = p->hash[kFix4HashSize + hashValue];
+
+ p->hash[ hash2Value] =
+ p->hash[kFix3HashSize + hash3Value] =
+ p->hash[kFix4HashSize + hashValue] = p->pos;
+
+ maxLen = 1;
+ offset = 0;
+ if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) {
+ distances[0] = maxLen = 2;
+ distances[1] = delta2 - 1;
+ offset = 2;
+ }
+ if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) {
+ maxLen = 3;
+ distances[offset + 1] = delta3 - 1;
+ offset += 2;
+ delta2 = delta3;
+ }
+ if (offset != 0) {
+ for (; maxLen != lenLimit; maxLen++)
+ if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
+ break;
+ distances[offset - 2] = maxLen;
+ if (maxLen == lenLimit) {
+ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
+ MOVE_POS_RET;
+ }
+ }
+ if (maxLen < 3)
+ maxLen = 3;
+ GET_MATCHES_FOOTER(offset, maxLen)
+}
+
+static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+ UInt32 hash2Value = 0, hash3Value = 0, delta2, delta3, maxLen, offset;
+ GET_MATCHES_HEADER(4)
+
+ HASH4_CALC;
+
+ delta2 = p->pos - p->hash[hash2Value];
+ delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];
+ curMatch = p->hash[kFix4HashSize + hashValue];
+
+ p->hash[hash2Value] =
+ p->hash[kFix3HashSize + hash3Value] =
+ p->hash[kFix4HashSize + hashValue] = p->pos;
+
+ maxLen = 1;
+ offset = 0;
+ if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) {
+ distances[0] = maxLen = 2;
+ distances[1] = delta2 - 1;
+ offset = 2;
+ }
+ if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) {
+ maxLen = 3;
+ distances[offset + 1] = delta3 - 1;
+ offset += 2;
+ delta2 = delta3;
+ }
+ if (offset != 0) {
+ for (; maxLen != lenLimit; maxLen++)
+ if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
+ break;
+ distances[offset - 2] = maxLen;
+ if (maxLen == lenLimit) {
+ p->son[p->cyclicBufferPos] = curMatch;
+ MOVE_POS_RET;
+ }
+ }
+ if (maxLen < 3)
+ maxLen = 3;
+ offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
+ distances + offset, maxLen) - (distances));
+ MOVE_POS_RET
+}
+
+UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+ UInt32 offset;
+ GET_MATCHES_HEADER(3)
+ HASH_ZIP_CALC;
+ curMatch = p->hash[hashValue];
+ p->hash[hashValue] = p->pos;
+ offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
+ distances, 2) - (distances));
+ MOVE_POS_RET
+}
+
+static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+ do {
+ SKIP_HEADER(2)
+ HASH2_CALC;
+ curMatch = p->hash[hashValue];
+ p->hash[hashValue] = p->pos;
+ SKIP_FOOTER
+ } while (--num != 0);
+}
+
+void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+ do {
+ SKIP_HEADER(3)
+ HASH_ZIP_CALC;
+ curMatch = p->hash[hashValue];
+ p->hash[hashValue] = p->pos;
+ SKIP_FOOTER
+ } while (--num != 0);
+}
+
+static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+ do {
+ UInt32 hash2Value = 0;
+ SKIP_HEADER(3)
+ HASH3_CALC;
+ curMatch = p->hash[kFix3HashSize + hashValue];
+ p->hash[hash2Value] =
+ p->hash[kFix3HashSize + hashValue] = p->pos;
+ SKIP_FOOTER
+ } while (--num != 0);
+}
+
+static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+ do {
+ UInt32 hash2Value = 0, hash3Value = 0;
+ SKIP_HEADER(4)
+ HASH4_CALC;
+ curMatch = p->hash[kFix4HashSize + hashValue];
+ p->hash[ hash2Value] =
+ p->hash[kFix3HashSize + hash3Value] = p->pos;
+ p->hash[kFix4HashSize + hashValue] = p->pos;
+ SKIP_FOOTER
+ } while (--num != 0);
+}
+
+static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+ do {
+ UInt32 hash2Value = 0, hash3Value = 0;
+ SKIP_HEADER(4)
+ HASH4_CALC;
+ curMatch = p->hash[kFix4HashSize + hashValue];
+ p->hash[ hash2Value] =
+ p->hash[kFix3HashSize + hash3Value] =
+ p->hash[kFix4HashSize + hashValue] = p->pos;
+ p->son[p->cyclicBufferPos] = curMatch;
+ MOVE_POS
+ } while (--num != 0);
+}
+
+void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+ do {
+ SKIP_HEADER(3)
+ HASH_ZIP_CALC;
+ curMatch = p->hash[hashValue];
+ p->hash[hashValue] = p->pos;
+ p->son[p->cyclicBufferPos] = curMatch;
+ MOVE_POS
+ } while (--num != 0);
+}
+
+void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable)
+{
+ vTable->Init = (Mf_Init_Func)MatchFinder_Init;
+ vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte;
+ vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes;
+ vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos;
+ if (!p->btMode) {
+ vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches;
+ vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip;
+ } else if (p->numHashBytes == 2) {
+ vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches;
+ vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip;
+ } else if (p->numHashBytes == 3) {
+ vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches;
+ vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip;
+ } else {
+ vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches;
+ vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip;
+ }
+}
diff -urN linux-4.9.37/lib/lzma/LzmaDec.c linux-4.9.y/lib/lzma/LzmaDec.c
--- linux-4.9.37/lib/lzma/LzmaDec.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/lib/lzma/LzmaDec.c 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,999 @@
+/* LzmaDec.c -- LZMA Decoder
+2009-09-20 : Igor Pavlov : Public domain */
+
+#include "LzmaDec.h"
+
+#include <string.h>
+
+#define kNumTopBits 24
+#define kTopValue ((UInt32)1 << kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
+#define kNumMoveBits 5
+
+#define RC_INIT_SIZE 5
+
+#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); }
+
+#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
+#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
+#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits));
+#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \
+ { UPDATE_0(p); i = (i + i); A0; } else \
+ { UPDATE_1(p); i = (i + i) + 1; A1; }
+#define GET_BIT(p, i) GET_BIT2(p, i, ; , ;)
+
+#define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); }
+#define TREE_DECODE(probs, limit, i) \
+ { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; }
+
+/* #define _LZMA_SIZE_OPT */
+
+#ifdef _LZMA_SIZE_OPT
+#define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i)
+#else
+#define TREE_6_DECODE(probs, i) \
+ { i = 1; \
+ TREE_GET_BIT(probs, i); \
+ TREE_GET_BIT(probs, i); \
+ TREE_GET_BIT(probs, i); \
+ TREE_GET_BIT(probs, i); \
+ TREE_GET_BIT(probs, i); \
+ TREE_GET_BIT(probs, i); \
+ i -= 0x40; }
+#endif
+
+#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); }
+
+#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
+#define UPDATE_0_CHECK range = bound;
+#define UPDATE_1_CHECK range -= bound; code -= bound;
+#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \
+ { UPDATE_0_CHECK; i = (i + i); A0; } else \
+ { UPDATE_1_CHECK; i = (i + i) + 1; A1; }
+#define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;)
+#define TREE_DECODE_CHECK(probs, limit, i) \
+ { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; }
+
+
+#define kNumPosBitsMax 4
+#define kNumPosStatesMax (1 << kNumPosBitsMax)
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
+#define kLenNumMidBits 3
+#define kLenNumMidSymbols (1 << kLenNumMidBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
+
+#define LenChoice 0
+#define LenChoice2 (LenChoice + 1)
+#define LenLow (LenChoice2 + 1)
+#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
+#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
+#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
+
+
+#define kNumStates 12
+#define kNumLitStates 7
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+
+#define kNumPosSlotBits 6
+#define kNumLenToPosStates 4
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 << kNumAlignBits)
+
+#define kMatchMinLen 2
+#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)
+
+#define IsMatch 0
+#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
+#define IsRepG0 (IsRep + kNumStates)
+#define IsRepG1 (IsRepG0 + kNumStates)
+#define IsRepG2 (IsRepG1 + kNumStates)
+#define IsRep0Long (IsRepG2 + kNumStates)
+#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
+#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
+#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
+#define LenCoder (Align + kAlignTableSize)
+#define RepLenCoder (LenCoder + kNumLenProbs)
+#define Literal (RepLenCoder + kNumLenProbs)
+
+#define LZMA_BASE_SIZE 1846
+#define LZMA_LIT_SIZE 768
+
+#define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp)))
+
+#if Literal != LZMA_BASE_SIZE
+StopCompilingDueBUG
+#endif
+
+#define LZMA_DIC_MIN (1 << 12)
+
+/* First LZMA-symbol is always decoded.
+And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization
+Out:
+ Result:
+ SZ_OK - OK
+ SZ_ERROR_DATA - Error
+ p->remainLen:
+ < kMatchSpecLenStart : normal remain
+ = kMatchSpecLenStart : finished
+ = kMatchSpecLenStart + 1 : Flush marker
+ = kMatchSpecLenStart + 2 : State Init Marker
+*/
+
+static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
+{
+ CLzmaProb *probs = p->probs;
+
+ unsigned state = p->state;
+ UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3];
+ unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1;
+ unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1;
+ unsigned lc = p->prop.lc;
+
+ Byte *dic = p->dic;
+ SizeT dicBufSize = p->dicBufSize;
+ SizeT dicPos = p->dicPos;
+
+ UInt32 processedPos = p->processedPos;
+ UInt32 checkDicSize = p->checkDicSize;
+ unsigned len = 0;
+
+ const Byte *buf = p->buf;
+ UInt32 range = p->range;
+ UInt32 code = p->code;
+
+ do
+ {
+ CLzmaProb *prob;
+ UInt32 bound;
+ unsigned ttt;
+ unsigned posState = processedPos & pbMask;
+
+ prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;
+ IF_BIT_0(prob)
+ {
+ unsigned symbol;
+ UPDATE_0(prob);
+ prob = probs + Literal;
+ if (checkDicSize != 0 || processedPos != 0)
+ prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) +
+ (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc))));
+
+ if (state < kNumLitStates)
+ {
+ state -= (state < 4) ? state : 3;
+ symbol = 1;
+ do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100);
+ }
+ else
+ {
+ unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
+ unsigned offs = 0x100;
+ state -= (state < 10) ? 3 : 6;
+ symbol = 1;
+ do
+ {
+ unsigned bit;
+ CLzmaProb *probLit;
+ matchByte <<= 1;
+ bit = (matchByte & offs);
+ probLit = prob + offs + bit + symbol;
+ GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit)
+ }
+ while (symbol < 0x100);
+ }
+ dic[dicPos++] = (Byte)symbol;
+ processedPos++;
+ continue;
+ }
+ else
+ {
+ UPDATE_1(prob);
+ prob = probs + IsRep + state;
+ IF_BIT_0(prob)
+ {
+ UPDATE_0(prob);
+ state += kNumStates;
+ prob = probs + LenCoder;
+ }
+ else
+ {
+ UPDATE_1(prob);
+ if (checkDicSize == 0 && processedPos == 0)
+ return SZ_ERROR_DATA;
+ prob = probs + IsRepG0 + state;
+ IF_BIT_0(prob)
+ {
+ UPDATE_0(prob);
+ prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;
+ IF_BIT_0(prob)
+ {
+ UPDATE_0(prob);
+ dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
+ dicPos++;
+ processedPos++;
+ state = state < kNumLitStates ? 9 : 11;
+ continue;
+ }
+ UPDATE_1(prob);
+ }
+ else
+ {
+ UInt32 distance;
+ UPDATE_1(prob);
+ prob = probs + IsRepG1 + state;
+ IF_BIT_0(prob)
+ {
+ UPDATE_0(prob);
+ distance = rep1;
+ }
+ else
+ {
+ UPDATE_1(prob);
+ prob = probs + IsRepG2 + state;
+ IF_BIT_0(prob)
+ {
+ UPDATE_0(prob);
+ distance = rep2;
+ }
+ else
+ {
+ UPDATE_1(prob);
+ distance = rep3;
+ rep3 = rep2;
+ }
+ rep2 = rep1;
+ }
+ rep1 = rep0;
+ rep0 = distance;
+ }
+ state = state < kNumLitStates ? 8 : 11;
+ prob = probs + RepLenCoder;
+ }
+ {
+ unsigned limit, offset;
+ CLzmaProb *probLen = prob + LenChoice;
+ IF_BIT_0(probLen)
+ {
+ UPDATE_0(probLen);
+ probLen = prob + LenLow + (posState << kLenNumLowBits);
+ offset = 0;
+ limit = (1 << kLenNumLowBits);
+ }
+ else
+ {
+ UPDATE_1(probLen);
+ probLen = prob + LenChoice2;
+ IF_BIT_0(probLen)
+ {
+ UPDATE_0(probLen);
+ probLen = prob + LenMid + (posState << kLenNumMidBits);
+ offset = kLenNumLowSymbols;
+ limit = (1 << kLenNumMidBits);
+ }
+ else
+ {
+ UPDATE_1(probLen);
+ probLen = prob + LenHigh;
+ offset = kLenNumLowSymbols + kLenNumMidSymbols;
+ limit = (1 << kLenNumHighBits);
+ }
+ }
+ TREE_DECODE(probLen, limit, len);
+ len += offset;
+ }
+
+ if (state >= kNumStates)
+ {
+ UInt32 distance;
+ prob = probs + PosSlot +
+ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits);
+ TREE_6_DECODE(prob, distance);
+ if (distance >= kStartPosModelIndex)
+ {
+ unsigned posSlot = (unsigned)distance;
+ int numDirectBits = (int)(((distance >> 1) - 1));
+ distance = (2 | (distance & 1));
+ if (posSlot < kEndPosModelIndex)
+ {
+ distance <<= numDirectBits;
+ prob = probs + SpecPos + distance - posSlot - 1;
+ {
+ UInt32 mask = 1;
+ unsigned i = 1;
+ do
+ {
+ GET_BIT2(prob + i, i, ; , distance |= mask);
+ mask <<= 1;
+ }
+ while (--numDirectBits != 0);
+ }
+ }
+ else
+ {
+ numDirectBits -= kNumAlignBits;
+ do
+ {
+ NORMALIZE
+ range >>= 1;
+
+ {
+ UInt32 t;
+ code -= range;
+ t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */
+ distance = (distance << 1) + (t + 1);
+ code += range & t;
+ }
+ /*
+ distance <<= 1;
+ if (code >= range)
+ {
+ code -= range;
+ distance |= 1;
+ }
+ */
+ }
+ while (--numDirectBits != 0);
+ prob = probs + Align;
+ distance <<= kNumAlignBits;
+ {
+ unsigned i = 1;
+ GET_BIT2(prob + i, i, ; , distance |= 1);
+ GET_BIT2(prob + i, i, ; , distance |= 2);
+ GET_BIT2(prob + i, i, ; , distance |= 4);
+ GET_BIT2(prob + i, i, ; , distance |= 8);
+ }
+ if (distance == (UInt32)0xFFFFFFFF)
+ {
+ len += kMatchSpecLenStart;
+ state -= kNumStates;
+ break;
+ }
+ }
+ }
+ rep3 = rep2;
+ rep2 = rep1;
+ rep1 = rep0;
+ rep0 = distance + 1;
+ if (checkDicSize == 0)
+ {
+ if (distance >= processedPos)
+ return SZ_ERROR_DATA;
+ }
+ else if (distance >= checkDicSize)
+ return SZ_ERROR_DATA;
+ state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;
+ }
+
+ len += kMatchMinLen;
+
+ if (limit == dicPos)
+ return SZ_ERROR_DATA;
+ {
+ SizeT rem = limit - dicPos;
+ unsigned curLen = ((rem < len) ? (unsigned)rem : len);
+ SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0);
+
+ processedPos += curLen;
+
+ len -= curLen;
+ if (pos + curLen <= dicBufSize)
+ {
+ Byte *dest = dic + dicPos;
+ ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos;
+ const Byte *lim = dest + curLen;
+ dicPos += curLen;
+ do
+ *(dest) = (Byte)*(dest + src);
+ while (++dest != lim);
+ }
+ else
+ {
+ do
+ {
+ dic[dicPos++] = dic[pos];
+ if (++pos == dicBufSize)
+ pos = 0;
+ }
+ while (--curLen != 0);
+ }
+ }
+ }
+ }
+ while (dicPos < limit && buf < bufLimit);
+ NORMALIZE;
+ p->buf = buf;
+ p->range = range;
+ p->code = code;
+ p->remainLen = len;
+ p->dicPos = dicPos;
+ p->processedPos = processedPos;
+ p->reps[0] = rep0;
+ p->reps[1] = rep1;
+ p->reps[2] = rep2;
+ p->reps[3] = rep3;
+ p->state = state;
+
+ return SZ_OK;
+}
+
+static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
+{
+ if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart)
+ {
+ Byte *dic = p->dic;
+ SizeT dicPos = p->dicPos;
+ SizeT dicBufSize = p->dicBufSize;
+ unsigned len = p->remainLen;
+ UInt32 rep0 = p->reps[0];
+ if (limit - dicPos < len)
+ len = (unsigned)(limit - dicPos);
+
+ if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len)
+ p->checkDicSize = p->prop.dicSize;
+
+ p->processedPos += len;
+ p->remainLen -= len;
+ while (len-- != 0)
+ {
+ dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
+ dicPos++;
+ }
+ p->dicPos = dicPos;
+ }
+}
+
+static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
+{
+ do
+ {
+ SizeT limit2 = limit;
+ if (p->checkDicSize == 0)
+ {
+ UInt32 rem = p->prop.dicSize - p->processedPos;
+ if (limit - p->dicPos > rem)
+ limit2 = p->dicPos + rem;
+ }
+ RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit));
+ if (p->processedPos >= p->prop.dicSize)
+ p->checkDicSize = p->prop.dicSize;
+ LzmaDec_WriteRem(p, limit);
+ }
+ while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart);
+
+ if (p->remainLen > kMatchSpecLenStart)
+ {
+ p->remainLen = kMatchSpecLenStart;
+ }
+ return 0;
+}
+
+typedef enum
+{
+ DUMMY_ERROR, /* unexpected end of input stream */
+ DUMMY_LIT,
+ DUMMY_MATCH,
+ DUMMY_REP
+} ELzmaDummy;
+
+static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize)
+{
+ UInt32 range = p->range;
+ UInt32 code = p->code;
+ const Byte *bufLimit = buf + inSize;
+ CLzmaProb *probs = p->probs;
+ unsigned state = p->state;
+ ELzmaDummy res;
+
+ {
+ CLzmaProb *prob;
+ UInt32 bound;
+ unsigned ttt;
+ unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1);
+
+ prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;
+ IF_BIT_0_CHECK(prob)
+ {
+ UPDATE_0_CHECK
+
+ /* if (bufLimit - buf >= 7) return DUMMY_LIT; */
+
+ prob = probs + Literal;
+ if (p->checkDicSize != 0 || p->processedPos != 0)
+ prob += (LZMA_LIT_SIZE *
+ ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) +
+ (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc))));
+
+ if (state < kNumLitStates)
+ {
+ unsigned symbol = 1;
+ do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100);
+ }
+ else
+ {
+ unsigned matchByte = p->dic[p->dicPos - p->reps[0] +
+ ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)];
+ unsigned offs = 0x100;
+ unsigned symbol = 1;
+ do
+ {
+ unsigned bit;
+ CLzmaProb *probLit;
+ matchByte <<= 1;
+ bit = (matchByte & offs);
+ probLit = prob + offs + bit + symbol;
+ GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit)
+ }
+ while (symbol < 0x100);
+ }
+ res = DUMMY_LIT;
+ }
+ else
+ {
+ unsigned len;
+ UPDATE_1_CHECK;
+
+ prob = probs + IsRep + state;
+ IF_BIT_0_CHECK(prob)
+ {
+ UPDATE_0_CHECK;
+ state = 0;
+ prob = probs + LenCoder;
+ res = DUMMY_MATCH;
+ }
+ else
+ {
+ UPDATE_1_CHECK;
+ res = DUMMY_REP;
+ prob = probs + IsRepG0 + state;
+ IF_BIT_0_CHECK(prob)
+ {
+ UPDATE_0_CHECK;
+ prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;
+ IF_BIT_0_CHECK(prob)
+ {
+ UPDATE_0_CHECK;
+ NORMALIZE_CHECK;
+ return DUMMY_REP;
+ }
+ else
+ {
+ UPDATE_1_CHECK;
+ }
+ }
+ else
+ {
+ UPDATE_1_CHECK;
+ prob = probs + IsRepG1 + state;
+ IF_BIT_0_CHECK(prob)
+ {
+ UPDATE_0_CHECK;
+ }
+ else
+ {
+ UPDATE_1_CHECK;
+ prob = probs + IsRepG2 + state;
+ IF_BIT_0_CHECK(prob)
+ {
+ UPDATE_0_CHECK;
+ }
+ else
+ {
+ UPDATE_1_CHECK;
+ }
+ }
+ }
+ state = kNumStates;
+ prob = probs + RepLenCoder;
+ }
+ {
+ unsigned limit, offset;
+ CLzmaProb *probLen = prob + LenChoice;
+ IF_BIT_0_CHECK(probLen)
+ {
+ UPDATE_0_CHECK;
+ probLen = prob + LenLow + (posState << kLenNumLowBits);
+ offset = 0;
+ limit = 1 << kLenNumLowBits;
+ }
+ else
+ {
+ UPDATE_1_CHECK;
+ probLen = prob + LenChoice2;
+ IF_BIT_0_CHECK(probLen)
+ {
+ UPDATE_0_CHECK;
+ probLen = prob + LenMid + (posState << kLenNumMidBits);
+ offset = kLenNumLowSymbols;
+ limit = 1 << kLenNumMidBits;
+ }
+ else
+ {
+ UPDATE_1_CHECK;
+ probLen = prob + LenHigh;
+ offset = kLenNumLowSymbols + kLenNumMidSymbols;
+ limit = 1 << kLenNumHighBits;
+ }
+ }
+ TREE_DECODE_CHECK(probLen, limit, len);
+ len += offset;
+ }
+
+ if (state < 4)
+ {
+ unsigned posSlot;
+ prob = probs + PosSlot +
+ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
+ kNumPosSlotBits);
+ TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot);
+ if (posSlot >= kStartPosModelIndex)
+ {
+ int numDirectBits = ((posSlot >> 1) - 1);
+
+ /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */
+
+ if (posSlot < kEndPosModelIndex)
+ {
+ prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1;
+ }
+ else
+ {
+ numDirectBits -= kNumAlignBits;
+ do
+ {
+ NORMALIZE_CHECK
+ range >>= 1;
+ code -= range & (((code - range) >> 31) - 1);
+ /* if (code >= range) code -= range; */
+ }
+ while (--numDirectBits != 0);
+ prob = probs + Align;
+ numDirectBits = kNumAlignBits;
+ }
+ {
+ unsigned i = 1;
+ do
+ {
+ GET_BIT_CHECK(prob + i, i);
+ }
+ while (--numDirectBits != 0);
+ }
+ }
+ }
+ }
+ }
+ NORMALIZE_CHECK;
+ return res;
+}
+
+
+static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data)
+{
+ p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]);
+ p->range = 0xFFFFFFFF;
+ p->needFlush = 0;
+}
+
+void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState)
+{
+ p->needFlush = 1;
+ p->remainLen = 0;
+ p->tempBufSize = 0;
+
+ if (initDic)
+ {
+ p->processedPos = 0;
+ p->checkDicSize = 0;
+ p->needInitState = 1;
+ }
+ if (initState)
+ p->needInitState = 1;
+}
+
+void LzmaDec_Init(CLzmaDec *p)
+{
+ p->dicPos = 0;
+ LzmaDec_InitDicAndState(p, True, True);
+}
+
+static void LzmaDec_InitStateReal(CLzmaDec *p)
+{
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp));
+ UInt32 i;
+ CLzmaProb *probs = p->probs;
+ for (i = 0; i < numProbs; i++)
+ probs[i] = kBitModelTotal >> 1;
+ p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1;
+ p->state = 0;
+ p->needInitState = 0;
+}
+
+SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen,
+ ELzmaFinishMode finishMode, ELzmaStatus *status)
+{
+ SizeT inSize = *srcLen;
+ (*srcLen) = 0;
+ LzmaDec_WriteRem(p, dicLimit);
+
+ *status = LZMA_STATUS_NOT_SPECIFIED;
+
+ while (p->remainLen != kMatchSpecLenStart)
+ {
+ int checkEndMarkNow;
+
+ if (p->needFlush != 0)
+ {
+ for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--)
+ p->tempBuf[p->tempBufSize++] = *src++;
+ if (p->tempBufSize < RC_INIT_SIZE)
+ {
+ *status = LZMA_STATUS_NEEDS_MORE_INPUT;
+ return SZ_OK;
+ }
+ if (p->tempBuf[0] != 0)
+ return SZ_ERROR_DATA;
+
+ LzmaDec_InitRc(p, p->tempBuf);
+ p->tempBufSize = 0;
+ }
+
+ checkEndMarkNow = 0;
+ if (p->dicPos >= dicLimit)
+ {
+ if (p->remainLen == 0 && p->code == 0)
+ {
+ *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK;
+ return SZ_OK;
+ }
+ if (finishMode == LZMA_FINISH_ANY)
+ {
+ *status = LZMA_STATUS_NOT_FINISHED;
+ return SZ_OK;
+ }
+ if (p->remainLen != 0)
+ {
+ *status = LZMA_STATUS_NOT_FINISHED;
+ return SZ_ERROR_DATA;
+ }
+ checkEndMarkNow = 1;
+ }
+
+ if (p->needInitState)
+ LzmaDec_InitStateReal(p);
+
+ if (p->tempBufSize == 0)
+ {
+ SizeT processed;
+ const Byte *bufLimit = NULL;
+ if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
+ {
+ int dummyRes = LzmaDec_TryDummy(p, src, inSize);
+ if (dummyRes == DUMMY_ERROR)
+ {
+ memcpy(p->tempBuf, src, inSize);
+ p->tempBufSize = (unsigned)inSize;
+ (*srcLen) += inSize;
+ *status = LZMA_STATUS_NEEDS_MORE_INPUT;
+ return SZ_OK;
+ }
+ if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
+ {
+ *status = LZMA_STATUS_NOT_FINISHED;
+ return SZ_ERROR_DATA;
+ }
+ bufLimit = src;
+ }
+ else
+ bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX;
+ p->buf = src;
+ if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0)
+ return SZ_ERROR_DATA;
+ processed = (SizeT)(p->buf - src);
+ (*srcLen) += processed;
+ src += processed;
+ inSize -= processed;
+ }
+ else
+ {
+ unsigned rem = p->tempBufSize, lookAhead = 0;
+ while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize)
+ p->tempBuf[rem++] = src[lookAhead++];
+ p->tempBufSize = rem;
+ if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
+ {
+ int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem);
+ if (dummyRes == DUMMY_ERROR)
+ {
+ (*srcLen) += lookAhead;
+ *status = LZMA_STATUS_NEEDS_MORE_INPUT;
+ return SZ_OK;
+ }
+ if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
+ {
+ *status = LZMA_STATUS_NOT_FINISHED;
+ return SZ_ERROR_DATA;
+ }
+ }
+ p->buf = p->tempBuf;
+ if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0)
+ return SZ_ERROR_DATA;
+ lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf));
+ (*srcLen) += lookAhead;
+ src += lookAhead;
+ inSize -= lookAhead;
+ p->tempBufSize = 0;
+ }
+ }
+ if (p->code == 0)
+ *status = LZMA_STATUS_FINISHED_WITH_MARK;
+ return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA;
+}
+
+SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
+{
+ SizeT outSize = *destLen;
+ SizeT inSize = *srcLen;
+ *srcLen = *destLen = 0;
+ for (;;)
+ {
+ SizeT inSizeCur = inSize, outSizeCur, dicPos;
+ ELzmaFinishMode curFinishMode;
+ SRes res;
+ if (p->dicPos == p->dicBufSize)
+ p->dicPos = 0;
+ dicPos = p->dicPos;
+ if (outSize > p->dicBufSize - dicPos)
+ {
+ outSizeCur = p->dicBufSize;
+ curFinishMode = LZMA_FINISH_ANY;
+ }
+ else
+ {
+ outSizeCur = dicPos + outSize;
+ curFinishMode = finishMode;
+ }
+
+ res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status);
+ src += inSizeCur;
+ inSize -= inSizeCur;
+ *srcLen += inSizeCur;
+ outSizeCur = p->dicPos - dicPos;
+ memcpy(dest, p->dic + dicPos, outSizeCur);
+ dest += outSizeCur;
+ outSize -= outSizeCur;
+ *destLen += outSizeCur;
+ if (res != 0)
+ return res;
+ if (outSizeCur == 0 || outSize == 0)
+ return SZ_OK;
+ }
+}
+
+void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc)
+{
+ alloc->Free(alloc, p->probs);
+ p->probs = 0;
+}
+
+static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc)
+{
+ alloc->Free(alloc, p->dic);
+ p->dic = 0;
+}
+
+void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc)
+{
+ LzmaDec_FreeProbs(p, alloc);
+ LzmaDec_FreeDict(p, alloc);
+}
+
+SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size)
+{
+ UInt32 dicSize;
+ Byte d;
+
+ if (size < LZMA_PROPS_SIZE)
+ return SZ_ERROR_UNSUPPORTED;
+ else
+ dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24);
+
+ if (dicSize < LZMA_DIC_MIN)
+ dicSize = LZMA_DIC_MIN;
+ p->dicSize = dicSize;
+
+ d = data[0];
+ if (d >= (9 * 5 * 5))
+ return SZ_ERROR_UNSUPPORTED;
+
+ p->lc = d % 9;
+ d /= 9;
+ p->pb = d / 5;
+ p->lp = d % 5;
+
+ return SZ_OK;
+}
+
+static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc)
+{
+ UInt32 numProbs = LzmaProps_GetNumProbs(propNew);
+ if (p->probs == 0 || numProbs != p->numProbs)
+ {
+ LzmaDec_FreeProbs(p, alloc);
+ p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb));
+ p->numProbs = numProbs;
+ if (p->probs == 0)
+ return SZ_ERROR_MEM;
+ }
+ return SZ_OK;
+}
+
+SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
+{
+ CLzmaProps propNew;
+ RINOK(LzmaProps_Decode(&propNew, props, propsSize));
+ RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
+ p->prop = propNew;
+ return SZ_OK;
+}
+
+SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
+{
+ CLzmaProps propNew;
+ SizeT dicBufSize;
+ RINOK(LzmaProps_Decode(&propNew, props, propsSize));
+ RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
+ dicBufSize = propNew.dicSize;
+ if (p->dic == 0 || dicBufSize != p->dicBufSize)
+ {
+ LzmaDec_FreeDict(p, alloc);
+ p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize);
+ if (p->dic == 0)
+ {
+ LzmaDec_FreeProbs(p, alloc);
+ return SZ_ERROR_MEM;
+ }
+ }
+ p->dicBufSize = dicBufSize;
+ p->prop = propNew;
+ return SZ_OK;
+}
+
+SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
+ const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
+ ELzmaStatus *status, ISzAlloc *alloc)
+{
+ CLzmaDec p;
+ SRes res;
+ SizeT inSize = *srcLen;
+ SizeT outSize = *destLen;
+ *srcLen = *destLen = 0;
+ if (inSize < RC_INIT_SIZE)
+ return SZ_ERROR_INPUT_EOF;
+
+ LzmaDec_Construct(&p);
+ res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc);
+ if (res != 0)
+ return res;
+ p.dic = dest;
+ p.dicBufSize = outSize;
+
+ LzmaDec_Init(&p);
+
+ *srcLen = inSize;
+ res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
+
+ if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
+ res = SZ_ERROR_INPUT_EOF;
+
+ (*destLen) = p.dicPos;
+ LzmaDec_FreeProbs(&p, alloc);
+ return res;
+}
diff -urN linux-4.9.37/lib/lzma/LzmaEnc.c linux-4.9.y/lib/lzma/LzmaEnc.c
--- linux-4.9.37/lib/lzma/LzmaEnc.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/lib/lzma/LzmaEnc.c 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,2271 @@
+/* LzmaEnc.c -- LZMA Encoder
+2009-11-24 : Igor Pavlov : Public domain */
+
+#include <string.h>
+
+/* #define SHOW_STAT */
+/* #define SHOW_STAT2 */
+
+#if defined(SHOW_STAT) || defined(SHOW_STAT2)
+#include <stdio.h>
+#endif
+
+#include "LzmaEnc.h"
+
+/* disable MT */
+#define _7ZIP_ST
+
+#include "LzFind.h"
+#ifndef _7ZIP_ST
+#include "LzFindMt.h"
+#endif
+
+#ifdef SHOW_STAT
+static int ttt = 0;
+#endif
+
+#define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1)
+
+#define kBlockSize (9 << 10)
+#define kUnpackBlockSize (1 << 18)
+#define kMatchArraySize (1 << 21)
+#define kMatchRecordMaxSize ((LZMA_MATCH_LEN_MAX * 2 + 3) * LZMA_MATCH_LEN_MAX)
+
+#define kNumMaxDirectBits (31)
+
+#define kNumTopBits 24
+#define kTopValue ((UInt32)1 << kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
+#define kNumMoveBits 5
+#define kProbInitValue (kBitModelTotal >> 1)
+
+#define kNumMoveReducingBits 4
+#define kNumBitPriceShiftBits 4
+#define kBitPrice (1 << kNumBitPriceShiftBits)
+
+void LzmaEncProps_Init(CLzmaEncProps *p)
+{
+ p->level = 5;
+ p->dictSize = p->mc = 0;
+ p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1;
+ p->writeEndMark = 0;
+}
+
+void LzmaEncProps_Normalize(CLzmaEncProps *p)
+{
+ int level = p->level;
+ if (level < 0) level = 5;
+ p->level = level;
+ if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26)));
+ if (p->lc < 0) p->lc = 3;
+ if (p->lp < 0) p->lp = 0;
+ if (p->pb < 0) p->pb = 2;
+ if (p->algo < 0) p->algo = (level < 5 ? 0 : 1);
+ if (p->fb < 0) p->fb = (level < 7 ? 32 : 64);
+ if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1);
+ if (p->numHashBytes < 0) p->numHashBytes = 4;
+ if (p->mc == 0) p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1);
+ if (p->numThreads < 0)
+ p->numThreads =
+ #ifndef _7ZIP_ST
+ ((p->btMode && p->algo) ? 2 : 1);
+ #else
+ 1;
+ #endif
+}
+
+UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2)
+{
+ CLzmaEncProps props = *props2;
+ LzmaEncProps_Normalize(&props);
+ return props.dictSize;
+}
+
+/* #define LZMA_LOG_BSR */
+/* Define it for Intel's CPU */
+
+
+#ifdef LZMA_LOG_BSR
+
+#define kDicLogSizeMaxCompress 30
+
+#define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); }
+
+UInt32 GetPosSlot1(UInt32 pos)
+{
+ UInt32 res;
+ BSR2_RET(pos, res);
+ return res;
+}
+#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }
+#define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); }
+
+#else
+
+#define kNumLogBits (9 + (int)sizeof(size_t) / 2)
+#define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7)
+
+void LzmaEnc_FastPosInit(Byte *g_FastPos)
+{
+ int c = 2, slotFast;
+ g_FastPos[0] = 0;
+ g_FastPos[1] = 1;
+
+ for (slotFast = 2; slotFast < kNumLogBits * 2; slotFast++)
+ {
+ UInt32 k = (1 << ((slotFast >> 1) - 1));
+ UInt32 j;
+ for (j = 0; j < k; j++, c++)
+ g_FastPos[c] = (Byte)slotFast;
+ }
+}
+
+#define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) & \
+ (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \
+ res = p->g_FastPos[pos >> i] + (i * 2); }
+/*
+#define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \
+ p->g_FastPos[pos >> 6] + 12 : \
+ p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; }
+*/
+
+#define GetPosSlot1(pos) p->g_FastPos[pos]
+#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }
+#define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos]; else BSR2_RET(pos, res); }
+
+#endif
+
+
+#define LZMA_NUM_REPS 4
+
+typedef unsigned CState;
+
+typedef struct
+{
+ UInt32 price;
+
+ CState state;
+ int prev1IsChar;
+ int prev2;
+
+ UInt32 posPrev2;
+ UInt32 backPrev2;
+
+ UInt32 posPrev;
+ UInt32 backPrev;
+ UInt32 backs[LZMA_NUM_REPS];
+} COptimal;
+
+#define kNumOpts (1 << 12)
+
+#define kNumLenToPosStates 4
+#define kNumPosSlotBits 6
+#define kDicLogSizeMin 0
+#define kDicLogSizeMax 32
+#define kDistTableSizeMax (kDicLogSizeMax * 2)
+
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 << kNumAlignBits)
+#define kAlignMask (kAlignTableSize - 1)
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumPosModels (kEndPosModelIndex - kStartPosModelIndex)
+
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+
+#ifdef _LZMA_PROB32
+#define CLzmaProb UInt32
+#else
+#define CLzmaProb UInt16
+#endif
+
+#define LZMA_PB_MAX 4
+#define LZMA_LC_MAX 8
+#define LZMA_LP_MAX 4
+
+#define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX)
+
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
+#define kLenNumMidBits 3
+#define kLenNumMidSymbols (1 << kLenNumMidBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
+
+#define kLenNumSymbolsTotal (kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)
+
+#define LZMA_MATCH_LEN_MIN 2
+#define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1)
+
+#define kNumStates 12
+
+typedef struct
+{
+ CLzmaProb choice;
+ CLzmaProb choice2;
+ CLzmaProb low[LZMA_NUM_PB_STATES_MAX << kLenNumLowBits];
+ CLzmaProb mid[LZMA_NUM_PB_STATES_MAX << kLenNumMidBits];
+ CLzmaProb high[kLenNumHighSymbols];
+} CLenEnc;
+
+typedef struct
+{
+ CLenEnc p;
+ UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal];
+ UInt32 tableSize;
+ UInt32 counters[LZMA_NUM_PB_STATES_MAX];
+} CLenPriceEnc;
+
+typedef struct
+{
+ UInt32 range;
+ Byte cache;
+ UInt64 low;
+ UInt64 cacheSize;
+ Byte *buf;
+ Byte *bufLim;
+ Byte *bufBase;
+ ISeqOutStream *outStream;
+ UInt64 processed;
+ SRes res;
+} CRangeEnc;
+
+typedef struct
+{
+ CLzmaProb *litProbs;
+
+ CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
+ CLzmaProb isRep[kNumStates];
+ CLzmaProb isRepG0[kNumStates];
+ CLzmaProb isRepG1[kNumStates];
+ CLzmaProb isRepG2[kNumStates];
+ CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];
+
+ CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];
+ CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex];
+ CLzmaProb posAlignEncoder[1 << kNumAlignBits];
+
+ CLenPriceEnc lenEnc;
+ CLenPriceEnc repLenEnc;
+
+ UInt32 reps[LZMA_NUM_REPS];
+ UInt32 state;
+} CSaveState;
+
+typedef struct
+{
+ IMatchFinder matchFinder;
+ void *matchFinderObj;
+
+ #ifndef _7ZIP_ST
+ Bool mtMode;
+ CMatchFinderMt matchFinderMt;
+ #endif
+
+ CMatchFinder matchFinderBase;
+
+ #ifndef _7ZIP_ST
+ Byte pad[128];
+ #endif
+
+ UInt32 optimumEndIndex;
+ UInt32 optimumCurrentIndex;
+
+ UInt32 longestMatchLength;
+ UInt32 numPairs;
+ UInt32 numAvail;
+ COptimal opt[kNumOpts];
+
+ #ifndef LZMA_LOG_BSR
+ Byte g_FastPos[1 << kNumLogBits];
+ #endif
+
+ UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits];
+ UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1];
+ UInt32 numFastBytes;
+ UInt32 additionalOffset;
+ UInt32 reps[LZMA_NUM_REPS];
+ UInt32 state;
+
+ UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax];
+ UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances];
+ UInt32 alignPrices[kAlignTableSize];
+ UInt32 alignPriceCount;
+
+ UInt32 distTableSize;
+
+ unsigned lc, lp, pb;
+ unsigned lpMask, pbMask;
+
+ CLzmaProb *litProbs;
+
+ CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
+ CLzmaProb isRep[kNumStates];
+ CLzmaProb isRepG0[kNumStates];
+ CLzmaProb isRepG1[kNumStates];
+ CLzmaProb isRepG2[kNumStates];
+ CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];
+
+ CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];
+ CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex];
+ CLzmaProb posAlignEncoder[1 << kNumAlignBits];
+
+ CLenPriceEnc lenEnc;
+ CLenPriceEnc repLenEnc;
+
+ unsigned lclp;
+
+ Bool fastMode;
+
+ CRangeEnc rc;
+
+ Bool writeEndMark;
+ UInt64 nowPos64;
+ UInt32 matchPriceCount;
+ Bool finished;
+ Bool multiThread;
+
+ SRes result;
+ UInt32 dictSize;
+ UInt32 matchFinderCycles;
+
+ int needInit;
+
+ CSaveState saveState;
+} CLzmaEnc;
+
+void LzmaEnc_SaveState(CLzmaEncHandle pp)
+{
+ CLzmaEnc *p = (CLzmaEnc *)pp;
+ CSaveState *dest = &p->saveState;
+ int i;
+ dest->lenEnc = p->lenEnc;
+ dest->repLenEnc = p->repLenEnc;
+ dest->state = p->state;
+
+ for (i = 0; i < kNumStates; i++)
+ {
+ memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i]));
+ memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i]));
+ }
+ for (i = 0; i < kNumLenToPosStates; i++)
+ memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i]));
+ memcpy(dest->isRep, p->isRep, sizeof(p->isRep));
+ memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0));
+ memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1));
+ memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2));
+ memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders));
+ memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder));
+ memcpy(dest->reps, p->reps, sizeof(p->reps));
+ memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb));
+}
+
+void LzmaEnc_RestoreState(CLzmaEncHandle pp)
+{
+ CLzmaEnc *dest = (CLzmaEnc *)pp;
+ const CSaveState *p = &dest->saveState;
+ int i;
+ dest->lenEnc = p->lenEnc;
+ dest->repLenEnc = p->repLenEnc;
+ dest->state = p->state;
+
+ for (i = 0; i < kNumStates; i++)
+ {
+ memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i]));
+ memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i]));
+ }
+ for (i = 0; i < kNumLenToPosStates; i++)
+ memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i]));
+ memcpy(dest->isRep, p->isRep, sizeof(p->isRep));
+ memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0));
+ memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1));
+ memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2));
+ memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders));
+ memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder));
+ memcpy(dest->reps, p->reps, sizeof(p->reps));
+ memcpy(dest->litProbs, p->litProbs, (0x300 << dest->lclp) * sizeof(CLzmaProb));
+}
+
+SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)
+{
+ CLzmaEnc *p = (CLzmaEnc *)pp;
+ CLzmaEncProps props = *props2;
+ LzmaEncProps_Normalize(&props);
+
+ if (props.lc > LZMA_LC_MAX || props.lp > LZMA_LP_MAX || props.pb > LZMA_PB_MAX ||
+ props.dictSize > (1 << kDicLogSizeMaxCompress) || props.dictSize > (1 << 30))
+ return SZ_ERROR_PARAM;
+ p->dictSize = props.dictSize;
+ p->matchFinderCycles = props.mc;
+ {
+ unsigned fb = props.fb;
+ if (fb < 5)
+ fb = 5;
+ if (fb > LZMA_MATCH_LEN_MAX)
+ fb = LZMA_MATCH_LEN_MAX;
+ p->numFastBytes = fb;
+ }
+ p->lc = props.lc;
+ p->lp = props.lp;
+ p->pb = props.pb;
+ p->fastMode = (props.algo == 0);
+ p->matchFinderBase.btMode = props.btMode;
+ {
+ UInt32 numHashBytes = 4;
+ if (props.btMode)
+ {
+ if (props.numHashBytes < 2)
+ numHashBytes = 2;
+ else if (props.numHashBytes < 4)
+ numHashBytes = props.numHashBytes;
+ }
+ p->matchFinderBase.numHashBytes = numHashBytes;
+ }
+
+ p->matchFinderBase.cutValue = props.mc;
+
+ p->writeEndMark = props.writeEndMark;
+
+ #ifndef _7ZIP_ST
+ /*
+ if (newMultiThread != _multiThread)
+ {
+ ReleaseMatchFinder();
+ _multiThread = newMultiThread;
+ }
+ */
+ p->multiThread = (props.numThreads > 1);
+ #endif
+
+ return SZ_OK;
+}
+
+static const int kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5};
+static const int kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};
+static const int kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};
+static const int kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};
+
+#define IsCharState(s) ((s) < 7)
+
+#define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1)
+
+#define kInfinityPrice (1 << 30)
+
+static void RangeEnc_Construct(CRangeEnc *p)
+{
+ p->outStream = 0;
+ p->bufBase = 0;
+}
+
+#define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize)
+
+#define RC_BUF_SIZE (1 << 16)
+static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc)
+{
+ if (p->bufBase == 0)
+ {
+ p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE);
+ if (p->bufBase == 0)
+ return 0;
+ p->bufLim = p->bufBase + RC_BUF_SIZE;
+ }
+ return 1;
+}
+
+static void RangeEnc_Free(CRangeEnc *p, ISzAlloc *alloc)
+{
+ alloc->Free(alloc, p->bufBase);
+ p->bufBase = 0;
+}
+
+static void RangeEnc_Init(CRangeEnc *p)
+{
+ /* Stream.Init(); */
+ p->low = 0;
+ p->range = 0xFFFFFFFF;
+ p->cacheSize = 1;
+ p->cache = 0;
+
+ p->buf = p->bufBase;
+
+ p->processed = 0;
+ p->res = SZ_OK;
+}
+
+static void RangeEnc_FlushStream(CRangeEnc *p)
+{
+ size_t num;
+ if (p->res != SZ_OK)
+ return;
+ num = p->buf - p->bufBase;
+ if (num != p->outStream->Write(p->outStream, p->bufBase, num))
+ p->res = SZ_ERROR_WRITE;
+ p->processed += num;
+ p->buf = p->bufBase;
+}
+
+static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p)
+{
+ if ((UInt32)p->low < (UInt32)0xFF000000 || (int)(p->low >> 32) != 0)
+ {
+ Byte temp = p->cache;
+ do
+ {
+ Byte *buf = p->buf;
+ *buf++ = (Byte)(temp + (Byte)(p->low >> 32));
+ p->buf = buf;
+ if (buf == p->bufLim)
+ RangeEnc_FlushStream(p);
+ temp = 0xFF;
+ }
+ while (--p->cacheSize != 0);
+ p->cache = (Byte)((UInt32)p->low >> 24);
+ }
+ p->cacheSize++;
+ p->low = (UInt32)p->low << 8;
+}
+
+static void RangeEnc_FlushData(CRangeEnc *p)
+{
+ int i;
+ for (i = 0; i < 5; i++)
+ RangeEnc_ShiftLow(p);
+}
+
+static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, int numBits)
+{
+ do
+ {
+ p->range >>= 1;
+ p->low += p->range & (0 - ((value >> --numBits) & 1));
+ if (p->range < kTopValue)
+ {
+ p->range <<= 8;
+ RangeEnc_ShiftLow(p);
+ }
+ }
+ while (numBits != 0);
+}
+
+static void RangeEnc_EncodeBit(CRangeEnc *p, CLzmaProb *prob, UInt32 symbol)
+{
+ UInt32 ttt = *prob;
+ UInt32 newBound = (p->range >> kNumBitModelTotalBits) * ttt;
+ if (symbol == 0)
+ {
+ p->range = newBound;
+ ttt += (kBitModelTotal - ttt) >> kNumMoveBits;
+ }
+ else
+ {
+ p->low += newBound;
+ p->range -= newBound;
+ ttt -= ttt >> kNumMoveBits;
+ }
+ *prob = (CLzmaProb)ttt;
+ if (p->range < kTopValue)
+ {
+ p->range <<= 8;
+ RangeEnc_ShiftLow(p);
+ }
+}
+
+static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol)
+{
+ symbol |= 0x100;
+ do
+ {
+ RangeEnc_EncodeBit(p, probs + (symbol >> 8), (symbol >> 7) & 1);
+ symbol <<= 1;
+ }
+ while (symbol < 0x10000);
+}
+
+static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol, UInt32 matchByte)
+{
+ UInt32 offs = 0x100;
+ symbol |= 0x100;
+ do
+ {
+ matchByte <<= 1;
+ RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (symbol >> 8)), (symbol >> 7) & 1);
+ symbol <<= 1;
+ offs &= ~(matchByte ^ symbol);
+ }
+ while (symbol < 0x10000);
+}
+
+void LzmaEnc_InitPriceTables(UInt32 *ProbPrices)
+{
+ UInt32 i;
+ for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits))
+ {
+ const int kCyclesBits = kNumBitPriceShiftBits;
+ UInt32 w = i;
+ UInt32 bitCount = 0;
+ int j;
+ for (j = 0; j < kCyclesBits; j++)
+ {
+ w = w * w;
+ bitCount <<= 1;
+ while (w >= ((UInt32)1 << 16))
+ {
+ w >>= 1;
+ bitCount++;
+ }
+ }
+ ProbPrices[i >> kNumMoveReducingBits] = ((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount);
+ }
+}
+
+
+#define GET_PRICE(prob, symbol) \
+ p->ProbPrices[((prob) ^ (((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
+
+#define GET_PRICEa(prob, symbol) \
+ ProbPrices[((prob) ^ ((-((int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
+
+#define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits]
+#define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
+
+#define GET_PRICE_0a(prob) ProbPrices[(prob) >> kNumMoveReducingBits]
+#define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
+
+static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 *ProbPrices)
+{
+ UInt32 price = 0;
+ symbol |= 0x100;
+ do
+ {
+ price += GET_PRICEa(probs[symbol >> 8], (symbol >> 7) & 1);
+ symbol <<= 1;
+ }
+ while (symbol < 0x10000);
+ return price;
+}
+
+static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, UInt32 *ProbPrices)
+{
+ UInt32 price = 0;
+ UInt32 offs = 0x100;
+ symbol |= 0x100;
+ do
+ {
+ matchByte <<= 1;
+ price += GET_PRICEa(probs[offs + (matchByte & offs) + (symbol >> 8)], (symbol >> 7) & 1);
+ symbol <<= 1;
+ offs &= ~(matchByte ^ symbol);
+ }
+ while (symbol < 0x10000);
+ return price;
+}
+
+
+static void RcTree_Encode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol)
+{
+ UInt32 m = 1;
+ int i;
+ for (i = numBitLevels; i != 0;)
+ {
+ UInt32 bit;
+ i--;
+ bit = (symbol >> i) & 1;
+ RangeEnc_EncodeBit(rc, probs + m, bit);
+ m = (m << 1) | bit;
+ }
+}
+
+static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol)
+{
+ UInt32 m = 1;
+ int i;
+ for (i = 0; i < numBitLevels; i++)
+ {
+ UInt32 bit = symbol & 1;
+ RangeEnc_EncodeBit(rc, probs + m, bit);
+ m = (m << 1) | bit;
+ symbol >>= 1;
+ }
+}
+
+static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices)
+{
+ UInt32 price = 0;
+ symbol |= (1 << numBitLevels);
+ while (symbol != 1)
+ {
+ price += GET_PRICEa(probs[symbol >> 1], symbol & 1);
+ symbol >>= 1;
+ }
+ return price;
+}
+
+static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices)
+{
+ UInt32 price = 0;
+ UInt32 m = 1;
+ int i;
+ for (i = numBitLevels; i != 0; i--)
+ {
+ UInt32 bit = symbol & 1;
+ symbol >>= 1;
+ price += GET_PRICEa(probs[m], bit);
+ m = (m << 1) | bit;
+ }
+ return price;
+}
+
+
+static void LenEnc_Init(CLenEnc *p)
+{
+ unsigned i;
+ p->choice = p->choice2 = kProbInitValue;
+ for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumLowBits); i++)
+ p->low[i] = kProbInitValue;
+ for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumMidBits); i++)
+ p->mid[i] = kProbInitValue;
+ for (i = 0; i < kLenNumHighSymbols; i++)
+ p->high[i] = kProbInitValue;
+}
+
+static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState)
+{
+ if (symbol < kLenNumLowSymbols)
+ {
+ RangeEnc_EncodeBit(rc, &p->choice, 0);
+ RcTree_Encode(rc, p->low + (posState << kLenNumLowBits), kLenNumLowBits, symbol);
+ }
+ else
+ {
+ RangeEnc_EncodeBit(rc, &p->choice, 1);
+ if (symbol < kLenNumLowSymbols + kLenNumMidSymbols)
+ {
+ RangeEnc_EncodeBit(rc, &p->choice2, 0);
+ RcTree_Encode(rc, p->mid + (posState << kLenNumMidBits), kLenNumMidBits, symbol - kLenNumLowSymbols);
+ }
+ else
+ {
+ RangeEnc_EncodeBit(rc, &p->choice2, 1);
+ RcTree_Encode(rc, p->high, kLenNumHighBits, symbol - kLenNumLowSymbols - kLenNumMidSymbols);
+ }
+ }
+}
+
+static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, UInt32 *ProbPrices)
+{
+ UInt32 a0 = GET_PRICE_0a(p->choice);
+ UInt32 a1 = GET_PRICE_1a(p->choice);
+ UInt32 b0 = a1 + GET_PRICE_0a(p->choice2);
+ UInt32 b1 = a1 + GET_PRICE_1a(p->choice2);
+ UInt32 i = 0;
+ for (i = 0; i < kLenNumLowSymbols; i++)
+ {
+ if (i >= numSymbols)
+ return;
+ prices[i] = a0 + RcTree_GetPrice(p->low + (posState << kLenNumLowBits), kLenNumLowBits, i, ProbPrices);
+ }
+ for (; i < kLenNumLowSymbols + kLenNumMidSymbols; i++)
+ {
+ if (i >= numSymbols)
+ return;
+ prices[i] = b0 + RcTree_GetPrice(p->mid + (posState << kLenNumMidBits), kLenNumMidBits, i - kLenNumLowSymbols, ProbPrices);
+ }
+ for (; i < numSymbols; i++)
+ prices[i] = b1 + RcTree_GetPrice(p->high, kLenNumHighBits, i - kLenNumLowSymbols - kLenNumMidSymbols, ProbPrices);
+}
+
+static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, UInt32 *ProbPrices)
+{
+ LenEnc_SetPrices(&p->p, posState, p->tableSize, p->prices[posState], ProbPrices);
+ p->counters[posState] = p->tableSize;
+}
+
+static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, UInt32 *ProbPrices)
+{
+ UInt32 posState;
+ for (posState = 0; posState < numPosStates; posState++)
+ LenPriceEnc_UpdateTable(p, posState, ProbPrices);
+}
+
+static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, UInt32 *ProbPrices)
+{
+ LenEnc_Encode(&p->p, rc, symbol, posState);
+ if (updatePrice)
+ if (--p->counters[posState] == 0)
+ LenPriceEnc_UpdateTable(p, posState, ProbPrices);
+}
+
+
+
+
+static void MovePos(CLzmaEnc *p, UInt32 num)
+{
+ #ifdef SHOW_STAT
+ ttt += num;
+ printf("\n MovePos %d", num);
+ #endif
+ if (num != 0)
+ {
+ p->additionalOffset += num;
+ p->matchFinder.Skip(p->matchFinderObj, num);
+ }
+}
+
+static UInt32 ReadMatchDistances(CLzmaEnc *p, UInt32 *numDistancePairsRes)
+{
+ UInt32 lenRes = 0, numPairs;
+ p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
+ numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches);
+ #ifdef SHOW_STAT
+ printf("\n i = %d numPairs = %d ", ttt, numPairs / 2);
+ ttt++;
+ {
+ UInt32 i;
+ for (i = 0; i < numPairs; i += 2)
+ printf("%2d %6d | ", p->matches[i], p->matches[i + 1]);
+ }
+ #endif
+ if (numPairs > 0)
+ {
+ lenRes = p->matches[numPairs - 2];
+ if (lenRes == p->numFastBytes)
+ {
+ const Byte *pby = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
+ UInt32 distance = p->matches[numPairs - 1] + 1;
+ UInt32 numAvail = p->numAvail;
+ if (numAvail > LZMA_MATCH_LEN_MAX)
+ numAvail = LZMA_MATCH_LEN_MAX;
+ {
+ const Byte *pby2 = pby - distance;
+ for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++);
+ }
+ }
+ }
+ p->additionalOffset++;
+ *numDistancePairsRes = numPairs;
+ return lenRes;
+}
+
+
+#define MakeAsChar(p) (p)->backPrev = (UInt32)(-1); (p)->prev1IsChar = False;
+#define MakeAsShortRep(p) (p)->backPrev = 0; (p)->prev1IsChar = False;
+#define IsShortRep(p) ((p)->backPrev == 0)
+
+static UInt32 GetRepLen1Price(CLzmaEnc *p, UInt32 state, UInt32 posState)
+{
+ return
+ GET_PRICE_0(p->isRepG0[state]) +
+ GET_PRICE_0(p->isRep0Long[state][posState]);
+}
+
+static UInt32 GetPureRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 state, UInt32 posState)
+{
+ UInt32 price;
+ if (repIndex == 0)
+ {
+ price = GET_PRICE_0(p->isRepG0[state]);
+ price += GET_PRICE_1(p->isRep0Long[state][posState]);
+ }
+ else
+ {
+ price = GET_PRICE_1(p->isRepG0[state]);
+ if (repIndex == 1)
+ price += GET_PRICE_0(p->isRepG1[state]);
+ else
+ {
+ price += GET_PRICE_1(p->isRepG1[state]);
+ price += GET_PRICE(p->isRepG2[state], repIndex - 2);
+ }
+ }
+ return price;
+}
+
+static UInt32 GetRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 len, UInt32 state, UInt32 posState)
+{
+ return p->repLenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN] +
+ GetPureRepPrice(p, repIndex, state, posState);
+}
+
+static UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur)
+{
+ UInt32 posMem = p->opt[cur].posPrev;
+ UInt32 backMem = p->opt[cur].backPrev;
+ p->optimumEndIndex = cur;
+ do
+ {
+ if (p->opt[cur].prev1IsChar)
+ {
+ MakeAsChar(&p->opt[posMem])
+ p->opt[posMem].posPrev = posMem - 1;
+ if (p->opt[cur].prev2)
+ {
+ p->opt[posMem - 1].prev1IsChar = False;
+ p->opt[posMem - 1].posPrev = p->opt[cur].posPrev2;
+ p->opt[posMem - 1].backPrev = p->opt[cur].backPrev2;
+ }
+ }
+ {
+ UInt32 posPrev = posMem;
+ UInt32 backCur = backMem;
+
+ backMem = p->opt[posPrev].backPrev;
+ posMem = p->opt[posPrev].posPrev;
+
+ p->opt[posPrev].backPrev = backCur;
+ p->opt[posPrev].posPrev = cur;
+ cur = posPrev;
+ }
+ }
+ while (cur != 0);
+ *backRes = p->opt[0].backPrev;
+ p->optimumCurrentIndex = p->opt[0].posPrev;
+ return p->optimumCurrentIndex;
+}
+
+#define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * 0x300)
+
+static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
+{
+ UInt32 numAvail, mainLen, numPairs, repMaxIndex, i, posState, lenEnd, len, cur;
+ UInt32 matchPrice, repMatchPrice, normalMatchPrice;
+ UInt32 reps[LZMA_NUM_REPS], repLens[LZMA_NUM_REPS];
+ UInt32 *matches = NULL;
+ const Byte *data = NULL;
+ Byte curByte, matchByte;
+ if (p->optimumEndIndex != p->optimumCurrentIndex)
+ {
+ const COptimal *opt = &p->opt[p->optimumCurrentIndex];
+ UInt32 lenRes = opt->posPrev - p->optimumCurrentIndex;
+ *backRes = opt->backPrev;
+ p->optimumCurrentIndex = opt->posPrev;
+ return lenRes;
+ }
+ p->optimumCurrentIndex = p->optimumEndIndex = 0;
+
+ if (p->additionalOffset == 0)
+ mainLen = ReadMatchDistances(p, &numPairs);
+ else
+ {
+ mainLen = p->longestMatchLength;
+ numPairs = p->numPairs;
+ }
+
+ numAvail = p->numAvail;
+ if (numAvail < 2)
+ {
+ *backRes = (UInt32)(-1);
+ return 1;
+ }
+ if (numAvail > LZMA_MATCH_LEN_MAX)
+ numAvail = LZMA_MATCH_LEN_MAX;
+
+ data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
+ repMaxIndex = 0;
+ for (i = 0; i < LZMA_NUM_REPS; i++)
+ {
+ UInt32 lenTest;
+ const Byte *data2 = NULL;
+ reps[i] = p->reps[i];
+ data2 = data - (reps[i] + 1);
+ if (data[0] != data2[0] || data[1] != data2[1])
+ {
+ repLens[i] = 0;
+ continue;
+ }
+ for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++);
+ repLens[i] = lenTest;
+ if (lenTest > repLens[repMaxIndex])
+ repMaxIndex = i;
+ }
+ if (repLens[repMaxIndex] >= p->numFastBytes)
+ {
+ UInt32 lenRes;
+ *backRes = repMaxIndex;
+ lenRes = repLens[repMaxIndex];
+ MovePos(p, lenRes - 1);
+ return lenRes;
+ }
+
+ matches = p->matches;
+ if (mainLen >= p->numFastBytes)
+ {
+ *backRes = matches[numPairs - 1] + LZMA_NUM_REPS;
+ MovePos(p, mainLen - 1);
+ return mainLen;
+ }
+ curByte = *data;
+ matchByte = *(data - (reps[0] + 1));
+
+ if (mainLen < 2 && curByte != matchByte && repLens[repMaxIndex] < 2)
+ {
+ *backRes = (UInt32)-1;
+ return 1;
+ }
+
+ p->opt[0].state = (CState)p->state;
+
+ posState = (position & p->pbMask);
+
+ {
+ const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
+ p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) +
+ (!IsCharState(p->state) ?
+ LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) :
+ LitEnc_GetPrice(probs, curByte, p->ProbPrices));
+ }
+
+ MakeAsChar(&p->opt[1]);
+
+ matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]);
+ repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]);
+
+ if (matchByte == curByte)
+ {
+ UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, p->state, posState);
+ if (shortRepPrice < p->opt[1].price)
+ {
+ p->opt[1].price = shortRepPrice;
+ MakeAsShortRep(&p->opt[1]);
+ }
+ }
+ lenEnd = ((mainLen >= repLens[repMaxIndex]) ? mainLen : repLens[repMaxIndex]);
+
+ if (lenEnd < 2)
+ {
+ *backRes = p->opt[1].backPrev;
+ return 1;
+ }
+
+ p->opt[1].posPrev = 0;
+ for (i = 0; i < LZMA_NUM_REPS; i++)
+ p->opt[0].backs[i] = reps[i];
+
+ len = lenEnd;
+ do
+ p->opt[len--].price = kInfinityPrice;
+ while (len >= 2);
+
+ for (i = 0; i < LZMA_NUM_REPS; i++)
+ {
+ UInt32 repLen = repLens[i];
+ UInt32 price;
+ if (repLen < 2)
+ continue;
+ price = repMatchPrice + GetPureRepPrice(p, i, p->state, posState);
+ do
+ {
+ UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][repLen - 2];
+ COptimal *opt = &p->opt[repLen];
+ if (curAndLenPrice < opt->price)
+ {
+ opt->price = curAndLenPrice;
+ opt->posPrev = 0;
+ opt->backPrev = i;
+ opt->prev1IsChar = False;
+ }
+ }
+ while (--repLen >= 2);
+ }
+
+ normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]);
+
+ len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2);
+ if (len <= mainLen)
+ {
+ UInt32 offs = 0;
+ while (len > matches[offs])
+ offs += 2;
+ for (; ; len++)
+ {
+ COptimal *opt = NULL;
+ UInt32 distance = matches[offs + 1];
+
+ UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN];
+ UInt32 lenToPosState = GetLenToPosState(len);
+ if (distance < kNumFullDistances)
+ curAndLenPrice += p->distancesPrices[lenToPosState][distance];
+ else
+ {
+ UInt32 slot;
+ GetPosSlot2(distance, slot);
+ curAndLenPrice += p->alignPrices[distance & kAlignMask] + p->posSlotPrices[lenToPosState][slot];
+ }
+ opt = &p->opt[len];
+ if (curAndLenPrice < opt->price)
+ {
+ opt->price = curAndLenPrice;
+ opt->posPrev = 0;
+ opt->backPrev = distance + LZMA_NUM_REPS;
+ opt->prev1IsChar = False;
+ }
+ if (len == matches[offs])
+ {
+ offs += 2;
+ if (offs == numPairs)
+ break;
+ }
+ }
+ }
+
+ cur = 0;
+
+ #ifdef SHOW_STAT2
+ if (position >= 0)
+ {
+ unsigned i;
+ printf("\n pos = %4X", position);
+ for (i = cur; i <= lenEnd; i++)
+ printf("\nprice[%4X] = %d", position - cur + i, p->opt[i].price);
+ }
+ #endif
+
+ for (;;)
+ {
+ UInt32 numAvailFull, newLen, numPairs, posPrev, state, posState, startLen;
+ UInt32 curPrice, curAnd1Price, matchPrice, repMatchPrice;
+ Bool nextIsChar;
+ Byte curByte, matchByte;
+ const Byte *data = NULL;
+ COptimal *curOpt = NULL;
+ COptimal *nextOpt = NULL;
+
+ cur++;
+ if (cur == lenEnd)
+ return Backward(p, backRes, cur);
+
+ newLen = ReadMatchDistances(p, &numPairs);
+ if (newLen >= p->numFastBytes)
+ {
+ p->numPairs = numPairs;
+ p->longestMatchLength = newLen;
+ return Backward(p, backRes, cur);
+ }
+ position++;
+ curOpt = &p->opt[cur];
+ posPrev = curOpt->posPrev;
+ if (curOpt->prev1IsChar)
+ {
+ posPrev--;
+ if (curOpt->prev2)
+ {
+ state = p->opt[curOpt->posPrev2].state;
+ if (curOpt->backPrev2 < LZMA_NUM_REPS)
+ state = kRepNextStates[state];
+ else
+ state = kMatchNextStates[state];
+ }
+ else
+ state = p->opt[posPrev].state;
+ state = kLiteralNextStates[state];
+ }
+ else
+ state = p->opt[posPrev].state;
+ if (posPrev == cur - 1)
+ {
+ if (IsShortRep(curOpt))
+ state = kShortRepNextStates[state];
+ else
+ state = kLiteralNextStates[state];
+ }
+ else
+ {
+ UInt32 pos;
+ const COptimal *prevOpt = NULL;
+ if (curOpt->prev1IsChar && curOpt->prev2)
+ {
+ posPrev = curOpt->posPrev2;
+ pos = curOpt->backPrev2;
+ state = kRepNextStates[state];
+ }
+ else
+ {
+ pos = curOpt->backPrev;
+ if (pos < LZMA_NUM_REPS)
+ state = kRepNextStates[state];
+ else
+ state = kMatchNextStates[state];
+ }
+ prevOpt = &p->opt[posPrev];
+ if (pos < LZMA_NUM_REPS)
+ {
+ UInt32 i;
+ reps[0] = prevOpt->backs[pos];
+ for (i = 1; i <= pos; i++)
+ reps[i] = prevOpt->backs[i - 1];
+ for (; i < LZMA_NUM_REPS; i++)
+ reps[i] = prevOpt->backs[i];
+ }
+ else
+ {
+ UInt32 i;
+ reps[0] = (pos - LZMA_NUM_REPS);
+ for (i = 1; i < LZMA_NUM_REPS; i++)
+ reps[i] = prevOpt->backs[i - 1];
+ }
+ }
+ curOpt->state = (CState)state;
+
+ curOpt->backs[0] = reps[0];
+ curOpt->backs[1] = reps[1];
+ curOpt->backs[2] = reps[2];
+ curOpt->backs[3] = reps[3];
+
+ curPrice = curOpt->price;
+ nextIsChar = False;
+ data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
+ curByte = *data;
+ matchByte = *(data - (reps[0] + 1));
+
+ posState = (position & p->pbMask);
+
+ curAnd1Price = curPrice + GET_PRICE_0(p->isMatch[state][posState]);
+ {
+ const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
+ curAnd1Price +=
+ (!IsCharState(state) ?
+ LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) :
+ LitEnc_GetPrice(probs, curByte, p->ProbPrices));
+ }
+
+ nextOpt = &p->opt[cur + 1];
+
+ if (curAnd1Price < nextOpt->price)
+ {
+ nextOpt->price = curAnd1Price;
+ nextOpt->posPrev = cur;
+ MakeAsChar(nextOpt);
+ nextIsChar = True;
+ }
+
+ matchPrice = curPrice + GET_PRICE_1(p->isMatch[state][posState]);
+ repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]);
+
+ if (matchByte == curByte && !(nextOpt->posPrev < cur && nextOpt->backPrev == 0))
+ {
+ UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, state, posState);
+ if (shortRepPrice <= nextOpt->price)
+ {
+ nextOpt->price = shortRepPrice;
+ nextOpt->posPrev = cur;
+ MakeAsShortRep(nextOpt);
+ nextIsChar = True;
+ }
+ }
+ numAvailFull = p->numAvail;
+ {
+ UInt32 temp = kNumOpts - 1 - cur;
+ if (temp < numAvailFull)
+ numAvailFull = temp;
+ }
+
+ if (numAvailFull < 2)
+ continue;
+ numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes);
+
+ if (!nextIsChar && matchByte != curByte) /* speed optimization */
+ {
+ /* try Literal + rep0 */
+ UInt32 temp;
+ UInt32 lenTest2;
+ const Byte *data2 = data - (reps[0] + 1);
+ UInt32 limit = p->numFastBytes + 1;
+ if (limit > numAvailFull)
+ limit = numAvailFull;
+
+ for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++);
+ lenTest2 = temp - 1;
+ if (lenTest2 >= 2)
+ {
+ UInt32 state2 = kLiteralNextStates[state];
+ UInt32 posStateNext = (position + 1) & p->pbMask;
+ UInt32 nextRepMatchPrice = curAnd1Price +
+ GET_PRICE_1(p->isMatch[state2][posStateNext]) +
+ GET_PRICE_1(p->isRep[state2]);
+ /* for (; lenTest2 >= 2; lenTest2--) */
+ {
+ UInt32 curAndLenPrice;
+ COptimal *opt;
+ UInt32 offset = cur + 1 + lenTest2;
+ while (lenEnd < offset)
+ p->opt[++lenEnd].price = kInfinityPrice;
+ curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);
+ opt = &p->opt[offset];
+ if (curAndLenPrice < opt->price)
+ {
+ opt->price = curAndLenPrice;
+ opt->posPrev = cur + 1;
+ opt->backPrev = 0;
+ opt->prev1IsChar = True;
+ opt->prev2 = False;
+ }
+ }
+ }
+ }
+
+ startLen = 2; /* speed optimization */
+ {
+ UInt32 repIndex;
+ for (repIndex = 0; repIndex < LZMA_NUM_REPS; repIndex++)
+ {
+ UInt32 lenTest;
+ UInt32 lenTestTemp;
+ UInt32 price;
+ const Byte *data2 = data - (reps[repIndex] + 1);
+ if (data[0] != data2[0] || data[1] != data2[1])
+ continue;
+ for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++);
+ while (lenEnd < cur + lenTest)
+ p->opt[++lenEnd].price = kInfinityPrice;
+ lenTestTemp = lenTest;
+ price = repMatchPrice + GetPureRepPrice(p, repIndex, state, posState);
+ do
+ {
+ UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][lenTest - 2];
+ COptimal *opt = &p->opt[cur + lenTest];
+ if (curAndLenPrice < opt->price)
+ {
+ opt->price = curAndLenPrice;
+ opt->posPrev = cur;
+ opt->backPrev = repIndex;
+ opt->prev1IsChar = False;
+ }
+ }
+ while (--lenTest >= 2);
+ lenTest = lenTestTemp;
+
+ if (repIndex == 0)
+ startLen = lenTest + 1;
+
+ /* if (_maxMode) */
+ {
+ UInt32 lenTest2 = lenTest + 1;
+ UInt32 limit = lenTest2 + p->numFastBytes;
+ UInt32 nextRepMatchPrice;
+ if (limit > numAvailFull)
+ limit = numAvailFull;
+ for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);
+ lenTest2 -= lenTest + 1;
+ if (lenTest2 >= 2)
+ {
+ UInt32 state2 = kRepNextStates[state];
+ UInt32 posStateNext = (position + lenTest) & p->pbMask;
+ UInt32 curAndLenCharPrice =
+ price + p->repLenEnc.prices[posState][lenTest - 2] +
+ GET_PRICE_0(p->isMatch[state2][posStateNext]) +
+ LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]),
+ data[lenTest], data2[lenTest], p->ProbPrices);
+ state2 = kLiteralNextStates[state2];
+ posStateNext = (position + lenTest + 1) & p->pbMask;
+ nextRepMatchPrice = curAndLenCharPrice +
+ GET_PRICE_1(p->isMatch[state2][posStateNext]) +
+ GET_PRICE_1(p->isRep[state2]);
+
+ /* for (; lenTest2 >= 2; lenTest2--) */
+ {
+ UInt32 curAndLenPrice;
+ COptimal *opt;
+ UInt32 offset = cur + lenTest + 1 + lenTest2;
+ while (lenEnd < offset)
+ p->opt[++lenEnd].price = kInfinityPrice;
+ curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);
+ opt = &p->opt[offset];
+ if (curAndLenPrice < opt->price)
+ {
+ opt->price = curAndLenPrice;
+ opt->posPrev = cur + lenTest + 1;
+ opt->backPrev = 0;
+ opt->prev1IsChar = True;
+ opt->prev2 = True;
+ opt->posPrev2 = cur;
+ opt->backPrev2 = repIndex;
+ }
+ }
+ }
+ }
+ }
+ }
+ /* for (UInt32 lenTest = 2; lenTest <= newLen; lenTest++) */
+ if (newLen > numAvail)
+ {
+ newLen = numAvail;
+ for (numPairs = 0; newLen > matches[numPairs]; numPairs += 2);
+ matches[numPairs] = newLen;
+ numPairs += 2;
+ }
+ if (newLen >= startLen)
+ {
+ UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]);
+ UInt32 offs, curBack, posSlot;
+ UInt32 lenTest;
+ while (lenEnd < cur + newLen)
+ p->opt[++lenEnd].price = kInfinityPrice;
+
+ offs = 0;
+ while (startLen > matches[offs])
+ offs += 2;
+ curBack = matches[offs + 1];
+ GetPosSlot2(curBack, posSlot);
+ for (lenTest = /*2*/ startLen; ; lenTest++)
+ {
+ UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][lenTest - LZMA_MATCH_LEN_MIN];
+ UInt32 lenToPosState = GetLenToPosState(lenTest);
+ COptimal *opt = NULL;
+ if (curBack < kNumFullDistances)
+ curAndLenPrice += p->distancesPrices[lenToPosState][curBack];
+ else
+ curAndLenPrice += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[curBack & kAlignMask];
+
+ opt = &p->opt[cur + lenTest];
+ if (curAndLenPrice < opt->price)
+ {
+ opt->price = curAndLenPrice;
+ opt->posPrev = cur;
+ opt->backPrev = curBack + LZMA_NUM_REPS;
+ opt->prev1IsChar = False;
+ }
+
+ if (/*_maxMode && */lenTest == matches[offs])
+ {
+ /* Try Match + Literal + Rep0 */
+ const Byte *data2 = data - (curBack + 1);
+ UInt32 lenTest2 = lenTest + 1;
+ UInt32 limit = lenTest2 + p->numFastBytes;
+ UInt32 nextRepMatchPrice;
+ if (limit > numAvailFull)
+ limit = numAvailFull;
+ for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);
+ lenTest2 -= lenTest + 1;
+ if (lenTest2 >= 2)
+ {
+ UInt32 state2 = kMatchNextStates[state];
+ UInt32 posStateNext = (position + lenTest) & p->pbMask;
+ UInt32 curAndLenCharPrice = curAndLenPrice +
+ GET_PRICE_0(p->isMatch[state2][posStateNext]) +
+ LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]),
+ data[lenTest], data2[lenTest], p->ProbPrices);
+ state2 = kLiteralNextStates[state2];
+ posStateNext = (posStateNext + 1) & p->pbMask;
+ nextRepMatchPrice = curAndLenCharPrice +
+ GET_PRICE_1(p->isMatch[state2][posStateNext]) +
+ GET_PRICE_1(p->isRep[state2]);
+
+ /* for (; lenTest2 >= 2; lenTest2--) */
+ {
+ UInt32 offset = cur + lenTest + 1 + lenTest2;
+ UInt32 curAndLenPrice;
+ COptimal *opt;
+ while (lenEnd < offset)
+ p->opt[++lenEnd].price = kInfinityPrice;
+ curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);
+ opt = &p->opt[offset];
+ if (curAndLenPrice < opt->price)
+ {
+ opt->price = curAndLenPrice;
+ opt->posPrev = cur + lenTest + 1;
+ opt->backPrev = 0;
+ opt->prev1IsChar = True;
+ opt->prev2 = True;
+ opt->posPrev2 = cur;
+ opt->backPrev2 = curBack + LZMA_NUM_REPS;
+ }
+ }
+ }
+ offs += 2;
+ if (offs == numPairs)
+ break;
+ curBack = matches[offs + 1];
+ if (curBack >= kNumFullDistances)
+ GetPosSlot2(curBack, posSlot);
+ }
+ }
+ }
+ }
+}
+
+#define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist))
+
+static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes)
+{
+ UInt32 numAvail, mainLen, mainDist, numPairs, repIndex, repLen, i;
+ const Byte *data = NULL;
+ const UInt32 *matches = NULL;
+
+ if (p->additionalOffset == 0)
+ mainLen = ReadMatchDistances(p, &numPairs);
+ else
+ {
+ mainLen = p->longestMatchLength;
+ numPairs = p->numPairs;
+ }
+
+ numAvail = p->numAvail;
+ *backRes = (UInt32)-1;
+ if (numAvail < 2)
+ return 1;
+ if (numAvail > LZMA_MATCH_LEN_MAX)
+ numAvail = LZMA_MATCH_LEN_MAX;
+ data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
+
+ repLen = repIndex = 0;
+ for (i = 0; i < LZMA_NUM_REPS; i++)
+ {
+ UInt32 len;
+ const Byte *data2 = data - (p->reps[i] + 1);
+ if (data[0] != data2[0] || data[1] != data2[1])
+ continue;
+ for (len = 2; len < numAvail && data[len] == data2[len]; len++);
+ if (len >= p->numFastBytes)
+ {
+ *backRes = i;
+ MovePos(p, len - 1);
+ return len;
+ }
+ if (len > repLen)
+ {
+ repIndex = i;
+ repLen = len;
+ }
+ }
+
+ matches = p->matches;
+ if (mainLen >= p->numFastBytes)
+ {
+ *backRes = matches[numPairs - 1] + LZMA_NUM_REPS;
+ MovePos(p, mainLen - 1);
+ return mainLen;
+ }
+
+ mainDist = 0; /* for GCC */
+ if (mainLen >= 2)
+ {
+ mainDist = matches[numPairs - 1];
+ while (numPairs > 2 && mainLen == matches[numPairs - 4] + 1)
+ {
+ if (!ChangePair(matches[numPairs - 3], mainDist))
+ break;
+ numPairs -= 2;
+ mainLen = matches[numPairs - 2];
+ mainDist = matches[numPairs - 1];
+ }
+ if (mainLen == 2 && mainDist >= 0x80)
+ mainLen = 1;
+ }
+
+ if (repLen >= 2 && (
+ (repLen + 1 >= mainLen) ||
+ (repLen + 2 >= mainLen && mainDist >= (1 << 9)) ||
+ (repLen + 3 >= mainLen && mainDist >= (1 << 15))))
+ {
+ *backRes = repIndex;
+ MovePos(p, repLen - 1);
+ return repLen;
+ }
+
+ if (mainLen < 2 || numAvail <= 2)
+ return 1;
+
+ p->longestMatchLength = ReadMatchDistances(p, &p->numPairs);
+ if (p->longestMatchLength >= 2)
+ {
+ UInt32 newDistance = matches[p->numPairs - 1];
+ if ((p->longestMatchLength >= mainLen && newDistance < mainDist) ||
+ (p->longestMatchLength == mainLen + 1 && !ChangePair(mainDist, newDistance)) ||
+ (p->longestMatchLength > mainLen + 1) ||
+ (p->longestMatchLength + 1 >= mainLen && mainLen >= 3 && ChangePair(newDistance, mainDist)))
+ return 1;
+ }
+
+ data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
+ for (i = 0; i < LZMA_NUM_REPS; i++)
+ {
+ UInt32 len, limit;
+ const Byte *data2 = data - (p->reps[i] + 1);
+ if (data[0] != data2[0] || data[1] != data2[1])
+ continue;
+ limit = mainLen - 1;
+ for (len = 2; len < limit && data[len] == data2[len]; len++);
+ if (len >= limit)
+ return 1;
+ }
+ *backRes = mainDist + LZMA_NUM_REPS;
+ MovePos(p, mainLen - 2);
+ return mainLen;
+}
+
+static void WriteEndMarker(CLzmaEnc *p, UInt32 posState)
+{
+ UInt32 len;
+ RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1);
+ RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0);
+ p->state = kMatchNextStates[p->state];
+ len = LZMA_MATCH_LEN_MIN;
+ LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);
+ RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, (1 << kNumPosSlotBits) - 1);
+ RangeEnc_EncodeDirectBits(&p->rc, (((UInt32)1 << 30) - 1) >> kNumAlignBits, 30 - kNumAlignBits);
+ RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask);
+}
+
+static SRes CheckErrors(CLzmaEnc *p)
+{
+ if (p->result != SZ_OK)
+ return p->result;
+ if (p->rc.res != SZ_OK)
+ p->result = SZ_ERROR_WRITE;
+ if (p->matchFinderBase.result != SZ_OK)
+ p->result = SZ_ERROR_READ;
+ if (p->result != SZ_OK)
+ p->finished = True;
+ return p->result;
+}
+
+static SRes Flush(CLzmaEnc *p, UInt32 nowPos)
+{
+ /* ReleaseMFStream(); */
+ p->finished = True;
+ if (p->writeEndMark)
+ WriteEndMarker(p, nowPos & p->pbMask);
+ RangeEnc_FlushData(&p->rc);
+ RangeEnc_FlushStream(&p->rc);
+ return CheckErrors(p);
+}
+
+static void FillAlignPrices(CLzmaEnc *p)
+{
+ UInt32 i;
+ for (i = 0; i < kAlignTableSize; i++)
+ p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices);
+ p->alignPriceCount = 0;
+}
+
+static void FillDistancesPrices(CLzmaEnc *p)
+{
+ UInt32 tempPrices[kNumFullDistances];
+ UInt32 i, lenToPosState;
+ for (i = kStartPosModelIndex; i < kNumFullDistances; i++)
+ {
+ UInt32 posSlot = GetPosSlot1(i);
+ UInt32 footerBits = ((posSlot >> 1) - 1);
+ UInt32 base = ((2 | (posSlot & 1)) << footerBits);
+ tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base - posSlot - 1, footerBits, i - base, p->ProbPrices);
+ }
+
+ for (lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++)
+ {
+ UInt32 posSlot;
+ const CLzmaProb *encoder = p->posSlotEncoder[lenToPosState];
+ UInt32 *posSlotPrices = p->posSlotPrices[lenToPosState];
+ for (posSlot = 0; posSlot < p->distTableSize; posSlot++)
+ posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices);
+ for (posSlot = kEndPosModelIndex; posSlot < p->distTableSize; posSlot++)
+ posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits);
+
+ {
+ UInt32 *distancesPrices = p->distancesPrices[lenToPosState];
+ UInt32 i;
+ for (i = 0; i < kStartPosModelIndex; i++)
+ distancesPrices[i] = posSlotPrices[i];
+ for (; i < kNumFullDistances; i++)
+ distancesPrices[i] = posSlotPrices[GetPosSlot1(i)] + tempPrices[i];
+ }
+ }
+ p->matchPriceCount = 0;
+}
+
+void LzmaEnc_Construct(CLzmaEnc *p)
+{
+ RangeEnc_Construct(&p->rc);
+ MatchFinder_Construct(&p->matchFinderBase);
+ #ifndef _7ZIP_ST
+ MatchFinderMt_Construct(&p->matchFinderMt);
+ p->matchFinderMt.MatchFinder = &p->matchFinderBase;
+ #endif
+
+ {
+ CLzmaEncProps props;
+ LzmaEncProps_Init(&props);
+ LzmaEnc_SetProps(p, &props);
+ }
+
+ #ifndef LZMA_LOG_BSR
+ LzmaEnc_FastPosInit(p->g_FastPos);
+ #endif
+
+ LzmaEnc_InitPriceTables(p->ProbPrices);
+ p->litProbs = 0;
+ p->saveState.litProbs = 0;
+}
+
+CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc)
+{
+ void *p;
+ p = alloc->Alloc(alloc, sizeof(CLzmaEnc));
+ if (p != 0)
+ LzmaEnc_Construct((CLzmaEnc *)p);
+ return p;
+}
+
+void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc)
+{
+ alloc->Free(alloc, p->litProbs);
+ alloc->Free(alloc, p->saveState.litProbs);
+ p->litProbs = 0;
+ p->saveState.litProbs = 0;
+}
+
+void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+ #ifndef _7ZIP_ST
+ MatchFinderMt_Destruct(&p->matchFinderMt, allocBig);
+ #endif
+ MatchFinder_Free(&p->matchFinderBase, allocBig);
+ LzmaEnc_FreeLits(p, alloc);
+ RangeEnc_Free(&p->rc, alloc);
+}
+
+void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+ LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig);
+ alloc->Free(alloc, p);
+}
+
+static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize, UInt32 maxUnpackSize)
+{
+ UInt32 nowPos32, startPos32;
+ if (p->needInit)
+ {
+ p->matchFinder.Init(p->matchFinderObj);
+ p->needInit = 0;
+ }
+
+ if (p->finished)
+ return p->result;
+ RINOK(CheckErrors(p));
+
+ nowPos32 = (UInt32)p->nowPos64;
+ startPos32 = nowPos32;
+
+ if (p->nowPos64 == 0)
+ {
+ UInt32 numPairs;
+ Byte curByte;
+ if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)
+ return Flush(p, nowPos32);
+ ReadMatchDistances(p, &numPairs);
+ RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][0], 0);
+ p->state = kLiteralNextStates[p->state];
+ curByte = p->matchFinder.GetIndexByte(p->matchFinderObj, 0 - p->additionalOffset);
+ LitEnc_Encode(&p->rc, p->litProbs, curByte);
+ p->additionalOffset--;
+ nowPos32++;
+ }
+
+ if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0)
+ for (;;)
+ {
+ UInt32 pos, len, posState;
+
+ if (p->fastMode)
+ len = GetOptimumFast(p, &pos);
+ else
+ len = GetOptimum(p, nowPos32, &pos);
+
+ #ifdef SHOW_STAT2
+ printf("\n pos = %4X, len = %d pos = %d", nowPos32, len, pos);
+ #endif
+
+ posState = nowPos32 & p->pbMask;
+ if (len == 1 && pos == (UInt32)-1)
+ {
+ Byte curByte;
+ CLzmaProb *probs = NULL;
+ const Byte *data = NULL;
+
+ RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 0);
+ data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
+ curByte = *data;
+ probs = LIT_PROBS(nowPos32, *(data - 1));
+ if (IsCharState(p->state))
+ LitEnc_Encode(&p->rc, probs, curByte);
+ else
+ LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0] - 1));
+ p->state = kLiteralNextStates[p->state];
+ }
+ else
+ {
+ RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1);
+ if (pos < LZMA_NUM_REPS)
+ {
+ RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 1);
+ if (pos == 0)
+ {
+ RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 0);
+ RangeEnc_EncodeBit(&p->rc, &p->isRep0Long[p->state][posState], ((len == 1) ? 0 : 1));
+ }
+ else
+ {
+ UInt32 distance = p->reps[pos];
+ RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 1);
+ if (pos == 1)
+ RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 0);
+ else
+ {
+ RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 1);
+ RangeEnc_EncodeBit(&p->rc, &p->isRepG2[p->state], pos - 2);
+ if (pos == 3)
+ p->reps[3] = p->reps[2];
+ p->reps[2] = p->reps[1];
+ }
+ p->reps[1] = p->reps[0];
+ p->reps[0] = distance;
+ }
+ if (len == 1)
+ p->state = kShortRepNextStates[p->state];
+ else
+ {
+ LenEnc_Encode2(&p->repLenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);
+ p->state = kRepNextStates[p->state];
+ }
+ }
+ else
+ {
+ UInt32 posSlot;
+ RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0);
+ p->state = kMatchNextStates[p->state];
+ LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);
+ pos -= LZMA_NUM_REPS;
+ GetPosSlot(pos, posSlot);
+ RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot);
+
+ if (posSlot >= kStartPosModelIndex)
+ {
+ UInt32 footerBits = ((posSlot >> 1) - 1);
+ UInt32 base = ((2 | (posSlot & 1)) << footerBits);
+ UInt32 posReduced = pos - base;
+
+ if (posSlot < kEndPosModelIndex)
+ RcTree_ReverseEncode(&p->rc, p->posEncoders + base - posSlot - 1, footerBits, posReduced);
+ else
+ {
+ RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits);
+ RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask);
+ p->alignPriceCount++;
+ }
+ }
+ p->reps[3] = p->reps[2];
+ p->reps[2] = p->reps[1];
+ p->reps[1] = p->reps[0];
+ p->reps[0] = pos;
+ p->matchPriceCount++;
+ }
+ }
+ p->additionalOffset -= len;
+ nowPos32 += len;
+ if (p->additionalOffset == 0)
+ {
+ UInt32 processed;
+ if (!p->fastMode)
+ {
+ if (p->matchPriceCount >= (1 << 7))
+ FillDistancesPrices(p);
+ if (p->alignPriceCount >= kAlignTableSize)
+ FillAlignPrices(p);
+ }
+ if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)
+ break;
+ processed = nowPos32 - startPos32;
+ if (useLimits)
+ {
+ if (processed + kNumOpts + 300 >= maxUnpackSize ||
+ RangeEnc_GetProcessed(&p->rc) + kNumOpts * 2 >= maxPackSize)
+ break;
+ }
+ else if (processed >= (1 << 15))
+ {
+ p->nowPos64 += nowPos32 - startPos32;
+ return CheckErrors(p);
+ }
+ }
+ }
+ p->nowPos64 += nowPos32 - startPos32;
+ return Flush(p, nowPos32);
+}
+
+#define kBigHashDicLimit ((UInt32)1 << 24)
+
+static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+ UInt32 beforeSize = kNumOpts;
+ Bool btMode;
+ if (!RangeEnc_Alloc(&p->rc, alloc))
+ return SZ_ERROR_MEM;
+ btMode = (p->matchFinderBase.btMode != 0);
+ #ifndef _7ZIP_ST
+ p->mtMode = (p->multiThread && !p->fastMode && btMode);
+ #endif
+
+ {
+ unsigned lclp = p->lc + p->lp;
+ if (p->litProbs == 0 || p->saveState.litProbs == 0 || p->lclp != lclp)
+ {
+ LzmaEnc_FreeLits(p, alloc);
+ p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb));
+ p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb));
+ if (p->litProbs == 0 || p->saveState.litProbs == 0)
+ {
+ LzmaEnc_FreeLits(p, alloc);
+ return SZ_ERROR_MEM;
+ }
+ p->lclp = lclp;
+ }
+ }
+
+ p->matchFinderBase.bigHash = (p->dictSize > kBigHashDicLimit);
+
+ if (beforeSize + p->dictSize < keepWindowSize)
+ beforeSize = keepWindowSize - p->dictSize;
+
+ #ifndef _7ZIP_ST
+ if (p->mtMode)
+ {
+ RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig));
+ p->matchFinderObj = &p->matchFinderMt;
+ MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder);
+ }
+ else
+ #endif
+ {
+ if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig))
+ return SZ_ERROR_MEM;
+ p->matchFinderObj = &p->matchFinderBase;
+ MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder);
+ }
+ return SZ_OK;
+}
+
+void LzmaEnc_Init(CLzmaEnc *p)
+{
+ UInt32 i;
+ p->state = 0;
+ for (i = 0 ; i < LZMA_NUM_REPS; i++)
+ p->reps[i] = 0;
+
+ RangeEnc_Init(&p->rc);
+
+
+ for (i = 0; i < kNumStates; i++)
+ {
+ UInt32 j;
+ for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++)
+ {
+ p->isMatch[i][j] = kProbInitValue;
+ p->isRep0Long[i][j] = kProbInitValue;
+ }
+ p->isRep[i] = kProbInitValue;
+ p->isRepG0[i] = kProbInitValue;
+ p->isRepG1[i] = kProbInitValue;
+ p->isRepG2[i] = kProbInitValue;
+ }
+
+ {
+ UInt32 num = 0x300 << (p->lp + p->lc);
+ for (i = 0; i < num; i++)
+ p->litProbs[i] = kProbInitValue;
+ }
+
+ {
+ for (i = 0; i < kNumLenToPosStates; i++)
+ {
+ CLzmaProb *probs = p->posSlotEncoder[i];
+ UInt32 j;
+ for (j = 0; j < (1 << kNumPosSlotBits); j++)
+ probs[j] = kProbInitValue;
+ }
+ }
+ {
+ for (i = 0; i < kNumFullDistances - kEndPosModelIndex; i++)
+ p->posEncoders[i] = kProbInitValue;
+ }
+
+ LenEnc_Init(&p->lenEnc.p);
+ LenEnc_Init(&p->repLenEnc.p);
+
+ for (i = 0; i < (1 << kNumAlignBits); i++)
+ p->posAlignEncoder[i] = kProbInitValue;
+
+ p->optimumEndIndex = 0;
+ p->optimumCurrentIndex = 0;
+ p->additionalOffset = 0;
+
+ p->pbMask = (1 << p->pb) - 1;
+ p->lpMask = (1 << p->lp) - 1;
+}
+
+void LzmaEnc_InitPrices(CLzmaEnc *p)
+{
+ if (!p->fastMode)
+ {
+ FillDistancesPrices(p);
+ FillAlignPrices(p);
+ }
+
+ p->lenEnc.tableSize =
+ p->repLenEnc.tableSize =
+ p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN;
+ LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, p->ProbPrices);
+ LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, p->ProbPrices);
+}
+
+static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+ UInt32 i;
+ for (i = 0; i < (UInt32)kDicLogSizeMaxCompress; i++)
+ if (p->dictSize <= ((UInt32)1 << i))
+ break;
+ p->distTableSize = i * 2;
+
+ p->finished = False;
+ p->result = SZ_OK;
+ RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig));
+ LzmaEnc_Init(p);
+ LzmaEnc_InitPrices(p);
+ p->nowPos64 = 0;
+ return SZ_OK;
+}
+
+static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream,
+ ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+ CLzmaEnc *p = (CLzmaEnc *)pp;
+ p->matchFinderBase.stream = inStream;
+ p->needInit = 1;
+ p->rc.outStream = outStream;
+ return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig);
+}
+
+SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp,
+ ISeqInStream *inStream, UInt32 keepWindowSize,
+ ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+ CLzmaEnc *p = (CLzmaEnc *)pp;
+ p->matchFinderBase.stream = inStream;
+ p->needInit = 1;
+ return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
+}
+
+static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen)
+{
+ p->matchFinderBase.directInput = 1;
+ p->matchFinderBase.bufferBase = (Byte *)src;
+ p->matchFinderBase.directInputRem = srcLen;
+}
+
+SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,
+ UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+ CLzmaEnc *p = (CLzmaEnc *)pp;
+ LzmaEnc_SetInputBuf(p, src, srcLen);
+ p->needInit = 1;
+
+ return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
+}
+
+void LzmaEnc_Finish(CLzmaEncHandle pp)
+{
+ #ifndef _7ZIP_ST
+ CLzmaEnc *p = (CLzmaEnc *)pp;
+ if (p->mtMode)
+ MatchFinderMt_ReleaseStream(&p->matchFinderMt);
+ #else
+ (void)pp;
+ #endif
+}
+
+typedef struct
+{
+ ISeqOutStream funcTable;
+ Byte *data;
+ SizeT rem;
+ Bool overflow;
+} CSeqOutStreamBuf;
+
+static size_t MyWrite(void *pp, const void *data, size_t size)
+{
+ CSeqOutStreamBuf *p = (CSeqOutStreamBuf *)pp;
+ if (p->rem < size)
+ {
+ size = p->rem;
+ p->overflow = True;
+ }
+ memcpy(p->data, data, size);
+ p->rem -= size;
+ p->data += size;
+ return size;
+}
+
+
+UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp)
+{
+ const CLzmaEnc *p = (CLzmaEnc *)pp;
+ return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
+}
+
+const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp)
+{
+ const CLzmaEnc *p = (CLzmaEnc *)pp;
+ return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
+}
+
+SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
+ Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize)
+{
+ CLzmaEnc *p = (CLzmaEnc *)pp;
+ UInt64 nowPos64;
+ SRes res;
+ CSeqOutStreamBuf outStream;
+
+ outStream.funcTable.Write = MyWrite;
+ outStream.data = dest;
+ outStream.rem = *destLen;
+ outStream.overflow = False;
+
+ p->writeEndMark = False;
+ p->finished = False;
+ p->result = SZ_OK;
+
+ if (reInit)
+ LzmaEnc_Init(p);
+ LzmaEnc_InitPrices(p);
+ nowPos64 = p->nowPos64;
+ RangeEnc_Init(&p->rc);
+ p->rc.outStream = &outStream.funcTable;
+
+ res = LzmaEnc_CodeOneBlock(p, True, desiredPackSize, *unpackSize);
+
+ *unpackSize = (UInt32)(p->nowPos64 - nowPos64);
+ *destLen -= outStream.rem;
+ if (outStream.overflow)
+ return SZ_ERROR_OUTPUT_EOF;
+
+ return res;
+}
+
+static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress)
+{
+ SRes res = SZ_OK;
+
+ #ifndef _7ZIP_ST
+ Byte allocaDummy[0x300];
+ int i = 0;
+ for (i = 0; i < 16; i++)
+ allocaDummy[i] = (Byte)i;
+ #endif
+
+ for (;;)
+ {
+ res = LzmaEnc_CodeOneBlock(p, False, 0, 0);
+ if (res != SZ_OK || p->finished != 0)
+ break;
+ if (progress != 0)
+ {
+ res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc));
+ if (res != SZ_OK)
+ {
+ res = SZ_ERROR_PROGRESS;
+ break;
+ }
+ }
+ }
+ LzmaEnc_Finish(p);
+ return res;
+}
+
+SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress,
+ ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+ RINOK(LzmaEnc_Prepare(pp, outStream, inStream, alloc, allocBig));
+ return LzmaEnc_Encode2((CLzmaEnc *)pp, progress);
+}
+
+SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size)
+{
+ CLzmaEnc *p = (CLzmaEnc *)pp;
+ int i;
+ UInt32 dictSize = p->dictSize;
+ if (*size < LZMA_PROPS_SIZE)
+ return SZ_ERROR_PARAM;
+ *size = LZMA_PROPS_SIZE;
+ props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc);
+
+ for (i = 11; i <= 30; i++)
+ {
+ if (dictSize <= ((UInt32)2 << i))
+ {
+ dictSize = (2 << i);
+ break;
+ }
+ if (dictSize <= ((UInt32)3 << i))
+ {
+ dictSize = (3 << i);
+ break;
+ }
+ }
+
+ for (i = 0; i < 4; i++)
+ props[1 + i] = (Byte)(dictSize >> (8 * i));
+ return SZ_OK;
+}
+
+SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
+ int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+ SRes res;
+ CLzmaEnc *p = (CLzmaEnc *)pp;
+
+ CSeqOutStreamBuf outStream;
+
+ LzmaEnc_SetInputBuf(p, src, srcLen);
+
+ outStream.funcTable.Write = MyWrite;
+ outStream.data = dest;
+ outStream.rem = *destLen;
+ outStream.overflow = False;
+
+ p->writeEndMark = writeEndMark;
+
+ p->rc.outStream = &outStream.funcTable;
+ res = LzmaEnc_MemPrepare(pp, src, srcLen, 0, alloc, allocBig);
+ if (res == SZ_OK)
+ res = LzmaEnc_Encode2(p, progress);
+
+ *destLen -= outStream.rem;
+ if (outStream.overflow)
+ return SZ_ERROR_OUTPUT_EOF;
+ return res;
+}
+
+SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
+ const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
+ ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+ CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc);
+ SRes res;
+ if (p == 0)
+ return SZ_ERROR_MEM;
+
+ res = LzmaEnc_SetProps(p, props);
+ if (res == SZ_OK)
+ {
+ res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize);
+ if (res == SZ_OK)
+ res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen,
+ writeEndMark, progress, alloc, allocBig);
+ }
+
+ LzmaEnc_Destroy(p, alloc, allocBig);
+ return res;
+}
diff -urN linux-4.9.37/lib/lzma/Makefile linux-4.9.y/lib/lzma/Makefile
--- linux-4.9.37/lib/lzma/Makefile 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/lib/lzma/Makefile 2021-06-07 13:01:34.000000000 +0300
@@ -0,0 +1,7 @@
+lzma_compress-objs := LzFind.o LzmaEnc.o
+lzma_decompress-objs := LzmaDec.o
+
+obj-$(CONFIG_LZMA_COMPRESS) += lzma_compress.o
+obj-$(CONFIG_LZMA_DECOMPRESS) += lzma_decompress.o
+
+EXTRA_CFLAGS += -Iinclude/linux -Iinclude/linux/lzma -include types.h
diff -urN linux-4.9.37/lib/Makefile linux-4.9.y/lib/Makefile
--- linux-4.9.37/lib/Makefile 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/lib/Makefile 2021-06-07 13:01:34.000000000 +0300
@@ -1,6 +1,15 @@
#
# Makefile for some libs needed in the kernel.
#
+ifdef CONFIG_JFFS2_ZLIB
+ CONFIG_ZLIB_INFLATE:=y
+ CONFIG_ZLIB_DEFLATE:=y
+endif
+
+ifdef CONFIG_JFFS2_LZMA
+ CONFIG_LZMA_DECOMPRESS:=y
+ CONFIG_LZMA_COMPRESS:=y
+endif
ifdef CONFIG_FUNCTION_TRACER
ORIG_CFLAGS := $(KBUILD_CFLAGS)
@@ -108,6 +117,8 @@
obj-$(CONFIG_LZ4_DECOMPRESS) += lz4/
obj-$(CONFIG_XZ_DEC) += xz/
obj-$(CONFIG_RAID6_PQ) += raid6/
+obj-$(CONFIG_LZMA_COMPRESS) += lzma/
+obj-$(CONFIG_LZMA_DECOMPRESS) += lzma/
lib-$(CONFIG_DECOMPRESS_GZIP) += decompress_inflate.o
lib-$(CONFIG_DECOMPRESS_BZIP2) += decompress_bunzip2.o
diff -urN linux-4.9.37/lib/raid6/.gitignore linux-4.9.y/lib/raid6/.gitignore
--- linux-4.9.37/lib/raid6/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/lib/raid6/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,6 +0,0 @@
-mktables
-altivec*.c
-int*.c
-tables.c
-neon?.c
-s390vx?.c
diff -urN linux-4.9.37/mm/init-mm.c linux-4.9.y/mm/init-mm.c
--- linux-4.9.37/mm/init-mm.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/mm/init-mm.c 2021-06-07 13:01:34.000000000 +0300
@@ -25,3 +25,5 @@
.user_ns = &init_user_ns,
INIT_MM_CONTEXT(init_mm)
};
+
+EXPORT_SYMBOL(init_mm);
diff -urN linux-4.9.37/mm/page_alloc.c linux-4.9.y/mm/page_alloc.c
--- linux-4.9.37/mm/page_alloc.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/mm/page_alloc.c 2021-06-07 13:01:34.000000000 +0300
@@ -7335,7 +7335,7 @@
/* Make sure the range is really isolated. */
if (test_pages_isolated(outer_start, end, false)) {
- pr_info("%s: [%lx, %lx) PFNs busy\n",
+ pr_warn_once("%s: [%lx, %lx) PFNs busy\n",
__func__, outer_start, end);
ret = -EBUSY;
goto done;
diff -urN linux-4.9.37/net/core/net_namespace.c linux-4.9.y/net/core/net_namespace.c
--- linux-4.9.37/net/core/net_namespace.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/net/core/net_namespace.c 2021-06-07 13:01:34.000000000 +0300
@@ -263,7 +263,7 @@
spin_lock_irqsave(&net->nsid_lock, flags);
peer = idr_find(&net->netns_ids, id);
if (peer)
- get_net(peer);
+ peer = maybe_get_net(peer);
spin_unlock_irqrestore(&net->nsid_lock, flags);
rcu_read_unlock();
diff -urN linux-4.9.37/net/ipv4/cipso_ipv4.c linux-4.9.y/net/ipv4/cipso_ipv4.c
--- linux-4.9.37/net/ipv4/cipso_ipv4.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/net/ipv4/cipso_ipv4.c 2021-06-07 13:01:34.000000000 +0300
@@ -1271,7 +1271,8 @@
return ret_val;
}
- secattr->flags |= NETLBL_SECATTR_MLS_CAT;
+ if (secattr->attr.mls.cat)
+ secattr->flags |= NETLBL_SECATTR_MLS_CAT;
}
return 0;
@@ -1452,7 +1453,8 @@
return ret_val;
}
- secattr->flags |= NETLBL_SECATTR_MLS_CAT;
+ if (secattr->attr.mls.cat)
+ secattr->flags |= NETLBL_SECATTR_MLS_CAT;
}
return 0;
diff -urN linux-4.9.37/net/ipv4/ip_output.c linux-4.9.y/net/ipv4/ip_output.c
--- linux-4.9.37/net/ipv4/ip_output.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/net/ipv4/ip_output.c 2021-06-07 13:01:34.000000000 +0300
@@ -1260,7 +1260,7 @@
if (skb->ip_summed != CHECKSUM_PARTIAL)
return -EOPNOTSUPP;
- skb_shinfo(skb)->gso_size = mtu - fragheaderlen;
+ skb_shinfo(skb)->gso_size = maxfraglen - fragheaderlen;
skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
}
cork->length += size;
diff -urN linux-4.9.37/net/ipv4/proc.c linux-4.9.y/net/ipv4/proc.c
--- linux-4.9.37/net/ipv4/proc.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/net/ipv4/proc.c 2021-06-07 13:01:34.000000000 +0300
@@ -305,6 +305,7 @@
SNMP_MIB_ITEM("TCPKeepAlive", LINUX_MIB_TCPKEEPALIVE),
SNMP_MIB_ITEM("TCPMTUPFail", LINUX_MIB_TCPMTUPFAIL),
SNMP_MIB_ITEM("TCPMTUPSuccess", LINUX_MIB_TCPMTUPSUCCESS),
+ SNMP_MIB_ITEM("TCPWqueueTooBig", LINUX_MIB_TCPWQUEUETOOBIG),
SNMP_MIB_SENTINEL
};
diff -urN linux-4.9.37/net/ipv4/sysctl_net_ipv4.c linux-4.9.y/net/ipv4/sysctl_net_ipv4.c
--- linux-4.9.37/net/ipv4/sysctl_net_ipv4.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/net/ipv4/sysctl_net_ipv4.c 2021-06-07 13:01:34.000000000 +0300
@@ -35,6 +35,8 @@
static int ip_local_port_range_max[] = { 65535, 65535 };
static int tcp_adv_win_scale_min = -31;
static int tcp_adv_win_scale_max = 31;
+static int tcp_min_snd_mss_min = TCP_MIN_SND_MSS;
+static int tcp_min_snd_mss_max = 65535;
static int ip_ttl_min = 1;
static int ip_ttl_max = 255;
static int tcp_syn_retries_min = 1;
@@ -827,6 +829,15 @@
.proc_handler = proc_dointvec,
},
{
+ .procname = "tcp_min_snd_mss",
+ .data = &init_net.ipv4.sysctl_tcp_min_snd_mss,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec_minmax,
+ .extra1 = &tcp_min_snd_mss_min,
+ .extra2 = &tcp_min_snd_mss_max,
+ },
+ {
.procname = "tcp_probe_threshold",
.data = &init_net.ipv4.sysctl_tcp_probe_threshold,
.maxlen = sizeof(int),
diff -urN linux-4.9.37/net/ipv4/tcp.c linux-4.9.y/net/ipv4/tcp.c
--- linux-4.9.37/net/ipv4/tcp.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/net/ipv4/tcp.c 2021-06-07 13:01:34.000000000 +0300
@@ -3289,6 +3289,7 @@
unsigned long limit;
unsigned int i;
+ BUILD_BUG_ON(TCP_MIN_SND_MSS <= MAX_TCP_OPTION_SPACE);
BUILD_BUG_ON(sizeof(struct tcp_skb_cb) >
FIELD_SIZEOF(struct sk_buff, cb));
diff -urN linux-4.9.37/net/ipv4/tcp_input.c linux-4.9.y/net/ipv4/tcp_input.c
--- linux-4.9.37/net/ipv4/tcp_input.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/net/ipv4/tcp_input.c 2021-06-07 13:01:34.000000000 +0300
@@ -1312,7 +1312,7 @@
TCP_SKB_CB(skb)->seq += shifted;
tcp_skb_pcount_add(prev, pcount);
- BUG_ON(tcp_skb_pcount(skb) < pcount);
+ WARN_ON_ONCE(tcp_skb_pcount(skb) < pcount);
tcp_skb_pcount_add(skb, -pcount);
/* When we're adding to gso_segs == 1, gso_size will be zero,
@@ -1379,6 +1379,21 @@
return !skb_headlen(skb) && skb_is_nonlinear(skb);
}
+int tcp_skb_shift(struct sk_buff *to, struct sk_buff *from,
+ int pcount, int shiftlen)
+{
+ /* TCP min gso_size is 8 bytes (TCP_MIN_GSO_SIZE)
+ * Since TCP_SKB_CB(skb)->tcp_gso_segs is 16 bits, we need
+ * to make sure not storing more than 65535 * 8 bytes per skb,
+ * even if current MSS is bigger.
+ */
+ if (unlikely(to->len + shiftlen >= 65535 * TCP_MIN_GSO_SIZE))
+ return 0;
+ if (unlikely(tcp_skb_pcount(to) + pcount > 65535))
+ return 0;
+ return skb_shift(to, from, shiftlen);
+}
+
/* Try collapsing SACK blocks spanning across multiple skbs to a single
* skb.
*/
@@ -1390,6 +1405,7 @@
struct tcp_sock *tp = tcp_sk(sk);
struct sk_buff *prev;
int mss;
+ int next_pcount;
int pcount = 0;
int len;
int in_sack;
@@ -1487,7 +1503,7 @@
if (!after(TCP_SKB_CB(skb)->seq + len, tp->snd_una))
goto fallback;
- if (!skb_shift(prev, skb, len))
+ if (!tcp_skb_shift(prev, skb, pcount, len))
goto fallback;
if (!tcp_shifted_skb(sk, skb, state, pcount, len, mss, dup_sack))
goto out;
@@ -1506,11 +1522,11 @@
goto out;
len = skb->len;
- if (skb_shift(prev, skb, len)) {
- pcount += tcp_skb_pcount(skb);
- tcp_shifted_skb(sk, skb, state, tcp_skb_pcount(skb), len, mss, 0);
+ next_pcount = tcp_skb_pcount(skb);
+ if (tcp_skb_shift(prev, skb, next_pcount, len)) {
+ pcount += next_pcount;
+ tcp_shifted_skb(sk, skb, state, next_pcount, len, mss, 0);
}
-
out:
state->fack_count += pcount;
return prev;
@@ -4949,6 +4965,7 @@
* 2) not add too big latencies if thousands of packets sit there.
* (But if application shrinks SO_RCVBUF, we could still end up
* freeing whole queue here)
+ * 3) Drop at least 12.5 % of sk_rcvbuf to avoid malicious attacks.
*
* Return true if queue has shrunk.
*/
@@ -4956,20 +4973,26 @@
{
struct tcp_sock *tp = tcp_sk(sk);
struct rb_node *node, *prev;
+ int goal;
if (RB_EMPTY_ROOT(&tp->out_of_order_queue))
return false;
NET_INC_STATS(sock_net(sk), LINUX_MIB_OFOPRUNED);
+ goal = sk->sk_rcvbuf >> 3;
node = &tp->ooo_last_skb->rbnode;
do {
prev = rb_prev(node);
rb_erase(node, &tp->out_of_order_queue);
+ goal -= rb_entry_safe(node, struct sk_buff, rbnode)->truesize;
tcp_drop(sk, rb_entry(node, struct sk_buff, rbnode));
- sk_mem_reclaim(sk);
- if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf &&
- !tcp_under_memory_pressure(sk))
- break;
+ if (!prev || goal <= 0) {
+ sk_mem_reclaim(sk);
+ if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf &&
+ !tcp_under_memory_pressure(sk))
+ break;
+ goal = sk->sk_rcvbuf >> 3;
+ }
node = prev;
} while (node);
tp->ooo_last_skb = rb_entry(prev, struct sk_buff, rbnode);
diff -urN linux-4.9.37/net/ipv4/tcp_ipv4.c linux-4.9.y/net/ipv4/tcp_ipv4.c
--- linux-4.9.37/net/ipv4/tcp_ipv4.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/net/ipv4/tcp_ipv4.c 2021-06-07 13:01:34.000000000 +0300
@@ -2440,6 +2440,7 @@
net->ipv4.sysctl_tcp_ecn_fallback = 1;
net->ipv4.sysctl_tcp_base_mss = TCP_BASE_MSS;
+ net->ipv4.sysctl_tcp_min_snd_mss = TCP_MIN_SND_MSS;
net->ipv4.sysctl_tcp_probe_threshold = TCP_PROBE_THRESHOLD;
net->ipv4.sysctl_tcp_probe_interval = TCP_PROBE_INTERVAL;
diff -urN linux-4.9.37/net/ipv4/tcp_output.c linux-4.9.y/net/ipv4/tcp_output.c
--- linux-4.9.37/net/ipv4/tcp_output.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/net/ipv4/tcp_output.c 2021-06-07 13:01:34.000000000 +0300
@@ -1170,6 +1170,11 @@
if (nsize < 0)
nsize = 0;
+ if (unlikely((sk->sk_wmem_queued >> 1) > sk->sk_sndbuf)) {
+ NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPWQUEUETOOBIG);
+ return -ENOMEM;
+ }
+
if (skb_unclone(skb, gfp))
return -ENOMEM;
@@ -1340,8 +1345,7 @@
mss_now -= icsk->icsk_ext_hdr_len;
/* Then reserve room for full set of TCP options and 8 bytes of data */
- if (mss_now < 48)
- mss_now = 48;
+ mss_now = max(mss_now, sock_net(sk)->ipv4.sysctl_tcp_min_snd_mss);
return mss_now;
}
diff -urN linux-4.9.37/net/ipv4/tcp_timer.c linux-4.9.y/net/ipv4/tcp_timer.c
--- linux-4.9.37/net/ipv4/tcp_timer.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/net/ipv4/tcp_timer.c 2021-06-07 13:01:34.000000000 +0300
@@ -125,6 +125,7 @@
mss = tcp_mtu_to_mss(sk, icsk->icsk_mtup.search_low) >> 1;
mss = min(net->ipv4.sysctl_tcp_base_mss, mss);
mss = max(mss, 68 - tp->tcp_header_len);
+ mss = max(mss, net->ipv4.sysctl_tcp_min_snd_mss);
icsk->icsk_mtup.search_low = tcp_mss_to_mtu(sk, mss);
tcp_sync_mss(sk, icsk->icsk_pmtu_cookie);
}
diff -urN linux-4.9.37/net/ipv6/calipso.c linux-4.9.y/net/ipv6/calipso.c
--- linux-4.9.37/net/ipv6/calipso.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/net/ipv6/calipso.c 2021-06-07 13:01:34.000000000 +0300
@@ -1062,7 +1062,8 @@
goto getattr_return;
}
- secattr->flags |= NETLBL_SECATTR_MLS_CAT;
+ if (secattr->attr.mls.cat)
+ secattr->flags |= NETLBL_SECATTR_MLS_CAT;
}
secattr->type = NETLBL_NLTYPE_CALIPSO;
diff -urN linux-4.9.37/net/ipv6/output_core.c linux-4.9.y/net/ipv6/output_core.c
--- linux-4.9.37/net/ipv6/output_core.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/net/ipv6/output_core.c 2021-06-07 13:01:34.000000000 +0300
@@ -78,7 +78,7 @@
int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
{
- u16 offset = sizeof(struct ipv6hdr);
+ unsigned int offset = sizeof(struct ipv6hdr);
unsigned int packet_len = skb_tail_pointer(skb) -
skb_network_header(skb);
int found_rhdr = 0;
@@ -86,6 +86,7 @@
while (offset <= packet_len) {
struct ipv6_opt_hdr *exthdr;
+ unsigned int len;
switch (**nexthdr) {
@@ -111,7 +112,10 @@
exthdr = (struct ipv6_opt_hdr *)(skb_network_header(skb) +
offset);
- offset += ipv6_optlen(exthdr);
+ len = ipv6_optlen(exthdr);
+ if (len + offset >= IPV6_MAXPLEN)
+ return -EINVAL;
+ offset += len;
*nexthdr = &exthdr->nexthdr;
}
diff -urN linux-4.9.37/net/netlabel/netlabel_kapi.c linux-4.9.y/net/netlabel/netlabel_kapi.c
--- linux-4.9.37/net/netlabel/netlabel_kapi.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/net/netlabel/netlabel_kapi.c 2021-06-07 13:01:34.000000000 +0300
@@ -748,6 +748,12 @@
if ((off & (BITS_PER_LONG - 1)) != 0)
return -EINVAL;
+ /* a null catmap is equivalent to an empty one */
+ if (!catmap) {
+ *offset = (u32)-1;
+ return 0;
+ }
+
if (off < catmap->startbit) {
off = catmap->startbit;
*offset = off;
diff -urN linux-4.9.37/net/wireless/.gitignore linux-4.9.y/net/wireless/.gitignore
--- linux-4.9.37/net/wireless/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/net/wireless/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-regdb.c
diff -urN linux-4.9.37/samples/auxdisplay/.gitignore linux-4.9.y/samples/auxdisplay/.gitignore
--- linux-4.9.37/samples/auxdisplay/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/samples/auxdisplay/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-cfag12864b-example
diff -urN linux-4.9.37/samples/connector/.gitignore linux-4.9.y/samples/connector/.gitignore
--- linux-4.9.37/samples/connector/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/samples/connector/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-ucon
diff -urN linux-4.9.37/samples/hidraw/.gitignore linux-4.9.y/samples/hidraw/.gitignore
--- linux-4.9.37/samples/hidraw/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/samples/hidraw/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-hid-example
diff -urN linux-4.9.37/samples/mei/.gitignore linux-4.9.y/samples/mei/.gitignore
--- linux-4.9.37/samples/mei/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/samples/mei/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-mei-amt-version
diff -urN linux-4.9.37/samples/mic/mpssd/.gitignore linux-4.9.y/samples/mic/mpssd/.gitignore
--- linux-4.9.37/samples/mic/mpssd/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/samples/mic/mpssd/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-mpssd
diff -urN linux-4.9.37/samples/seccomp/.gitignore linux-4.9.y/samples/seccomp/.gitignore
--- linux-4.9.37/samples/seccomp/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/samples/seccomp/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,3 +0,0 @@
-bpf-direct
-bpf-fancy
-dropper
diff -urN linux-4.9.37/samples/timers/.gitignore linux-4.9.y/samples/timers/.gitignore
--- linux-4.9.37/samples/timers/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/samples/timers/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-hpet_example
diff -urN linux-4.9.37/samples/watchdog/.gitignore linux-4.9.y/samples/watchdog/.gitignore
--- linux-4.9.37/samples/watchdog/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/samples/watchdog/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-watchdog-simple
diff -urN linux-4.9.37/scripts/basic/.gitignore linux-4.9.y/scripts/basic/.gitignore
--- linux-4.9.37/scripts/basic/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/scripts/basic/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,2 +0,0 @@
-fixdep
-bin2c
diff -urN linux-4.9.37/scripts/dtc/.gitignore linux-4.9.y/scripts/dtc/.gitignore
--- linux-4.9.37/scripts/dtc/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/scripts/dtc/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,4 +0,0 @@
-dtc
-dtc-lexer.lex.c
-dtc-parser.tab.c
-dtc-parser.tab.h
diff -urN linux-4.9.37/scripts/gdb/linux/.gitignore linux-4.9.y/scripts/gdb/linux/.gitignore
--- linux-4.9.37/scripts/gdb/linux/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/scripts/gdb/linux/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,3 +0,0 @@
-*.pyc
-*.pyo
-constants.py
diff -urN linux-4.9.37/scripts/genksyms/.gitignore linux-4.9.y/scripts/genksyms/.gitignore
--- linux-4.9.37/scripts/genksyms/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/scripts/genksyms/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,5 +0,0 @@
-*.hash.c
-*.lex.c
-*.tab.c
-*.tab.h
-genksyms
diff -urN linux-4.9.37/scripts/.gitignore linux-4.9.y/scripts/.gitignore
--- linux-4.9.37/scripts/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/scripts/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,16 +0,0 @@
-#
-# Generated files
-#
-conmakehash
-kallsyms
-pnmtologo
-unifdef
-ihex2fw
-recordmcount
-docproc
-check-lc_ctype
-sortextable
-asn1_compiler
-extract-cert
-sign-file
-insert-sys-cert
diff -urN linux-4.9.37/scripts/kconfig/.gitignore linux-4.9.y/scripts/kconfig/.gitignore
--- linux-4.9.37/scripts/kconfig/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/scripts/kconfig/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,22 +0,0 @@
-#
-# Generated files
-#
-config*
-*.lex.c
-*.tab.c
-*.tab.h
-zconf.hash.c
-*.moc
-gconf.glade.h
-*.pot
-*.mo
-
-#
-# configuration programs
-#
-conf
-mconf
-nconf
-qconf
-gconf
-kxgettext
diff -urN linux-4.9.37/scripts/kconfig/lxdialog/.gitignore linux-4.9.y/scripts/kconfig/lxdialog/.gitignore
--- linux-4.9.37/scripts/kconfig/lxdialog/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/scripts/kconfig/lxdialog/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,4 +0,0 @@
-#
-# Generated files
-#
-lxdialog
diff -urN linux-4.9.37/scripts/Makefile.clean linux-4.9.y/scripts/Makefile.clean
--- linux-4.9.37/scripts/Makefile.clean 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/scripts/Makefile.clean 2021-06-07 13:01:34.000000000 +0300
@@ -11,7 +11,7 @@
# The filename Kbuild has precedence over Makefile
kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
-include $(if $(wildcard $(kbuild-dir)/Kbuild), $(kbuild-dir)/Kbuild, $(kbuild-dir)/Makefile)
+-include $(if $(wildcard $(kbuild-dir)/Kbuild), $(kbuild-dir)/Kbuild, $(kbuild-dir)/Makefile)
# Figure out what we need to build from the various variables
# ==========================================================================
diff -urN linux-4.9.37/scripts/mod/.gitignore linux-4.9.y/scripts/mod/.gitignore
--- linux-4.9.37/scripts/mod/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/scripts/mod/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,4 +0,0 @@
-elfconfig.h
-mk_elfconfig
-modpost
-devicetable-offsets.h
diff -urN linux-4.9.37/scripts/selinux/genheaders/.gitignore linux-4.9.y/scripts/selinux/genheaders/.gitignore
--- linux-4.9.37/scripts/selinux/genheaders/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/scripts/selinux/genheaders/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-genheaders
diff -urN linux-4.9.37/scripts/selinux/mdp/.gitignore linux-4.9.y/scripts/selinux/mdp/.gitignore
--- linux-4.9.37/scripts/selinux/mdp/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/scripts/selinux/mdp/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,2 +0,0 @@
-# Generated file
-mdp
diff -urN linux-4.9.37/scripts/setlocalversion linux-4.9.y/scripts/setlocalversion
--- linux-4.9.37/scripts/setlocalversion 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/scripts/setlocalversion 2021-06-07 13:01:34.000000000 +0300
@@ -153,6 +153,7 @@
res="$res$(collect_files "$srctree"/localversion*)"
fi
+LOCALVERSION=
# CONFIG_LOCALVERSION and LOCALVERSION (if set)
res="${res}${CONFIG_LOCALVERSION}${LOCALVERSION}"
diff -urN linux-4.9.37/security/apparmor/.gitignore linux-4.9.y/security/apparmor/.gitignore
--- linux-4.9.37/security/apparmor/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/security/apparmor/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,5 +0,0 @@
-#
-# Generated include files
-#
-capability_names.h
-rlim_names.h
diff -urN linux-4.9.37/security/selinux/.gitignore linux-4.9.y/security/selinux/.gitignore
--- linux-4.9.37/security/selinux/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/security/selinux/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,2 +0,0 @@
-av_permissions.h
-flask.h
diff -urN linux-4.9.37/security/tomoyo/.gitignore linux-4.9.y/security/tomoyo/.gitignore
--- linux-4.9.37/security/tomoyo/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/security/tomoyo/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,2 +0,0 @@
-builtin-policy.h
-policy/*.conf
diff -urN linux-4.9.37/sound/oss/.gitignore linux-4.9.y/sound/oss/.gitignore
--- linux-4.9.37/sound/oss/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/sound/oss/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,3 +0,0 @@
-#Ignore generated files
-pss_boot.h
-trix_boot.h
diff -urN linux-4.9.37/sound/usb/mixer.c linux-4.9.y/sound/usb/mixer.c
--- linux-4.9.37/sound/usb/mixer.c 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/sound/usb/mixer.c 2021-06-07 13:01:34.000000000 +0300
@@ -318,12 +318,15 @@
while (timeout-- > 0) {
idx = snd_usb_ctrl_intf(chip) | (cval->head.id << 8);
- if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request,
- USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
- validx, idx, buf, val_len) >= val_len) {
+ err = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request,
+ USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
+ validx, idx, buf, val_len);
+ if (err >= val_len) {
*value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len));
err = 0;
goto out;
+ } else if (err == -ETIMEDOUT) {
+ goto out;
}
}
usb_audio_dbg(chip,
@@ -483,12 +486,15 @@
while (timeout-- > 0) {
idx = snd_usb_ctrl_intf(chip) | (cval->head.id << 8);
- if (snd_usb_ctl_msg(chip->dev,
- usb_sndctrlpipe(chip->dev, 0), request,
- USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
- validx, idx, buf, val_len) >= 0) {
+ err = snd_usb_ctl_msg(chip->dev,
+ usb_sndctrlpipe(chip->dev, 0), request,
+ USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
+ validx, idx, buf, val_len);
+ if (err >= 0) {
err = 0;
goto out;
+ } else if (err == -ETIMEDOUT) {
+ goto out;
}
}
usb_audio_dbg(chip, "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n",
diff -urN linux-4.9.37/tools/accounting/.gitignore linux-4.9.y/tools/accounting/.gitignore
--- linux-4.9.37/tools/accounting/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/accounting/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-getdelays
diff -urN linux-4.9.37/tools/build/feature/.gitignore linux-4.9.y/tools/build/feature/.gitignore
--- linux-4.9.37/tools/build/feature/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/build/feature/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,3 +0,0 @@
-*.d
-*.bin
-*.output
diff -urN linux-4.9.37/tools/build/.gitignore linux-4.9.y/tools/build/.gitignore
--- linux-4.9.37/tools/build/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/build/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-fixdep
diff -urN linux-4.9.37/tools/cgroup/.gitignore linux-4.9.y/tools/cgroup/.gitignore
--- linux-4.9.37/tools/cgroup/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/cgroup/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-cgroup_event_listener
diff -urN linux-4.9.37/tools/laptop/dslm/.gitignore linux-4.9.y/tools/laptop/dslm/.gitignore
--- linux-4.9.37/tools/laptop/dslm/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/laptop/dslm/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-dslm
diff -urN linux-4.9.37/tools/lguest/.gitignore linux-4.9.y/tools/lguest/.gitignore
--- linux-4.9.37/tools/lguest/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/lguest/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,2 +0,0 @@
-lguest
-include
diff -urN linux-4.9.37/tools/lib/bpf/.gitignore linux-4.9.y/tools/lib/bpf/.gitignore
--- linux-4.9.37/tools/lib/bpf/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/lib/bpf/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,2 +0,0 @@
-libbpf_version.h
-FEATURE-DUMP.libbpf
diff -urN linux-4.9.37/tools/lib/lockdep/.gitignore linux-4.9.y/tools/lib/lockdep/.gitignore
--- linux-4.9.37/tools/lib/lockdep/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/lib/lockdep/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-liblockdep.so.*
diff -urN linux-4.9.37/tools/lib/traceevent/.gitignore linux-4.9.y/tools/lib/traceevent/.gitignore
--- linux-4.9.37/tools/lib/traceevent/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/lib/traceevent/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,3 +0,0 @@
-TRACEEVENT-CFLAGS
-libtraceevent-dynamic-list
-libtraceevent.so.*
diff -urN linux-4.9.37/tools/objtool/.gitignore linux-4.9.y/tools/objtool/.gitignore
--- linux-4.9.37/tools/objtool/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/objtool/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,3 +0,0 @@
-arch/x86/insn/inat-tables.c
-objtool
-fixdep
diff -urN linux-4.9.37/tools/pcmcia/.gitignore linux-4.9.y/tools/pcmcia/.gitignore
--- linux-4.9.37/tools/pcmcia/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/pcmcia/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-crc32hash
diff -urN linux-4.9.37/tools/perf/.gitignore linux-4.9.y/tools/perf/.gitignore
--- linux-4.9.37/tools/perf/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/perf/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,33 +0,0 @@
-PERF-CFLAGS
-PERF-GUI-VARS
-PERF-VERSION-FILE
-FEATURE-DUMP
-perf
-perf-read-vdso32
-perf-read-vdsox32
-perf-help
-perf-record
-perf-report
-perf-stat
-perf-top
-perf*.1
-perf*.xml
-perf*.html
-common-cmds.h
-perf.data
-perf.data.old
-output.svg
-perf-archive
-perf-with-kcore
-tags
-TAGS
-cscope*
-config.mak
-config.mak.autogen
-*-bison.*
-*-flex.*
-*.pyc
-*.pyo
-.config-detected
-util/intel-pt-decoder/inat-tables.c
-arch/*/include/generated/
diff -urN linux-4.9.37/tools/perf/tests/.gitignore linux-4.9.y/tools/perf/tests/.gitignore
--- linux-4.9.37/tools/perf/tests/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/perf/tests/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,4 +0,0 @@
-llvm-src-base.c
-llvm-src-kbuild.c
-llvm-src-prologue.c
-llvm-src-relocation.c
diff -urN linux-4.9.37/tools/power/cpupower/.gitignore linux-4.9.y/tools/power/cpupower/.gitignore
--- linux-4.9.37/tools/power/cpupower/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/power/cpupower/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,29 +0,0 @@
-.libs
-libcpupower.so
-libcpupower.so.0
-libcpupower.so.0.0.0
-build/ccdv
-cpufreq-info
-cpufreq-set
-cpufreq-aperf
-lib/.libs
-lib/cpufreq.lo
-lib/cpufreq.o
-lib/proc.lo
-lib/proc.o
-lib/sysfs.lo
-lib/sysfs.o
-po/cpupowerutils.pot
-po/*.gmo
-utils/cpufreq-info.o
-utils/cpufreq-set.o
-utils/cpufreq-aperf.o
-cpupower
-bench/cpufreq-bench
-debug/kernel/Module.symvers
-debug/i386/centrino-decode
-debug/i386/dump_psb
-debug/i386/intel_gsic
-debug/i386/powernow-k8-decode
-debug/x86_64/centrino-decode
-debug/x86_64/powernow-k8-decode
diff -urN linux-4.9.37/tools/power/x86/turbostat/.gitignore linux-4.9.y/tools/power/x86/turbostat/.gitignore
--- linux-4.9.37/tools/power/x86/turbostat/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/power/x86/turbostat/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-turbostat
diff -urN linux-4.9.37/tools/spi/.gitignore linux-4.9.y/tools/spi/.gitignore
--- linux-4.9.37/tools/spi/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/spi/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,2 +0,0 @@
-spidev_fdx
-spidev_test
diff -urN linux-4.9.37/tools/testing/radix-tree/.gitignore linux-4.9.y/tools/testing/radix-tree/.gitignore
--- linux-4.9.37/tools/testing/radix-tree/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/radix-tree/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,2 +0,0 @@
-main
-radix-tree.c
diff -urN linux-4.9.37/tools/testing/selftests/breakpoints/.gitignore linux-4.9.y/tools/testing/selftests/breakpoints/.gitignore
--- linux-4.9.37/tools/testing/selftests/breakpoints/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/breakpoints/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,2 +0,0 @@
-breakpoint_test
-step_after_suspend_test
diff -urN linux-4.9.37/tools/testing/selftests/capabilities/.gitignore linux-4.9.y/tools/testing/selftests/capabilities/.gitignore
--- linux-4.9.37/tools/testing/selftests/capabilities/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/capabilities/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,2 +0,0 @@
-test_execve
-validate_cap
diff -urN linux-4.9.37/tools/testing/selftests/efivarfs/.gitignore linux-4.9.y/tools/testing/selftests/efivarfs/.gitignore
--- linux-4.9.37/tools/testing/selftests/efivarfs/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/efivarfs/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,2 +0,0 @@
-create-read
-open-unlink
diff -urN linux-4.9.37/tools/testing/selftests/exec/.gitignore linux-4.9.y/tools/testing/selftests/exec/.gitignore
--- linux-4.9.37/tools/testing/selftests/exec/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/exec/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,9 +0,0 @@
-subdir*
-script*
-execveat
-execveat.symlink
-execveat.moved
-execveat.path.ephemeral
-execveat.ephemeral
-execveat.denatured
-xxxxxxxx*
\ В конце файла нет новой строки
diff -urN linux-4.9.37/tools/testing/selftests/filesystems/.gitignore linux-4.9.y/tools/testing/selftests/filesystems/.gitignore
--- linux-4.9.37/tools/testing/selftests/filesystems/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/filesystems/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-dnotify_test
diff -urN linux-4.9.37/tools/testing/selftests/futex/functional/.gitignore linux-4.9.y/tools/testing/selftests/futex/functional/.gitignore
--- linux-4.9.37/tools/testing/selftests/futex/functional/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/futex/functional/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,7 +0,0 @@
-futex_requeue_pi
-futex_requeue_pi_mismatched_ops
-futex_requeue_pi_signal_restart
-futex_wait_private_mapped_file
-futex_wait_timeout
-futex_wait_uninitialized_heap
-futex_wait_wouldblock
diff -urN linux-4.9.37/tools/testing/selftests/ia64/.gitignore linux-4.9.y/tools/testing/selftests/ia64/.gitignore
--- linux-4.9.37/tools/testing/selftests/ia64/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/ia64/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-aliasing-test
diff -urN linux-4.9.37/tools/testing/selftests/ipc/.gitignore linux-4.9.y/tools/testing/selftests/ipc/.gitignore
--- linux-4.9.37/tools/testing/selftests/ipc/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/ipc/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-msgque_test
diff -urN linux-4.9.37/tools/testing/selftests/kcmp/.gitignore linux-4.9.y/tools/testing/selftests/kcmp/.gitignore
--- linux-4.9.37/tools/testing/selftests/kcmp/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/kcmp/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,2 +0,0 @@
-kcmp_test
-kcmp-test-file
diff -urN linux-4.9.37/tools/testing/selftests/media_tests/.gitignore linux-4.9.y/tools/testing/selftests/media_tests/.gitignore
--- linux-4.9.37/tools/testing/selftests/media_tests/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/media_tests/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,3 +0,0 @@
-media_device_test
-media_device_open
-video_device_test
diff -urN linux-4.9.37/tools/testing/selftests/membarrier/.gitignore linux-4.9.y/tools/testing/selftests/membarrier/.gitignore
--- linux-4.9.37/tools/testing/selftests/membarrier/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/membarrier/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-membarrier_test
diff -urN linux-4.9.37/tools/testing/selftests/memfd/.gitignore linux-4.9.y/tools/testing/selftests/memfd/.gitignore
--- linux-4.9.37/tools/testing/selftests/memfd/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/memfd/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,4 +0,0 @@
-fuse_mnt
-fuse_test
-memfd_test
-memfd-test-file
diff -urN linux-4.9.37/tools/testing/selftests/mount/.gitignore linux-4.9.y/tools/testing/selftests/mount/.gitignore
--- linux-4.9.37/tools/testing/selftests/mount/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/mount/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-unprivileged-remount-test
diff -urN linux-4.9.37/tools/testing/selftests/mqueue/.gitignore linux-4.9.y/tools/testing/selftests/mqueue/.gitignore
--- linux-4.9.37/tools/testing/selftests/mqueue/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/mqueue/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,2 +0,0 @@
-mq_open_tests
-mq_perf_tests
diff -urN linux-4.9.37/tools/testing/selftests/net/.gitignore linux-4.9.y/tools/testing/selftests/net/.gitignore
--- linux-4.9.37/tools/testing/selftests/net/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/net/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,6 +0,0 @@
-socket
-psock_fanout
-psock_tpacket
-reuseport_bpf
-reuseport_bpf_cpu
-reuseport_dualstack
diff -urN linux-4.9.37/tools/testing/selftests/networking/timestamping/.gitignore linux-4.9.y/tools/testing/selftests/networking/timestamping/.gitignore
--- linux-4.9.37/tools/testing/selftests/networking/timestamping/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/networking/timestamping/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,3 +0,0 @@
-timestamping
-txtimestamp
-hwtstamp_config
diff -urN linux-4.9.37/tools/testing/selftests/powerpc/alignment/.gitignore linux-4.9.y/tools/testing/selftests/powerpc/alignment/.gitignore
--- linux-4.9.37/tools/testing/selftests/powerpc/alignment/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/powerpc/alignment/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,5 +0,0 @@
-copy_unaligned
-copy_first_unaligned
-paste_unaligned
-paste_last_unaligned
-copy_paste_unaligned_common
diff -urN linux-4.9.37/tools/testing/selftests/powerpc/benchmarks/.gitignore linux-4.9.y/tools/testing/selftests/powerpc/benchmarks/.gitignore
--- linux-4.9.37/tools/testing/selftests/powerpc/benchmarks/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/powerpc/benchmarks/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,4 +0,0 @@
-gettimeofday
-context_switch
-mmap_bench
-futex_bench
\ В конце файла нет новой строки
diff -urN linux-4.9.37/tools/testing/selftests/powerpc/context_switch/.gitignore linux-4.9.y/tools/testing/selftests/powerpc/context_switch/.gitignore
--- linux-4.9.37/tools/testing/selftests/powerpc/context_switch/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/powerpc/context_switch/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-cp_abort
diff -urN linux-4.9.37/tools/testing/selftests/powerpc/copyloops/.gitignore linux-4.9.y/tools/testing/selftests/powerpc/copyloops/.gitignore
--- linux-4.9.37/tools/testing/selftests/powerpc/copyloops/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/powerpc/copyloops/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,4 +0,0 @@
-copyuser_64
-copyuser_power7
-memcpy_64
-memcpy_power7
diff -urN linux-4.9.37/tools/testing/selftests/powerpc/dscr/.gitignore linux-4.9.y/tools/testing/selftests/powerpc/dscr/.gitignore
--- linux-4.9.37/tools/testing/selftests/powerpc/dscr/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/powerpc/dscr/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,7 +0,0 @@
-dscr_default_test
-dscr_explicit_test
-dscr_inherit_exec_test
-dscr_inherit_test
-dscr_sysfs_test
-dscr_sysfs_thread_test
-dscr_user_test
diff -urN linux-4.9.37/tools/testing/selftests/powerpc/math/.gitignore linux-4.9.y/tools/testing/selftests/powerpc/math/.gitignore
--- linux-4.9.37/tools/testing/selftests/powerpc/math/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/powerpc/math/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,7 +0,0 @@
-fpu_syscall
-vmx_syscall
-fpu_preempt
-vmx_preempt
-fpu_signal
-vmx_signal
-vsx_preempt
diff -urN linux-4.9.37/tools/testing/selftests/powerpc/mm/.gitignore linux-4.9.y/tools/testing/selftests/powerpc/mm/.gitignore
--- linux-4.9.37/tools/testing/selftests/powerpc/mm/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/powerpc/mm/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,4 +0,0 @@
-hugetlb_vs_thp_test
-subpage_prot
-tempfile
-prot_sao
\ В конце файла нет новой строки
diff -urN linux-4.9.37/tools/testing/selftests/powerpc/pmu/ebb/.gitignore linux-4.9.y/tools/testing/selftests/powerpc/pmu/ebb/.gitignore
--- linux-4.9.37/tools/testing/selftests/powerpc/pmu/ebb/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/powerpc/pmu/ebb/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,24 +0,0 @@
-reg_access_test
-event_attributes_test
-cycles_test
-cycles_with_freeze_test
-pmc56_overflow_test
-ebb_vs_cpu_event_test
-cpu_event_vs_ebb_test
-cpu_event_pinned_vs_ebb_test
-task_event_vs_ebb_test
-task_event_pinned_vs_ebb_test
-multi_ebb_procs_test
-multi_counter_test
-pmae_handling_test
-close_clears_pmcc_test
-instruction_count_test
-fork_cleanup_test
-ebb_on_child_test
-ebb_on_willing_child_test
-back_to_back_ebbs_test
-lost_exception_test
-no_handler_test
-cycles_with_mmcr2_test
-ebb_lmr
-ebb_lmr_regs
\ В конце файла нет новой строки
diff -urN linux-4.9.37/tools/testing/selftests/powerpc/pmu/.gitignore linux-4.9.y/tools/testing/selftests/powerpc/pmu/.gitignore
--- linux-4.9.37/tools/testing/selftests/powerpc/pmu/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/powerpc/pmu/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,3 +0,0 @@
-count_instructions
-l3_bank_test
-per_event_excludes
diff -urN linux-4.9.37/tools/testing/selftests/powerpc/primitives/.gitignore linux-4.9.y/tools/testing/selftests/powerpc/primitives/.gitignore
--- linux-4.9.37/tools/testing/selftests/powerpc/primitives/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/powerpc/primitives/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-load_unaligned_zeropad
diff -urN linux-4.9.37/tools/testing/selftests/powerpc/signal/.gitignore linux-4.9.y/tools/testing/selftests/powerpc/signal/.gitignore
--- linux-4.9.37/tools/testing/selftests/powerpc/signal/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/powerpc/signal/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,2 +0,0 @@
-signal
-signal_tm
diff -urN linux-4.9.37/tools/testing/selftests/powerpc/stringloops/.gitignore linux-4.9.y/tools/testing/selftests/powerpc/stringloops/.gitignore
--- linux-4.9.37/tools/testing/selftests/powerpc/stringloops/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/powerpc/stringloops/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-memcmp
diff -urN linux-4.9.37/tools/testing/selftests/powerpc/switch_endian/.gitignore linux-4.9.y/tools/testing/selftests/powerpc/switch_endian/.gitignore
--- linux-4.9.37/tools/testing/selftests/powerpc/switch_endian/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/powerpc/switch_endian/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,2 +0,0 @@
-switch_endian_test
-check-reversed.S
diff -urN linux-4.9.37/tools/testing/selftests/powerpc/syscalls/.gitignore linux-4.9.y/tools/testing/selftests/powerpc/syscalls/.gitignore
--- linux-4.9.37/tools/testing/selftests/powerpc/syscalls/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/powerpc/syscalls/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-ipc_unmuxed
diff -urN linux-4.9.37/tools/testing/selftests/powerpc/tm/.gitignore linux-4.9.y/tools/testing/selftests/powerpc/tm/.gitignore
--- linux-4.9.37/tools/testing/selftests/powerpc/tm/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/powerpc/tm/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,13 +0,0 @@
-tm-resched-dscr
-tm-syscall
-tm-signal-msr-resv
-tm-signal-stack
-tm-vmxcopy
-tm-fork
-tm-tar
-tm-tmspr
-tm-exec
-tm-signal-context-chk-fpu
-tm-signal-context-chk-gpr
-tm-signal-context-chk-vmx
-tm-signal-context-chk-vsx
diff -urN linux-4.9.37/tools/testing/selftests/powerpc/vphn/.gitignore linux-4.9.y/tools/testing/selftests/powerpc/vphn/.gitignore
--- linux-4.9.37/tools/testing/selftests/powerpc/vphn/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/powerpc/vphn/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-test-vphn
diff -urN linux-4.9.37/tools/testing/selftests/prctl/.gitignore linux-4.9.y/tools/testing/selftests/prctl/.gitignore
--- linux-4.9.37/tools/testing/selftests/prctl/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/prctl/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,3 +0,0 @@
-disable-tsc-ctxt-sw-stress-test
-disable-tsc-on-off-stress-test
-disable-tsc-test
diff -urN linux-4.9.37/tools/testing/selftests/ptp/.gitignore linux-4.9.y/tools/testing/selftests/ptp/.gitignore
--- linux-4.9.37/tools/testing/selftests/ptp/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/ptp/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-testptp
diff -urN linux-4.9.37/tools/testing/selftests/ptrace/.gitignore linux-4.9.y/tools/testing/selftests/ptrace/.gitignore
--- linux-4.9.37/tools/testing/selftests/ptrace/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/ptrace/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-peeksiginfo
diff -urN linux-4.9.37/tools/testing/selftests/rcutorture/.gitignore linux-4.9.y/tools/testing/selftests/rcutorture/.gitignore
--- linux-4.9.37/tools/testing/selftests/rcutorture/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/rcutorture/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,6 +0,0 @@
-initrd
-linux-2.6
-b[0-9]*
-rcu-test-image
-res
-*.swp
diff -urN linux-4.9.37/tools/testing/selftests/seccomp/.gitignore linux-4.9.y/tools/testing/selftests/seccomp/.gitignore
--- linux-4.9.37/tools/testing/selftests/seccomp/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/seccomp/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-seccomp_bpf
diff -urN linux-4.9.37/tools/testing/selftests/size/.gitignore linux-4.9.y/tools/testing/selftests/size/.gitignore
--- linux-4.9.37/tools/testing/selftests/size/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/size/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-get_size
diff -urN linux-4.9.37/tools/testing/selftests/timers/.gitignore linux-4.9.y/tools/testing/selftests/timers/.gitignore
--- linux-4.9.37/tools/testing/selftests/timers/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/timers/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,19 +0,0 @@
-alarmtimer-suspend
-change_skew
-clocksource-switch
-inconsistency-check
-leap-a-day
-leapcrash
-mqueue-lat
-nanosleep
-nsleep-lat
-posix_timers
-raw_skew
-rtctest
-set-2038
-set-tai
-set-timer-lat
-skew_consistency
-threadtest
-valid-adjtimex
-adjtick
diff -urN linux-4.9.37/tools/testing/selftests/vDSO/.gitignore linux-4.9.y/tools/testing/selftests/vDSO/.gitignore
--- linux-4.9.37/tools/testing/selftests/vDSO/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/vDSO/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,2 +0,0 @@
-vdso_test
-vdso_standalone_test_x86
diff -urN linux-4.9.37/tools/testing/selftests/vm/.gitignore linux-4.9.y/tools/testing/selftests/vm/.gitignore
--- linux-4.9.37/tools/testing/selftests/vm/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/vm/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,10 +0,0 @@
-hugepage-mmap
-hugepage-shm
-map_hugetlb
-thuge-gen
-compaction_test
-mlock2-tests
-on-fault-limit
-transhuge-stress
-userfaultfd
-mlock-intersect-test
diff -urN linux-4.9.37/tools/testing/selftests/watchdog/.gitignore linux-4.9.y/tools/testing/selftests/watchdog/.gitignore
--- linux-4.9.37/tools/testing/selftests/watchdog/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/watchdog/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-watchdog-test
diff -urN linux-4.9.37/tools/testing/selftests/x86/.gitignore linux-4.9.y/tools/testing/selftests/x86/.gitignore
--- linux-4.9.37/tools/testing/selftests/x86/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/testing/selftests/x86/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,2 +0,0 @@
-*_32
-*_64
diff -urN linux-4.9.37/tools/thermal/tmon/.gitignore linux-4.9.y/tools/thermal/tmon/.gitignore
--- linux-4.9.37/tools/thermal/tmon/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/thermal/tmon/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1 +0,0 @@
-/tmon
diff -urN linux-4.9.37/tools/usb/usbip/.gitignore linux-4.9.y/tools/usb/usbip/.gitignore
--- linux-4.9.37/tools/usb/usbip/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/usb/usbip/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,28 +0,0 @@
-Makefile
-Makefile.in
-aclocal.m4
-autom4te.cache/
-config.guess
-config.h
-config.h.in
-config.log
-config.status
-config.sub
-configure
-depcomp
-install-sh
-libsrc/Makefile
-libsrc/Makefile.in
-libtool
-ltmain.sh
-missing
-src/Makefile
-src/Makefile.in
-stamp-h1
-libsrc/libusbip.la
-libsrc/libusbip_la-names.lo
-libsrc/libusbip_la-usbip_common.lo
-libsrc/libusbip_la-usbip_host_driver.lo
-libsrc/libusbip_la-vhci_driver.lo
-src/usbip
-src/usbipd
diff -urN linux-4.9.37/tools/virtio/.gitignore linux-4.9.y/tools/virtio/.gitignore
--- linux-4.9.37/tools/virtio/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/virtio/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,3 +0,0 @@
-*.d
-virtio_test
-vringh_test
diff -urN linux-4.9.37/tools/vm/.gitignore linux-4.9.y/tools/vm/.gitignore
--- linux-4.9.37/tools/vm/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/tools/vm/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,2 +0,0 @@
-slabinfo
-page-types
diff -urN linux-4.9.37/usr/.gitignore linux-4.9.y/usr/.gitignore
--- linux-4.9.37/usr/.gitignore 2017-07-12 16:42:41.000000000 +0300
+++ linux-4.9.y/usr/.gitignore 1970-01-01 03:00:00.000000000 +0300
@@ -1,10 +0,0 @@
-#
-# Generated files
-#
-gen_init_cpio
-initramfs_data.cpio
-initramfs_data.cpio.gz
-initramfs_data.cpio.bz2
-initramfs_data.cpio.lzma
-initramfs_list
-include