mirror of https://github.com/OpenIPC/firmware.git
Goke kernel update (#398)
parent
c623d17f02
commit
0dd034a014
|
@ -190,6 +190,10 @@ jobs:
|
|||
- platform: gk7205v300
|
||||
release: fpv
|
||||
|
||||
# Original SDK test
|
||||
- platform: gk7205v200
|
||||
release: original
|
||||
|
||||
# MVP
|
||||
- platform: t10
|
||||
release: lite
|
||||
|
|
|
@ -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";
|
||||
};
|
||||
|
|
@ -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";
|
||||
};
|
||||
};
|
||||
};
|
|
@ -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";
|
||||
};
|
||||
|
|
@ -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";
|
||||
};
|
||||
};
|
||||
};
|
|
@ -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";
|
||||
};
|
||||
|
|
@ -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";
|
||||
};
|
||||
};
|
||||
};
|
|
@ -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";
|
||||
};
|
||||
|
|
@ -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";
|
||||
};
|
||||
};
|
||||
};
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -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
|
|
@ -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"
|
|
@ -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?
|
|
@ -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)
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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"
|
|
@ -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
|
|
@ -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)
|
|
@ -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
|
|
@ -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
|
|
@ -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__ */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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);
|
|
@ -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();
|
|
@ -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)
|
||||
{
|
|
@ -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 = .;
|
||||
- }
|
||||
-}
|
|
@ -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 = .;
|
||||
- }
|
||||
-}
|
|
@ -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
|
|
@ -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/
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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.
|
||||
+
|
|
@ -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
|
|
@ -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);
|
||||
+
|
|
@ -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);
|
||||
+
|
|
@ -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);
|
||||
+
|
|
@ -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);
|
||||
+
|
|
@ -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
|
|
@ -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 */
|
|
@ -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);
|
|
@ -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 */
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
|
@ -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"
|
|
@ -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/
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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);
|
||||
|
|
@ -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);
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
|
@ -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
|
||||
+
|
|
@ -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 */
|
|
@ -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);
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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
|
||||
+
|
|
@ -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 */
|
|
@ -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
|
|
@ -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();
|
||||
}
|
|
@ -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
|
|
@ -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/
|
|
@ -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.
|
|
@ -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
|
|
@ -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);
|
|
@ -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) {
|
|
@ -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
|
|
@ -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
|
|
@ -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");
|
|
@ -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);
|
|
@ -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)
|
|
@ -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;
|
|
@ -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;
|
|
@ -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)
|
|
@ -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
|
|
@ -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
|
|
@ -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");
|
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue