Goke kernel update (#398)

pull/401/head
Dmitry Ilyin 2022-08-22 22:12:02 +03:00 committed by GitHub
parent c623d17f02
commit 0dd034a014
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
379 changed files with 98593 additions and 100620 deletions

View File

@ -190,6 +190,10 @@ jobs:
- platform: gk7205v300
release: fpv
# Original SDK test
- platform: gk7205v200
release: original
# MVP
- platform: t10
release: lite

View File

@ -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";
};

View File

@ -0,0 +1,626 @@
/*
* 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,sp805", "arm,primecell5";
/* timer2 & timer3 */
interrupts = <0 6 4>;
reg = <0x12001000 0x1000>;
clocks = <&clk_3m>, <&clk_3m>, <&clk_apb>;
clock-names = "timer10", "timer11", "apb_pclk";
status = "okay";
};
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",
"goke,femac-v2";
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";
};
};
};

View File

@ -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 = "okay";
};
&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 = "disabled";
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";
};

View File

@ -0,0 +1,626 @@
/*
* 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,sp805", "arm,primecell5";
/* timer2 & timer3 */
interrupts = <0 6 4>;
reg = <0x12001000 0x1000>;
clocks = <&clk_3m>, <&clk_3m>, <&clk_apb>;
clock-names = "timer10", "timer11", "apb_pclk";
status = "okay";
};
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",
"goke,femac-v2";
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";
};
};
};

View File

@ -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 = "okay";
};
&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";
};

View File

@ -0,0 +1,645 @@
/*
* 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,sp805", "arm,primecell5";
/* timer2 & timer3 */
interrupts = <0 6 4>;
reg = <0x12001000 0x1000>;
clocks = <&clk_3m>, <&clk_3m>, <&clk_apb>;
clock-names = "timer10", "timer11", "apb_pclk";
status = "okay";
};
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",
"goke,femac-v2";
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";
};
};
};

View File

@ -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";
};

View File

@ -0,0 +1,645 @@
/*
* 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",
"goke,femac-v2";
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";
};
};
};

View File

@ -0,0 +1,61 @@
--- 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

View File

@ -0,0 +1,20 @@
--- 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"

View File

@ -0,0 +1,21 @@
--- 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?

View File

@ -0,0 +1,45 @@
--- 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)

View File

@ -0,0 +1,24 @@
--- 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

View File

@ -0,0 +1,17 @@
--- 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

View File

@ -0,0 +1,11 @@
--- 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"

View File

@ -0,0 +1,74 @@
--- 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

View File

@ -0,0 +1,6 @@
--- 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)

View File

@ -0,0 +1,11 @@
--- 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

View File

@ -0,0 +1,9 @@
--- 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

View File

@ -0,0 +1,9 @@
--- 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__ */

View File

@ -0,0 +1,15 @@
--- 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 */

View File

@ -0,0 +1,55 @@
--- 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 */

View File

@ -0,0 +1,55 @@
--- 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 */

View File

@ -0,0 +1,55 @@
--- 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 */

View File

@ -0,0 +1,55 @@
--- 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 */

View File

@ -0,0 +1,43 @@
--- 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);

View File

@ -0,0 +1,15 @@
--- 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();

View File

@ -0,0 +1,11 @@
--- 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)
{

View File

@ -0,0 +1,13 @@
--- 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 = .;
- }
-}

View File

@ -0,0 +1,11 @@
--- 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 = .;
- }
-}

View File

@ -0,0 +1,9 @@
--- 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

View File

@ -0,0 +1,15 @@
--- 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/

View File

@ -0,0 +1,18 @@
--- 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

View File

@ -0,0 +1,9 @@
--- 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

View File

@ -0,0 +1,8 @@
--- 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/
\ No newline at end of file

View File

@ -0,0 +1,42 @@
--- 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
+ select RESET_CONTROLLER
+ help
+ Build reset controller driver for Goke device chipsets.
+

View File

@ -0,0 +1,13 @@
--- 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

View File

@ -0,0 +1,236 @@
--- 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);
+

View File

@ -0,0 +1,238 @@
--- 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);
+

View File

@ -0,0 +1,236 @@
--- 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);
+

View File

@ -0,0 +1,236 @@
--- 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);
+

View File

@ -0,0 +1,192 @@
--- 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);
\ No newline at end of file

View File

@ -0,0 +1,93 @@
--- 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 */

View File

@ -0,0 +1,116 @@
--- 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);

View File

@ -0,0 +1,18 @@
--- 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 */

View File

@ -0,0 +1,17 @@
--- 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

View File

@ -0,0 +1,14 @@
--- 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);
}

View File

@ -0,0 +1,13 @@
--- 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;

View File

@ -0,0 +1,22 @@
--- 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"

View File

@ -0,0 +1,10 @@
--- 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/

View File

@ -0,0 +1,35 @@
--- 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 */

View File

@ -0,0 +1,100 @@
--- 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 */

View File

@ -0,0 +1,35 @@
--- 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);

View File

@ -0,0 +1,219 @@
--- 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);

View File

@ -0,0 +1,34 @@
--- 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;
}

View File

@ -0,0 +1,46 @@
--- 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 */

View File

@ -0,0 +1,741 @@
--- 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
+

View File

@ -0,0 +1,366 @@
--- 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 */

View File

@ -0,0 +1,143 @@
--- 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);

View File

@ -0,0 +1,135 @@
--- 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

View File

@ -0,0 +1,11 @@
--- 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

View File

@ -0,0 +1,5 @@
--- 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

View File

@ -0,0 +1,35 @@
--- 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 */

View File

@ -0,0 +1,100 @@
--- 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 */

View File

@ -0,0 +1,280 @@
--- 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 */

View File

@ -0,0 +1,63 @@
--- 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 */

View File

@ -0,0 +1,743 @@
--- 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
+

View File

@ -0,0 +1,366 @@
--- 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 */

View File

@ -0,0 +1,262 @@
--- 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

View File

@ -0,0 +1,69 @@
--- 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();
}

View File

@ -0,0 +1,7 @@
--- 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

View File

@ -0,0 +1,4 @@
--- 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/

View File

@ -0,0 +1,19 @@
--- 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.

View File

@ -0,0 +1,5 @@
--- 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

View File

@ -0,0 +1,181 @@
--- 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);

View File

@ -0,0 +1,76 @@
--- 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) {

View File

@ -0,0 +1,40 @@
--- 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

View File

@ -0,0 +1,10 @@
--- 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

View File

@ -0,0 +1,970 @@
--- 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");

View File

@ -0,0 +1,24 @@
--- 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);

View File

@ -0,0 +1,39 @@
--- 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)

View File

@ -0,0 +1,36 @@
--- 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;

View File

@ -0,0 +1,20 @@
--- 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;

View File

@ -0,0 +1,10 @@
--- 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)

View File

@ -0,0 +1,19 @@
--- 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

View File

@ -0,0 +1,10 @@
--- 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

View File

@ -0,0 +1,124 @@
--- 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");

Some files were not shown because too many files have changed in this diff Show More