[board]:Init board config for JH7110

This commit is contained in:
yanhong.wang 2021-11-18 14:06:27 +08:00
parent 2555693dd8
commit be5046fcbf
20 changed files with 2287 additions and 1 deletions

View file

@ -19,6 +19,82 @@ config SOC_SIFIVE
help
This enables support for SiFive SoC platform hardware.
config SOC_STARFIVE
bool "StarFive Socs"
select SOC_SIFIVE
select OF_RESERVED_MEM
select SIFIVE_L2
select SIFIVE_L2_FLUSH
select DW_AXI_DMAC_STARFIVE
help
StarFive JH SOC platform
choice
prompt "StarFive JH SOCs"
help
choice StarFive JH SOC platform
config SOC_STARFIVE_VIC7100
bool "VIC7100"
select HW_RANDOM_STARFIVE_VIC
depends on SOC_STARFIVE
help
This enables support for StarFive VIC7100 SoC Platform Hardware.
config SOC_STARFIVE_JH7110
bool "JH7110"
select HW_RANDOM_STARFIVE_TRNG
depends on SOC_STARFIVE
help
This enables support for StarFive JH7110 SoC Platform Hardware.
endchoice
menu "StarFive JH SoC Debug Option"
depends on SOC_STARFIVE
choice
prompt "JH SOC GMAC Speed"
depends on SOC_STARFIVE
default FPGA_GMAC_SPEED_AUTO
help
choice VIC7100 GMAC speed.
(GMAC only works well on 10M/duple, for FPGA board.)
config FPGA_GMAC_SPEED10
bool "GMAC works on 10M mode"
config FPGA_GMAC_SPEED100
bool "GMAC works on 100M mode"
config FPGA_GMAC_SPEED_AUTO
bool "GMAC works on auto mode"
endchoice
config FPGA_GMAC_FLUSH_DDR
bool "VIC7100 SOC GMAC description and packet buffer flush"
depends on SOC_STARFIVE_VIC7100
depends on STMMAC_ETH
default y if SOC_STARFIVE_VIC7100
help
enable VIC7100 GMAC description and packet buffer flush
config MMC_DW_FLUSH_DDR
bool "VIC7100 SOC DW MMC buffer flush"
depends on SOC_STARFIVE_VIC7100
depends on MMC_DW
default y if SOC_STARFIVE_VIC7100
help
enable VIC7100 DW MMC description and data buffer flush
config USB_CDNS3_HOST_FLUSH_DMA
bool "Cadence USB3 host controller flush dma memery"
depends on USB
depends on USB_CDNS3
depends on SOC_STARFIVE_VIC7100
default y if SOC_STARFIVE_VIC7100
help
enable VIC7100 DW USB CDNS3 driver data buffer flush
endmenu
config SOC_VIRT
bool "QEMU Virt Machine"
select CLINT_TIMER if RISCV_M_MODE

View file

@ -2,5 +2,6 @@
subdir-y += sifive
subdir-$(CONFIG_SOC_CANAAN_K210_DTB_BUILTIN) += canaan
subdir-y += microchip
subdir-y += starfive
obj-$(CONFIG_BUILTIN_DTB) := $(addsuffix /, $(subdir-y))

View file

@ -0,0 +1,2 @@
# SPDX-License-Identifier: GPL-2.0
dtb-$(CONFIG_SOC_STARFIVE_JH7110) += starfive_jh7110.dtb

View file

@ -0,0 +1,432 @@
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/dts-v1/;
#include "starfive_jh7110_clk.dtsi"
/ {
#address-cells = <2>;
#size-cells = <2>;
compatible = "sifive,freedom-u74-arty";
model = "sifive,freedom-u74-arty";
chosen {
linux,initrd-start = <0x0 0x46100000>;
linux,initrd-end = <0x0 0x4c000000>;
stdout-path = "/soc/serial@10000000:115200";
#bootargs = "debug console=ttyS0 rootwait";
};
aliases {
spi0="/soc/spi@13010000";
gpio0="/soc/gpio@13040000";
ethernet0="/soc/gmac0@16030000";
mmc0="/soc/sdio0@16010000";
mmc1="/soc/sdio1@16020000";
};
cpus: cpus {
#address-cells = <1>;
#size-cells = <0>;
timebase-frequency = <2000000>;
compatible = "starfive,fu74-g000";
cpu@0 {
clock-frequency = <0>;
compatible = "starfive,rocket0", "riscv";
d-cache-block-size = <64>;
d-cache-sets = <64>;
d-cache-size = <32768>;
d-tlb-sets = <1>;
d-tlb-size = <40>;
device_type = "cpu";
i-cache-block-size = <64>;
i-cache-sets = <64>;
i-cache-size = <32768>;
i-tlb-sets = <1>;
i-tlb-size = <40>;
mmu-type = "riscv,sv39";
next-level-cache = <&cachectrl>;
reg = <0>;
riscv,isa = "rv64imac";
status = "disabled";
tlb-split;
cpu0intctrl: interrupt-controller {
#interrupt-cells = <1>;
compatible = "riscv,cpu-intc";
interrupt-controller;
};
};
cpu@1 {
clock-frequency = <0>;
compatible = "starfive,rocket0", "riscv";
d-cache-block-size = <64>;
d-cache-sets = <64>;
d-cache-size = <32768>;
d-tlb-sets = <1>;
d-tlb-size = <40>;
device_type = "cpu";
i-cache-block-size = <64>;
i-cache-sets = <64>;
i-cache-size = <32768>;
i-tlb-sets = <1>;
i-tlb-size = <40>;
mmu-type = "riscv,sv39";
next-level-cache = <&cachectrl>;
reg = <1>;
riscv,isa = "rv64imafdc";
status = "okay";
tlb-split;
cpu1intctrl: interrupt-controller {
#interrupt-cells = <1>;
compatible = "riscv,cpu-intc";
interrupt-controller;
};
};
cpu@2 {
clock-frequency = <0>;
compatible = "starfive,rocket0", "riscv";
d-cache-block-size = <64>;
d-cache-sets = <64>;
d-cache-size = <32768>;
d-tlb-sets = <1>;
d-tlb-size = <40>;
device_type = "cpu";
i-cache-block-size = <64>;
i-cache-sets = <64>;
i-cache-size = <32768>;
i-tlb-sets = <1>;
i-tlb-size = <40>;
mmu-type = "riscv,sv39";
next-level-cache = <&cachectrl>;
reg = <2>;
riscv,isa = "rv64imafdc";
status = "okay";
tlb-split;
cpu2intctrl: interrupt-controller {
#interrupt-cells = <1>;
compatible = "riscv,cpu-intc";
interrupt-controller;
};
};
cpu@3 {
clock-frequency = <0>;
compatible = "starfive,rocket0", "riscv";
d-cache-block-size = <64>;
d-cache-sets = <64>;
d-cache-size = <32768>;
d-tlb-sets = <1>;
d-tlb-size = <40>;
device_type = "cpu";
i-cache-block-size = <64>;
i-cache-sets = <64>;
i-cache-size = <32768>;
i-tlb-sets = <1>;
i-tlb-size = <40>;
mmu-type = "riscv,sv39";
next-level-cache = <&cachectrl>;
reg = <3>;
riscv,isa = "rv64imafdc";
status = "okay";
tlb-split;
cpu3intctrl: interrupt-controller {
#interrupt-cells = <1>;
compatible = "riscv,cpu-intc";
interrupt-controller;
};
};
cpu@4 {
clock-frequency = <0>;
compatible = "starfive,rocket0", "riscv";
d-cache-block-size = <64>;
d-cache-sets = <64>;
d-cache-size = <32768>;
d-tlb-sets = <1>;
d-tlb-size = <40>;
device_type = "cpu";
i-cache-block-size = <64>;
i-cache-sets = <64>;
i-cache-size = <32768>;
i-tlb-sets = <1>;
i-tlb-size = <40>;
mmu-type = "riscv,sv39";
next-level-cache = <&cachectrl>;
reg = <4>;
riscv,isa = "rv64imafdc";
status = "okay";
tlb-split;
cpu4intctrl: interrupt-controller {
#interrupt-cells = <1>;
compatible = "riscv,cpu-intc";
interrupt-controller;
};
};
};
memory@80000000 {
device_type = "memory";
reg = <0x0 0x40000000 0x1 0x0>;
};
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
ranges;
linux,cma {
compatible = "shared-dma-pool";
reusable;
size = <0x0 0x20000000>;
alignment = <0x0 0x1000>;
alloc-ranges = <0x0 0xa0000000 0x0 0x20000000>;
linux,cma-default;
};
};
soc: soc {
#address-cells = <2>;
#size-cells = <2>;
#clock-cells = <1>;
compatible = "starfive,freedom-u74-arty", "simple-bus", "arm,amba-bus";
ranges;
cachectrl: cache-controller@2010000 {
cache-block-size = <64>;
cache-level = <2>;
cache-sets = <2048>;
cache-size = <2097152>;
cache-unified;
compatible = "sifive,fu540-c000-ccache", "starfive,ccache0", "cache";
interrupt-parent = <&plic>;
interrupts = <1 3 4 2>;
/*next-level-cache = <&L40 &L36>;*/
reg = <0x0 0x2010000 0x0 0x4000 0x0 0x8000000 0x0 0x2000000>;
reg-names = "control", "sideband";
};
clint: clint@2000000 {
#interrupt-cells = <1>;
compatible = "riscv,clint0";
/*interrupts-extended = <&cpu0intctrl 3 &cpu0intctrl 7 &cpu1intctrl 3 &cpu1intctrl 7 >;*/
interrupts-extended = <&cpu0intctrl 3 &cpu0intctrl 7 &cpu1intctrl 3 &cpu1intctrl 7 &cpu2intctrl 3 &cpu2intctrl 7 &cpu3intctrl 3 &cpu3intctrl 7 &cpu4intctrl 3 &cpu4intctrl 7>;
reg = <0x0 0x2000000 0x0 0x10000>;
reg-names = "control";
};
plic: plic@c000000 {
#interrupt-cells = <1>;
compatible = "riscv,plic0";
interrupt-controller;
/*interrupts-extended = <&cpu0intctrl 11 &cpu0intctrl 9 &cpu1intctrl 11 &cpu1intctrl 9 >;*/
interrupts-extended = <&cpu0intctrl 11 &cpu1intctrl 11 &cpu1intctrl 9 &cpu2intctrl 11 &cpu2intctrl 9 &cpu3intctrl 11 &cpu3intctrl 9 &cpu4intctrl 11 &cpu4intctrl 9>;
reg = <0x0 0xc000000 0x0 0x4000000>;
reg-names = "control";
riscv,max-priority = <7>;
riscv,ndev = <136>;
};
uart0: serial@10000000 {
compatible = "snps,dw-apb-uart";
interrupt-parent = <&plic>;
interrupts = <32>;
reg = <0x0 0x10000000 0x0 0x10000>;
reg-io-width = <4>;
reg-shift = <2>;
clocks = <&oscclk>, <&apb0clk>;
clock-names = "baudclk", "apb_pclk";
status = "okay";
};
uart1: serial@10010000 {
compatible = "snps,dw-apb-uart";
interrupt-parent = <&plic>;
interrupts = <33>;
reg = <0x0 0x10010000 0x0 0x10000>;
reg-io-width = <4>;
reg-shift = <2>;
clocks = <&oscclk>, <&apb0clk>;
clock-names = "baudclk", "apb_pclk";
status = "okay";
};
uart2: serial@10020000 {
compatible = "snps,dw-apb-uart";
interrupt-parent = <&plic>;
interrupts = <34>;
reg = <0x0 0x10020000 0x0 0x10000>;
reg-io-width = <4>;
reg-shift = <2>;
clocks = <&oscclk>, <&apb0clk>;
clock-names = "baudclk", "apb_pclk";
status = "okay";
};
uart3: serial@12000000 {
compatible = "snps,dw-apb-uart";
interrupt-parent = <&plic>;
interrupts = <45>;
reg = <0x0 0x12000000 0x0 0x10000>;
reg-io-width = <4>;
reg-shift = <2>;
clocks = <&uartclk>, <&apb0clk>;
clock-names = "baudclk", "apb_pclk";
status = "okay";
};
uart4: serial@12010000 {
compatible = "snps,dw-apb-uart";
interrupt-parent = <&plic>;
interrupts = <46>;
reg = <0x0 0x12010000 0x0 0x10000>;
reg-io-width = <4>;
reg-shift = <2>;
clocks = <&uartclk>, <&apb0clk>;
clock-names = "baudclk", "apb_pclk";
status = "okay";
};
uart5: serial@12020000 {
compatible = "snps,dw-apb-uart";
interrupt-parent = <&plic>;
interrupts = <47>;
reg = <0x0 0x12020000 0x0 0x10000>;
reg-io-width = <4>;
reg-shift = <2>;
clocks = <&uartclk>, <&apb0clk>;
clock-names = "baudclk", "apb_pclk";
status = "okay";
};
gpio: gpio@13040000 {
compatible = "starfive,gpio7110";
interrupt-parent = <&plic>;
interrupts = <91>;
reg = <0x0 0x13040000 0x0 0x10000>;
reg-names = "control";
interrupt-controller;
#gpio-cells = <2>;
ngpios = <64>;
status = "okay";
};
/*emmc*/
sdio0:sdio0@16010000{
compatible = "snps,dw-mshc";
reg = <0x0 0x16010000 0x0 0x10000>;
interrupts = <74>;
interrupt-parent = <&plic>;
clocks = <&dwmmc_biuclk>,<&dwmmc_ciuclk>;
clock-names = "biu","ciu";
clock-frequency = <4000000>;
max-frequency = <1000000>;
fifo-depth = <32>;
card-detect-delay = <300>;
fifo-watermark-aligned;
data-addr = <0>;
bus-width = <8>;
cap-sd-highspeed;
/*broken-cd;*/
cap-sdio-irq;
cap-mmc-hw-reset;
non-removable;
enable-sdio-wakeup;
keep-power-in-suspend;
/*cap-power-off-card;*/
cap-mmc-highspeed;
/*fixed-emmc-driver-type;*/
post-power-on-delay-ms = <200>;
};
/*SD*/
sdio1:sdio1@16020000{
compatible = "snps,dw-mshc";
reg = <0x0 0x16020000 0x0 0x10000>;
interrupts = <75>;
interrupt-parent = <&plic>;
clocks = <&dwmmc_biuclk>,<&dwmmc_ciuclk>;
clock-names = "biu","ciu";
clock-frequency = <4000000>;
max-frequency = <1000000>;
fifo-depth = <32>;
card-detect-delay = <300>;
fifo-watermark-aligned;
data-addr = <0>;
bus-width = <4>;
cap-sd-highspeed;
/*broken-cd;*/
cap-sdio-irq;
cap-mmc-hw-reset;
non-removable;
enable-sdio-wakeup;
keep-power-in-suspend;
/*cap-power-off-card;*/
cap-mmc-highspeed;
/*fixed-emmc-driver-type;*/
post-power-on-delay-ms = <200>;
};
jpu: jpu@11900000 {
compatible = "cm,codaj12-jpu";
reg = <0x0 0x13090000 0x0 0x300>;
interrupt-parent = <&plic>;
interrupts = <14>;
clocks = <&jpuclk>;
clock-names = "jpege";
status = "okay";
};
vpu_dec: vpu_dec@130A0000 {
compatible = "c&m,cm511-vpu";
reg = <0 0x130A0000 0 0x10000>;
interrupt-parent = <&plic>;
interrupts = <13>;
clocks = <&vdec_rootclk>;
clock-names = "vcodec";
status = "okay";
};
vpu_enc:vpu_enc@130B0000 {
compatible = "cnm,cnm420l-vpu";
reg = <0x0 0x130B0000 0x0 0x10000>;
interrupt-parent = <&plic>;
interrupts = <15>;
clocks = <&venc_rootclk>;
clock-names = "vcodec";
reg-names = "control";
};
rst: reset-controller {
compatible = "starfive,jh7110-reset";
#reset-cells = <1>;
reset-controller;
};
/*gmac device configuration*/
stmmac_axi_setup: stmmac-axi-config {
snps,wr_osr_lmt = <0xf>;
snps,rd_osr_lmt = <0xf>;
snps,blen = <256 128 64 32 0 0 0>;
};
gmac0:gmac0@16030000{
compatible = "snps,dwc-qos-ethernet-5.10a";
reg = <0x0 0x16030000 0x0 0x10000>;
interrupt-parent = <&plic>;
interrupts = <7>;
phy-reset-gpios = <&gpio 63 0>;
max-frame-size = <9000>;
phy-mode = "rgmii-id";
snps,multicast-filter-bins = <256>;
snps,perfect-filter-entries = <128>;
rx-fifo-depth = <262144>;
tx-fifo-depth = <131072>;
clock-names = "stmmaceth","phy_ref_clk", "apb_pclk","ptp_ref";
clocks = <&gmac_bus_clk>, <&gmac_rxtx_clk>, <&gmac_bus_clk>,<&gmac_ptp_clk>;
snps,fixed-burst;
snps,no-pbl-x8;
/*snps,force_sf_dma_mode;*/
snps,force_thresh_dma_mode;
snps,axi-config = <&stmmac_axi_setup>;
snps,tso;
snps,en-tx-lpi-clockgating;
snps,en-lpi;
snps,write-requests = <2>;
snps,read-requests = <16>;
snps,burst-map = <0x7>;
snps,txpbl = <16>;
snps,rxpbl = <16>;
};
gpu:gpu@18000000{
compatible = "img-gpu";
interrupt-parent = <&plic>;
interrupts = <87>;
reg = <0x0 0x18000000 0x0 0x100000 0x0 0x130C000 0x0 0x10000>;
clocks = <&gpu_core_clk>, <&gpu_sys_clk>;
clock-names = "gpu_core_clk","gpu_sys_clk";
current-clock = <8000000>;
status = "okay";
};
};
};

View file

@ -0,0 +1,88 @@
&soc{
sound_pwmdac:snd-card_pwmdac{
compatible = "simple-audio-card";
simple-audio-card,name = "Starfive-Pwmdac-Sound-Card";
simple-audio-card,bitclock-master = <&pwmdac_dailink_master>;
simple-audio-card,frame-master = <&pwmdac_dailink_master>;
simple-audio-card,format = "left_j";
pwmdac_dailink_master:simple-audio-card,cpu {
sound-dai = <&pwmdac>;
};
simple-audio-card,codec {
sound-dai = <&pwmdac_codec>;
};
};
sound_wm8960:snd-card-wm8960{
compatible = "simple-audio-card";
simple-audio-card,name = "Starfive-wm8960-Sound-Card";
/* i2s + wm8960 */
simple-audio-card,dai-link@0 {
reg = <0>;
status = "okay";
format = "i2s";
bitclock-master = <&sndcodec0>;
frame-master = <&sndcodec0>;
widgets =
"Microphone", "Mic Jack",
"Line", "Line In",
"Line", "Line Out",
"Speaker", "Speaker",
"Headphone", "Headphone Jack";
routing =
"Headphone Jack", "HP_L",
"Headphone Jack", "HP_R",
"Speaker", "SPK_LP",
"Speaker", "SPK_LN",
"LINPUT1", "Mic Jack",
"LINPUT3", "Mic Jack",
"RINPUT1", "Mic Jack",
"RINPUT2", "Mic Jack";
cpu0 {
sound-dai = <&i2stx_4ch1>;
};
cpu1 {
sound-dai = <&i2srx_3ch>;
};
sndcodec0:codec {
sound-dai = <&wm8960>;
clocks = <&audioclk>;
clock-names = "mclk";
};
};
};
sound_spdif:snd-card-spdif{
compatible = "simple-audio-card";
simple-audio-card,name = "SF-SPDIF-Sound-Card";
simple-audio-card,bitclock-master = <&spdif_dailink_master>;
simple-audio-card,frame-master = <&spdif_dailink_master>;
simple-audio-card,format = "left_j";
spdif_dailink_master:simple-audio-card,cpu {
sound-dai = <&spdif0>;
};
simple-audio-card,codec {
sound-dai = <&spdif_transmitter>;
};
};
sound_pdm:snd-card-pdm{
compatible = "simple-audio-card";
simple-audio-card,format = "i2s";
simple-audio-card,name = "SF-PDM-Sound-Card";
simple-audio-card,bitclock-master = <&pdm_dailink_master>;
simple-audio-card,frame-master = <&pdm_dailink_master>;
status = "okay";
simple-audio-card,cpu {
sound-dai = <&i2srx_3ch>;
};
pdm_dailink_master:simple-audio-card,codec {
sound-dai = <&pdm>;
};
};
};

View file

@ -0,0 +1,149 @@
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/ {
oscclk:oscclk{
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <24000000>;
clock-output-names = "oscclk";
};
pll0clk:pll0clk{
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <1000000000>;
clock-output-names = "pll0clk";
};
pll1clk:pll1clk{
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <1066000000>;
clock-output-names = "pll1clk";
};
pll2clk:pll2clk{
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <1228800000>;
clock-output-names = "pll2clk";
};
rtcclk: rtcclk {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <4000000>;
clock-output-names = "rtcclk";
};
perh_rootclk: perh_rootclk {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <500000000>;
};
ahb0clk: ahb0clk {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <204800000>;
};
ahb1clk: ahb1clk {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <204800000>;
};
apb0clk: apb0clk {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <512000000>;
};
apb2clk: apb2clk {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <49500000>;
};
apb12clk: apb12clk {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <49500000>;
};
jpuclk: jpuclk {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <204800000>;
};
vdec_rootclk: vdec_rootclk {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <400000000>;
};
venc_rootclk: venc_rootclk {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <245760000>;
};
gmac_bus_clk: gmac_bus_clk {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <4000000>;
};
gmac_rxtx_clk: gmac_rxtx_clk {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <2500000>;
};
gmac_ptp_clk: gmac_ptp_clk {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <2500000>;
};
qspi_clk: qspi-clk@0 {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <50000000>;
};
uartclk: uartclk {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <51200000>;
};
dwmmc_biuclk: dwmmc_biuclk {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <4000000>;
};
dwmmc_ciuclk: dwmmc_ciuclk {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <4000000>;
};
stg_axiahb_clk: stg_axiahb_clk {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <204800000>;
};
stg_apbclk: stg_apbclk {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <51200000>;
};
gpu_core_clk: gpu_core_clk {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <24000000>;
};
gpu_sys_clk: gpu_sys_clk {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <24000000>;
};
pwmclk: pwmclk {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <125000000>;
};
audioclk: audioclk {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <12288000>;
};
canclk: canclk {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <24000000>;
};
};

View file

@ -0,0 +1,235 @@
CONFIG_DEFAULT_HOSTNAME="StarFive"
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
CONFIG_USELIB=y
CONFIG_NO_HZ_IDLE=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_BPF_SYSCALL=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_CGROUPS=y
CONFIG_CGROUP_SCHED=y
CONFIG_CFS_BANDWIDTH=y
CONFIG_CGROUP_BPF=y
CONFIG_NAMESPACES=y
CONFIG_USER_NS=y
CONFIG_CHECKPOINT_RESTORE=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_EXPERT=y
CONFIG_SOC_STARFIVE=y
CONFIG_SOC_STARFIVE_JH7110=y
CONFIG_FPGA_GMAC_SPEED10=y
CONFIG_SMP=y
CONFIG_HZ_100=y
# CONFIG_SECCOMP is not set
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_PAGE_REPORTING=y
CONFIG_CMA=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
CONFIG_IP_PNP_RARP=y
# CONFIG_IPV6 is not set
CONFIG_NETFILTER=y
CONFIG_NETFILTER_NETLINK_ACCT=y
CONFIG_NETFILTER_NETLINK_QUEUE=y
CONFIG_NF_CONNTRACK=y
CONFIG_NF_TABLES=y
CONFIG_NFT_CT=y
CONFIG_NFT_COMPAT=y
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
CONFIG_NETFILTER_XT_MATCH_IPCOMP=y
CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
CONFIG_NETFILTER_XT_MATCH_MAC=y
CONFIG_NETFILTER_XT_MATCH_MARK=y
CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
CONFIG_NETFILTER_XT_MATCH_SOCKET=y
CONFIG_NETFILTER_XT_MATCH_STATE=y
CONFIG_NETFILTER_XT_MATCH_STRING=y
CONFIG_NETFILTER_XT_MATCH_U32=y
CONFIG_NF_TABLES_IPV4=y
CONFIG_NFT_DUP_IPV4=y
CONFIG_NFT_FIB_IPV4=y
CONFIG_IP_NF_IPTABLES=y
CONFIG_IP_NF_FILTER=y
CONFIG_IP_NF_TARGET_REJECT=y
CONFIG_IP_NF_NAT=y
CONFIG_IP_NF_TARGET_MASQUERADE=y
CONFIG_IP_NF_TARGET_NETMAP=y
CONFIG_IP_NF_TARGET_REDIRECT=y
CONFIG_NETLINK_DIAG=y
CONFIG_BT=y
CONFIG_BT_RFCOMM=y
CONFIG_BT_RFCOMM_TTY=y
CONFIG_BT_BNEP=y
CONFIG_BT_BNEP_MC_FILTER=y
CONFIG_BT_BNEP_PROTO_FILTER=y
CONFIG_BT_HCIUART=y
CONFIG_BT_HCIUART_H4=y
CONFIG_CFG80211=y
CONFIG_NET_9P=y
CONFIG_NET_9P_VIRTIO=y
CONFIG_PCI=y
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_VIRTIO_BLK=y
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_BLK_DEV_SR=y
CONFIG_SCSI_VIRTIO=y
CONFIG_NETDEVICES=y
CONFIG_VIRTIO_NET=y
# CONFIG_NET_VENDOR_ALACRITECH is not set
# CONFIG_NET_VENDOR_AMAZON is not set
# CONFIG_NET_VENDOR_AQUANTIA is not set
# CONFIG_NET_VENDOR_ARC is not set
# CONFIG_NET_VENDOR_BROADCOM is not set
# CONFIG_NET_VENDOR_CADENCE is not set
# CONFIG_NET_VENDOR_CAVIUM is not set
# CONFIG_NET_VENDOR_CORTINA is not set
# CONFIG_NET_VENDOR_EZCHIP is not set
# CONFIG_NET_VENDOR_GOOGLE is not set
# CONFIG_NET_VENDOR_HUAWEI is not set
# CONFIG_NET_VENDOR_INTEL is not set
# CONFIG_NET_VENDOR_MARVELL is not set
# CONFIG_NET_VENDOR_MELLANOX is not set
# CONFIG_NET_VENDOR_MICREL is not set
# CONFIG_NET_VENDOR_MICROCHIP is not set
# CONFIG_NET_VENDOR_MICROSEMI is not set
# CONFIG_NET_VENDOR_NATSEMI is not set
# CONFIG_NET_VENDOR_NETRONOME is not set
# CONFIG_NET_VENDOR_NI is not set
# CONFIG_NET_VENDOR_PENSANDO is not set
# CONFIG_NET_VENDOR_QUALCOMM is not set
CONFIG_R8169=y
# CONFIG_NET_VENDOR_RENESAS is not set
# CONFIG_NET_VENDOR_ROCKER is not set
# CONFIG_NET_VENDOR_SAMSUNG is not set
# CONFIG_NET_VENDOR_SEEQ is not set
# CONFIG_NET_VENDOR_SOLARFLARE is not set
# CONFIG_NET_VENDOR_SOCIONEXT is not set
CONFIG_STMMAC_ETH=y
CONFIG_STMMAC_SELFTESTS=y
CONFIG_DWMAC_DWC_QOS_ETH=y
# CONFIG_NET_VENDOR_SYNOPSYS is not set
# CONFIG_NET_VENDOR_VIA is not set
# CONFIG_NET_VENDOR_WIZNET is not set
# CONFIG_NET_VENDOR_XILINX is not set
CONFIG_MARVELL_PHY=y
CONFIG_MICREL_PHY=y
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
CONFIG_SERIO_LIBPS2=y
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_NR_UARTS=6
CONFIG_SERIAL_8250_RUNTIME_UARTS=6
CONFIG_SERIAL_8250_EXTENDED=y
CONFIG_SERIAL_8250_MANY_PORTS=y
CONFIG_SERIAL_8250_DW=y
CONFIG_SERIAL_OF_PLATFORM=y
CONFIG_SERIAL_EARLYCON_RISCV_SBI=y
CONFIG_HVC_RISCV_SBI=y
CONFIG_TTY_PRINTK=y
CONFIG_VIRTIO_CONSOLE=y
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_VIRTIO=y
CONFIG_I2C=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_DESIGNWARE_PLATFORM=y
CONFIG_SPI=y
CONFIG_SPI_SIFIVE=y
CONFIG_SPI_SPIDEV=y
# CONFIG_PTP_1588_CLOCK is not set
CONFIG_GPIOLIB=y
CONFIG_GPIO_STARFIVE_JH7110=y
CONFIG_POWER_RESET=y
CONFIG_POWER_RESET_SYSCON=y
CONFIG_POWER_RESET_SYSCON_POWEROFF=y
# CONFIG_HWMON is not set
CONFIG_WATCHDOG=y
CONFIG_FB=y
CONFIG_BACKLIGHT_CLASS_DEVICE=y
CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
CONFIG_USB=y
CONFIG_USB_XHCI_HCD=y
CONFIG_USB_STORAGE=y
CONFIG_USB_UAS=y
CONFIG_USB_CDNS_SUPPORT=y
CONFIG_USB_CDNS3=y
CONFIG_USB_CDNS3_HOST=y
CONFIG_MMC=y
CONFIG_MMC_DEBUG=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_SDHCI_OF_DWCMSHC=y
CONFIG_MMC_SPI=y
CONFIG_MMC_DW=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_GOLDFISH=y
CONFIG_DMADEVICES=y
CONFIG_DW_AXI_DMAC=y
CONFIG_DMATEST=m
CONFIG_SYNC_FILE=y
# CONFIG_VIRTIO_MENU is not set
# CONFIG_VHOST_MENU is not set
CONFIG_GOLDFISH=y
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_RPMSG_CHAR=y
CONFIG_RPMSG_VIRTIO=y
CONFIG_PWM=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_AUTOFS4_FS=y
CONFIG_FUSE_FS=y
CONFIG_CUSE=y
CONFIG_VIRTIO_FS=y
CONFIG_MSDOS_FS=y
CONFIG_VFAT_FS=y
CONFIG_FAT_DEFAULT_UTF8=y
CONFIG_EXFAT_FS=y
CONFIG_NTFS_FS=y
CONFIG_NTFS_RW=y
CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
CONFIG_HUGETLBFS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V4=y
CONFIG_NFS_V4_1=y
CONFIG_NFS_V4_2=y
CONFIG_ROOT_NFS=y
CONFIG_CRYPTO_USER=y
# CONFIG_CRYPTO_AES is not set
CONFIG_CRYPTO_USER_API_HASH=y
CONFIG_CRYPTO_USER_API_SKCIPHER=y
CONFIG_CRYPTO_USER_API_RNG=y
CONFIG_CRYPTO_USER_API_AEAD=y
CONFIG_CRYPTO_DEV_VIRTIO=y
CONFIG_DMA_CMA=y
CONFIG_PRINTK_TIME=y
CONFIG_DEBUG_FS=y
CONFIG_SOFTLOCKUP_DETECTOR=y
CONFIG_WQ_WATCHDOG=y
CONFIG_DEBUG_TIMEKEEPING=y
CONFIG_DEBUG_RT_MUTEXES=y
CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_RWSEMS=y
CONFIG_DEBUG_ATOMIC_SLEEP=y
CONFIG_STACKTRACE=y
CONFIG_DEBUG_LIST=y
CONFIG_DEBUG_PLIST=y
CONFIG_DEBUG_SG=y
# CONFIG_RCU_TRACE is not set
CONFIG_RCU_EQS_DEBUG=y
# CONFIG_FTRACE is not set
# CONFIG_RUNTIME_TESTING_MENU is not set
CONFIG_MEMTEST=y

View file

@ -549,6 +549,13 @@ config GPIO_SIFIVE
select REGMAP_MMIO
help
Say yes here to support the GPIO device on SiFive SoCs.
config GPIO_STARFIVE_JH7110
bool "Starfive JH7110 GPIO support"
depends on SOC_STARFIVE_JH7110
depends on OF_GPIO
select GPIOLIB_IRQCHIP
help
Say yes here to support the GPIO device on Starfive VIC7110 SoCs.
config GPIO_SIOX
tristate "SIOX GPIO support"

View file

@ -133,6 +133,7 @@ obj-$(CONFIG_GPIO_SAMA5D2_PIOBU) += gpio-sama5d2-piobu.o
obj-$(CONFIG_GPIO_SCH311X) += gpio-sch311x.o
obj-$(CONFIG_GPIO_SCH) += gpio-sch.o
obj-$(CONFIG_GPIO_SIFIVE) += gpio-sifive.o
obj-$(CONFIG_GPIO_STARFIVE_JH7110) += gpio-starfive-jh7110.o
obj-$(CONFIG_GPIO_SIOX) += gpio-siox.o
obj-$(CONFIG_GPIO_SL28CPLD) += gpio-sl28cpld.o
obj-$(CONFIG_GPIO_SODAVILLE) += gpio-sodaville.o

View file

@ -0,0 +1,792 @@
/*
******************************************************************************
* @file gpio-starfive-vic7110.c
* @author StarFive Technology
* @version V1.0
* @date 08/13/2020
* @brief
******************************************************************************
* @copy
*
* THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STARFIVE SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* COPYRIGHT 2020 Shanghai StarFive Technology Co., Ltd.
*/
#include <linux/bitops.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/of_irq.h>
#include <linux/gpio/driver.h>
#include <linux/interrupt.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/init.h>
#include <linux/of.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
#include <linux/mutex.h>
#include <linux/uaccess.h>
#include <linux/spinlock.h>
#define GPIO_EN 0xe0
#define GPIO_IS_LOW 0xe4
#define GPIO_IS_HIGH 0xe8
#define GPIO_IBE_LOW 0xf4
#define GPIO_IBE_HIGH 0xf8
#define GPIO_IEV_LOW 0xfc
#define GPIO_IEV_HIGH 0x100
#define GPIO_IE_LOW 0x104
#define GPIO_IE_HIGH 0x108
#define GPIO_IC_LOW 0xec
#define GPIO_IC_HIGH 0xf0
//read only
#define GPIO_RIS_LOW 0x10c
#define GPIO_RIS_HIGH 0x110
#define GPIO_MIS_LOW 0x114
#define GPIO_MIS_HIGH 0x118
#define GPIO_DIN_LOW 0x11C
#define GPIO_DIN_HIGH 0x120
#define GPIO_DOUT_X_REG 0x0
#define GPIO_DOEN_X_REG 0x40
#define GPIO_INPUT_ENABLE_X_REG 0x124
#define MAX_GPIO 64
#define PROC_VIC "vic_gpio7110"
struct sfvic7110_gpio {
raw_spinlock_t lock;
void __iomem *base;
struct gpio_chip gc;
unsigned long enabled;
unsigned trigger[MAX_GPIO];
unsigned int irq_parent[MAX_GPIO];
struct sfvic7110_gpio *self_ptr[MAX_GPIO];
};
/* lock for procfs read access */
static DEFINE_MUTEX(read_lock);
/* lock for procfs write access */
static DEFINE_MUTEX(write_lock);
static DEFINE_SPINLOCK(sfg_lock);
static void __iomem *gpio_base = NULL;
static int sfvic7110_direction_input(struct gpio_chip *gc, unsigned offset)
{
struct sfvic7110_gpio *chip = gpiochip_get_data(gc);
unsigned long flags;
unsigned int v;
if (offset >= gc->ngpio)
return -EINVAL;
raw_spin_lock_irqsave(&chip->lock, flags);
v = readl_relaxed(chip->base + GPIO_DOEN_X_REG + (offset & ~0x3));
v &= ~(0x3f << ((offset & 0x3) * 8));
v |= 1 << ((offset & 0x3) * 8);
writel_relaxed(v, chip->base + GPIO_DOEN_X_REG + (offset & ~0x3));
raw_spin_unlock_irqrestore(&chip->lock, flags);
return 0;
}
static int sfvic7110_direction_output(struct gpio_chip *gc, unsigned offset, int value)
{
struct sfvic7110_gpio *chip = gpiochip_get_data(gc);
unsigned long flags;
unsigned int v;
if (offset >= gc->ngpio)
return -EINVAL;
raw_spin_lock_irqsave(&chip->lock, flags);
v = readl_relaxed(chip->base + GPIO_DOEN_X_REG + (offset & ~0x3));
v &= ~(0x3f << ((offset & 0x3) * 8));
writel_relaxed(v, chip->base + GPIO_DOEN_X_REG + (offset & ~0x3));
v = readl_relaxed(chip->base + GPIO_DOUT_X_REG + (offset & ~0x3));
v &= ~(0x3f << ((offset & 0x3) * 8));
v |= value << ((offset & 0x3) * 8);
writel_relaxed(v, chip->base + GPIO_DOUT_X_REG + (offset & ~0x3));
raw_spin_unlock_irqrestore(&chip->lock, flags);
return 0;
}
static int sfvic7110_get_direction(struct gpio_chip *gc, unsigned offset)
{
struct sfvic7110_gpio *chip = gpiochip_get_data(gc);
unsigned int v;
if (offset >= gc->ngpio)
return -EINVAL;
v = readl_relaxed(chip->base + GPIO_DOEN_X_REG + (offset & ~0x3));
return !!(v & (0x3f << ((offset & 0x3) * 8)));
}
static int sfvic7110_get_value(struct gpio_chip *gc, unsigned offset)
{
struct sfvic7110_gpio *chip = gpiochip_get_data(gc);
int value;
if (offset >= gc->ngpio)
return -EINVAL;
if(offset < 32){
value = readl_relaxed(chip->base + GPIO_DIN_LOW);
return (value >> offset) & 0x1;
} else {
value = readl_relaxed(chip->base + GPIO_DIN_HIGH);
return (value >> (offset - 32)) & 0x1;
}
}
static void sfvic7110_set_value(struct gpio_chip *gc, unsigned offset, int value)
{
struct sfvic7110_gpio *chip = gpiochip_get_data(gc);
unsigned long flags;
unsigned int v;
if (offset >= gc->ngpio)
return;
raw_spin_lock_irqsave(&chip->lock, flags);
v = readl_relaxed(chip->base + GPIO_DOUT_X_REG + (offset & ~0x3));
v &= ~(0x3f << ((offset & 0x3) * 8));
v |= value << ((offset & 0x3) * 8);
writel_relaxed(v, chip->base + GPIO_DOUT_X_REG + (offset & ~0x3));
raw_spin_unlock_irqrestore(&chip->lock, flags);
}
static void sfvic7110_set_ie(struct sfvic7110_gpio *chip, int offset)
{
unsigned long flags;
int old_value, new_value;
int reg_offset, index;
if(offset < 32) {
reg_offset = 0;
index = offset;
} else {
reg_offset = 4;
index = offset - 32;
}
raw_spin_lock_irqsave(&chip->lock, flags);
old_value = readl_relaxed(chip->base + GPIO_IE_LOW + reg_offset);
new_value = old_value | ( 1 << index);
writel_relaxed(new_value, chip->base + GPIO_IE_LOW + reg_offset);
raw_spin_unlock_irqrestore(&chip->lock, flags);
}
static int sfvic7110_irq_set_type(struct irq_data *d, unsigned trigger)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct sfvic7110_gpio *chip = gpiochip_get_data(gc);
int offset = irqd_to_hwirq(d);
unsigned int reg_is, reg_ibe, reg_iev;
int reg_offset, index;
if (offset < 0 || offset >= gc->ngpio)
return -EINVAL;
if(offset < 32) {
reg_offset = 0;
index = offset;
} else {
reg_offset = 4;
index = offset - 32;
}
switch(trigger) {
case IRQ_TYPE_LEVEL_HIGH:
reg_is = readl_relaxed(chip->base + GPIO_IS_LOW + reg_offset);
reg_ibe = readl_relaxed(chip->base + GPIO_IBE_LOW + reg_offset);
reg_iev = readl_relaxed(chip->base + GPIO_IEV_LOW + reg_offset);
reg_is &= (~(0x1<< index));
reg_ibe &= (~(0x1<< index));
reg_iev |= (0x1<< index);
writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset);
writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset);
writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset);
break;
case IRQ_TYPE_LEVEL_LOW:
reg_is = readl_relaxed(chip->base + GPIO_IS_LOW + reg_offset);
reg_ibe = readl_relaxed(chip->base + GPIO_IBE_LOW + reg_offset);
reg_iev = readl_relaxed(chip->base + GPIO_IEV_LOW + reg_offset);
reg_is &= (~(0x1<< index));
reg_ibe &= (~(0x1<< index));
reg_iev &= (0x1<< index);
writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset);
writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset);
writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset);
break;
case IRQ_TYPE_EDGE_BOTH:
reg_is = readl_relaxed(chip->base + GPIO_IS_LOW + reg_offset);
reg_ibe = readl_relaxed(chip->base + GPIO_IBE_LOW + reg_offset);
//reg_iev = readl_relaxed(chip->base + GPIO_IEV_LOW + reg_offset);
reg_is |= (~(0x1<< index));
reg_ibe |= (~(0x1<< index));
//reg_iev |= (0x1<< index);
writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset);
writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset);
//writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset);
break;
case IRQ_TYPE_EDGE_RISING:
reg_is = readl_relaxed(chip->base + GPIO_IS_LOW + reg_offset);
reg_ibe = readl_relaxed(chip->base + GPIO_IBE_LOW + reg_offset);
reg_iev = readl_relaxed(chip->base + GPIO_IEV_LOW + reg_offset);
reg_is |= (~(0x1<< index));
reg_ibe &= (~(0x1<< index));
reg_iev |= (0x1<< index);
writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset);
writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset);
writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset);
break;
case IRQ_TYPE_EDGE_FALLING:
reg_is = readl_relaxed(chip->base + GPIO_IS_LOW + reg_offset);
reg_ibe = readl_relaxed(chip->base + GPIO_IBE_LOW + reg_offset);
reg_iev = readl_relaxed(chip->base + GPIO_IEV_LOW + reg_offset);
reg_is |= (~(0x1<< index));
reg_ibe &= (~(0x1<< index));
reg_iev &= (0x1<< index);
writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset);
writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset);
writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset);
break;
}
chip->trigger[offset] = trigger;
sfvic7110_set_ie(chip, offset);
return 0;
}
/* chained_irq_{enter,exit} already mask the parent */
static void sfvic7110_irq_mask(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct sfvic7110_gpio *chip = gpiochip_get_data(gc);
unsigned int value;
int offset = irqd_to_hwirq(d);
int reg_offset, index;
if (offset < 0 || offset >= gc->ngpio)
return;
if(offset < 32) {
reg_offset = 0;
index = offset;
} else {
reg_offset = 4;
index = offset - 32;
}
value = readl_relaxed(chip->base + GPIO_IE_LOW + reg_offset);
value &= ~(0x1 << index);
writel_relaxed(value,chip->base + GPIO_IE_LOW + reg_offset);
}
static void sfvic7110_irq_unmask(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct sfvic7110_gpio *chip = gpiochip_get_data(gc);
unsigned int value;
int offset = irqd_to_hwirq(d);
int reg_offset, index;
if (offset < 0 || offset >= gc->ngpio)
return;
if(offset < 32) {
reg_offset = 0;
index = offset;
} else {
reg_offset = 4;
index = offset - 32;
}
value = readl_relaxed(chip->base + GPIO_IE_LOW + reg_offset);
value |= (0x1 << index);
writel_relaxed(value,chip->base + GPIO_IE_LOW + reg_offset);
}
static void sfvic7110_irq_enable(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct sfvic7110_gpio *chip = gpiochip_get_data(gc);
int offset = irqd_to_hwirq(d);
sfvic7110_irq_unmask(d);
assign_bit(offset, &chip->enabled, 1);
}
static void sfvic7110_irq_disable(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct sfvic7110_gpio *chip = gpiochip_get_data(gc);
int offset = irqd_to_hwirq(d) % MAX_GPIO; // must not fail
assign_bit(offset, &chip->enabled, 0);
sfvic7110_set_ie(chip, offset);
}
static struct irq_chip sfvic7110_irqchip = {
.name = "sfvic7110-gpio",
.irq_set_type = sfvic7110_irq_set_type,
.irq_mask = sfvic7110_irq_mask,
.irq_unmask = sfvic7110_irq_unmask,
.irq_enable = sfvic7110_irq_enable,
.irq_disable = sfvic7110_irq_disable,
};
static int starfive_gpio_child_to_parent_hwirq(struct gpio_chip *gc,
unsigned int child,
unsigned int child_type,
unsigned int *parent,
unsigned int *parent_type)
{
struct sfvic7110_gpio *chip = gpiochip_get_data(gc);
struct irq_data *d = irq_get_irq_data(chip->irq_parent[child]);
*parent_type = IRQ_TYPE_NONE;
*parent = irqd_to_hwirq(d);
return 0;
}
static irqreturn_t sfvic7110_irq_handler(int irq, void *gc)
{
int offset;
// = self_ptr - &chip->self_ptr[0];
int reg_offset, index;
unsigned int value;
unsigned long flags;
struct sfvic7110_gpio *chip = gc;
for (offset = 0; offset < 64; offset++) {
if(offset < 32) {
reg_offset = 0;
index = offset;
} else {
reg_offset = 4;
index = offset - 32;
}
raw_spin_lock_irqsave(&chip->lock, flags);
value = readl_relaxed(chip->base + GPIO_MIS_LOW + reg_offset);
if(value & BIT(index))
writel_relaxed(BIT(index), chip->base + GPIO_IC_LOW +
reg_offset);
//generic_handle_irq(irq_find_mapping(chip->gc.irq.domain,
// offset));
raw_spin_unlock_irqrestore(&chip->lock, flags);
}
return IRQ_HANDLED;
}
void sf_vic_gpio_dout_reverse(int gpio,int en)
{
unsigned int value;
int offset;
if(!gpio_base)
return;
offset = GPIO_DOUT_X_REG + (gpio & ~0x3);
spin_lock(&sfg_lock);
value = ioread32(gpio_base + offset);
value &= ~(0x3f << ((offset & 0x3) * 8));
value |= (en & 0x1) << ((offset & 0x3) * 8);
iowrite32(value, gpio_base + offset);
spin_unlock(&sfg_lock);
}
EXPORT_SYMBOL_GPL(sf_vic_gpio_dout_reverse);
void sf_vic_gpio_dout_value(int gpio,int v)
{
unsigned int value;
int offset;
if(!gpio_base)
return;
offset = GPIO_DOUT_X_REG + (gpio & ~0x3);
spin_lock(&sfg_lock);
value = ioread32(gpio_base + offset);
value &= ~(0x3f << ((offset & 0x3) * 8));
value |= (v & 0x3f) << ((offset & 0x3) * 8);
iowrite32(value,gpio_base + offset);
spin_unlock(&sfg_lock);
}
EXPORT_SYMBOL_GPL(sf_vic_gpio_dout_value);
void sf_vic_gpio_dout_low(int gpio)
{
sf_vic_gpio_dout_value(gpio, 0);
}
EXPORT_SYMBOL_GPL(sf_vic_gpio_dout_low);
void sf_vic_gpio_dout_high(int gpio)
{
sf_vic_gpio_dout_value(gpio, 1);
}
EXPORT_SYMBOL_GPL(sf_vic_gpio_dout_high);
void sf_vic_gpio_doen_reverse(int gpio,int en)
{
unsigned int value;
int offset;
if(!gpio_base)
return;
offset = GPIO_DOEN_X_REG + (gpio & ~0x3);
spin_lock(&sfg_lock);
value = ioread32(gpio_base + offset);
value &= ~(0x3f << ((offset & 0x3) * 8));
value |= (en & 0x1) << ((offset & 0x3) * 8);
iowrite32(value,gpio_base + offset);
spin_unlock(&sfg_lock);
}
EXPORT_SYMBOL_GPL(sf_vic_gpio_doen_reverse);
void sf_vic_gpio_doen_value(int gpio,int v)
{
unsigned int value;
int offset;
if(!gpio_base)
return;
offset = GPIO_DOEN_X_REG + (gpio & ~0x3);
spin_lock(&sfg_lock);
value = ioread32(gpio_base + offset);
value &= ~(0x3f << ((offset & 0x3) * 8));
value |= (v & 0x3f) << ((offset & 0x3) * 8);
iowrite32(value,gpio_base + offset);
spin_unlock(&sfg_lock);
}
EXPORT_SYMBOL_GPL(sf_vic_gpio_doen_value);
void sf_vic_gpio_doen_low(int gpio)
{
sf_vic_gpio_doen_value(gpio, 0);
}
EXPORT_SYMBOL_GPL(sf_vic_gpio_doen_low);
void sf_vic_gpio_doen_high(int gpio)
{
sf_vic_gpio_doen_value(gpio, 1);
}
EXPORT_SYMBOL_GPL(sf_vic_gpio_doen_high);
void sf_vic_gpio_manual(int offset,int v)
{
unsigned int value;
if(!gpio_base)
return ;
spin_lock(&sfg_lock);
value = ioread32(gpio_base + offset);
value &= ~(0xFF);
value |= (v&0xFF);
iowrite32(value,gpio_base + offset);
spin_unlock(&sfg_lock);
}
EXPORT_SYMBOL_GPL(sf_vic_gpio_manual);
static int str_to_num(char *str)
{
char *p = str;
int value = 0;
if((*p == '0') && (*(p + 1) == 'x' || *(p + 1) == 'X')) {
p = p + 2;
while(((*p >= '0') && (*p <= '9')) ||
((*p >= 'a') && (*p <= 'f')) ||
((*p >= 'A') && (*p <= 'F'))) {
if((*p >= '0') && (*p <= '9'))
value = value * 16 + (*p - '0');
if((*p >= 'a') && (*p <= 'f'))
value = value * 16 + 10 + (*p - 'a');
if((*p >= 'A') && (*p <= 'F'))
value = value * 16 + 10 + (*p - 'A');
p = p + 1;
}
} else {
while((*p >= '0') && (*p <= '9')) {
value = value * 10 + (*p - '0');
p = p + 1;
}
}
if(*p != '\0')
return -EFAULT;
return value;
}
static ssize_t vic_gpio_proc_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
int ret;
char message[64], cmd[8],gnum[8],v[8];
int gpionum, value;
if (mutex_lock_interruptible(&write_lock))
return -ERESTARTSYS;
ret = copy_from_user(message, buf, count);
mutex_unlock(&write_lock);
if(ret)
return -EFAULT;
sscanf(message, "%s %s %s", cmd, gnum, v);
gpionum = str_to_num(gnum);
if(gpionum < 0)
return -EFAULT;
value = str_to_num(v);
if(value < 0)
return -EFAULT;
if(!strcmp(cmd,"dout")) {
if(gpionum < 0 || gpionum > 63){
printk(KERN_ERR "vic-gpio: dout gpionum (0-63) value (0/1) invalid: gpionum = %d value = %d\n",
gpionum,value);
return -EFAULT;
}
sf_vic_gpio_dout_value(gpionum, value);
}else if(!strcmp(cmd,"doen")) {
if(gpionum < 0 || gpionum > 63){
printk(KERN_ERR "vic-gpio: doen gpionum (0-63) value (0/1) invalid: gpionum = %d value = %d\n",
gpionum,value);
return -EFAULT;
}
sf_vic_gpio_doen_value(gpionum,value);
}else if(!strcmp(cmd,"utrv")) {
if(gpionum < 0 || gpionum > 63){
printk(KERN_ERR "vic-gpio: utrv gpionum (0-63) is invalid: %d\n",gpionum);
return -EFAULT;
}
sf_vic_gpio_doen_reverse(gpionum,value);
}else if(!strcmp(cmd,"enrv")) {
if(gpionum < 0 || gpionum > 63){
printk(KERN_ERR "vic-gpio: enrv gpionum (0-63) is invalid: %d\n",gpionum);
return -EFAULT;
}
sf_vic_gpio_doen_reverse(gpionum, value);
}else if(!strcmp(cmd,"manu")) {
if(gpionum < 0x250 || gpionum > 0x378 || (gpionum & 0x3)){
printk(KERN_ERR "vic-gpio: manu offset (0x250-0x378 & mod 4) is invalid: %d\n",gpionum);
return -EFAULT;
}
sf_vic_gpio_manual(gpionum, value);
}else {
printk(KERN_ERR "vic-gpio: cmd (dout doen utrv enrv manu) invalid: %s\n",cmd);
}
return count;
}
static ssize_t vic_gpio_proc_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
int ret;
unsigned int copied;
char message[256];
sprintf(message, "Usage: echo 'cmd gpionum value' >/proc/vic_gpio\n\t"
"cmd: dout doen utrv enrv or manu\n\t"
"gpionum: gpionum or address offset for manu\n\t"
"value: 0/1 for utrv/enrv, value for dout/doen/manual\n");
copied = strlen(message);
if(*ppos >= copied)
return 0;
if (mutex_lock_interruptible(&read_lock))
return -ERESTARTSYS;
ret = copy_to_user(buf, message, copied);
if(ret) {
mutex_unlock(&read_lock);
}
*ppos += copied;
mutex_unlock(&read_lock);
return copied;
}
static const struct file_operations vic_gpio_fops = {
.owner = THIS_MODULE,
.read = vic_gpio_proc_read,
.write = vic_gpio_proc_write,
.llseek = noop_llseek,
};
static int sfvic7110_gpio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct sfvic7110_gpio *chip;
struct resource *res;
int irq, ret, ngpio;
int loop;
struct gpio_irq_chip *girq;
struct device_node *node = pdev->dev.of_node;
struct device_node *irq_parent;
struct irq_domain *parent;
chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
if (!chip) {
dev_err(dev, "out of memory\n");
return -ENOMEM;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
chip->base = devm_ioremap_resource(dev, res);
if (IS_ERR(chip->base)) {
dev_err(dev, "failed to allocate device memory\n");
return PTR_ERR(chip->base);
}
gpio_base = chip->base ;
ngpio = 64;
raw_spin_lock_init(&chip->lock);
chip->gc.direction_input = sfvic7110_direction_input;
chip->gc.direction_output = sfvic7110_direction_output;
chip->gc.get_direction = sfvic7110_get_direction;
chip->gc.get = sfvic7110_get_value;
chip->gc.set = sfvic7110_set_value;
chip->gc.base = 0;
chip->gc.ngpio = ngpio;
chip->gc.label = dev_name(dev);
chip->gc.parent = dev;
chip->gc.owner = THIS_MODULE;
irq_parent = of_irq_find_parent(node);
if (!irq_parent) {
dev_err(dev, "no IRQ parent node\n");
return -ENODEV;
}
parent = irq_find_host(irq_parent);
if (!parent) {
dev_err(dev, "no IRQ parent domain\n");
return -ENODEV;
}
girq = &chip->gc.irq;
girq->chip = &sfvic7110_irqchip;
girq->fwnode = of_node_to_fwnode(node);
girq->parent_domain = parent;
girq->child_to_parent_hwirq = starfive_gpio_child_to_parent_hwirq;
girq->handler = handle_simple_irq;
girq->default_type = IRQ_TYPE_NONE;
/* Disable all GPIO interrupts before enabling parent interrupts */
iowrite32(0, chip->base + GPIO_IE_HIGH);
iowrite32(0, chip->base + GPIO_IE_LOW);
chip->enabled = 0;
platform_set_drvdata(pdev, chip);
ret = gpiochip_add_data(&chip->gc, chip);
if (ret){
dev_err(dev, "gpiochip_add_data ret=%d!\n", ret);
return ret;
}
#if 0
/* Disable all GPIO interrupts before enabling parent interrupts */
iowrite32(0, chip->base + GPIO_IE_HIGH);
iowrite32(0, chip->base + GPIO_IE_LOW);
chip->enabled = 0;
ret = gpiochip_gpiochip_add(&chip->gc, &sfvic7110_irqchip, 0,
handle_simple_irq, IRQ_TYPE_NONE);
if (ret) {
dev_err(dev, "could not add irqchip\n");
gpiochip_remove(&chip->gc);
return ret;
}
#endif
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(dev, "Cannot get IRQ resource\n");
return irq;
}
chip->irq_parent[0] = irq;
ret = devm_request_irq(dev, irq, sfvic7110_irq_handler, IRQF_SHARED,
dev_name(dev), chip);
if (ret) {
dev_err(dev, "IRQ handler registering failed (%d)\n", ret);
return ret;
}
writel_relaxed(1, chip->base + GPIO_EN);
for(loop = 0; loop < MAX_GPIO; loop++) {
unsigned int v;
v = readl_relaxed(chip->base + GPIO_INPUT_ENABLE_X_REG + (loop << 2));
v |= 0x1;
writel_relaxed(v, chip->base + GPIO_INPUT_ENABLE_X_REG + (loop << 2));
}
if (proc_create(PROC_VIC, 0, NULL, (void *)&vic_gpio_fops) == NULL) {
return -ENOMEM;
}
dev_info(dev, "SiFive GPIO chip registered %d GPIOs\n", ngpio);
return 0;
}
static const struct of_device_id sfvic7110_gpio_match[] = {
{ .compatible = "starfive,gpio7110", },
{ },
};
static struct platform_driver sfvic7110_gpio_driver = {
.probe = sfvic7110_gpio_probe,
.driver = {
.name = "sfvic7110_gpio",
.of_match_table = of_match_ptr(sfvic7110_gpio_match),
},
};
static int __init sfvic7110_gpio_init(void)
{
return platform_driver_register(&sfvic7110_gpio_driver);
}
subsys_initcall(sfvic7110_gpio_init);
static void __exit sfvic7110_gpio_exit(void)
{
platform_driver_unregister(&sfvic7110_gpio_driver);
}
module_exit(sfvic7110_gpio_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Huan Feng <huan.feng@starfivetech.com>");
MODULE_DESCRIPTION("Starfive VIC GPIO generator driver");

View file

@ -493,6 +493,7 @@ static int dwc_eth_dwmac_remove(struct platform_device *pdev)
static const struct of_device_id dwc_eth_dwmac_match[] = {
{ .compatible = "snps,dwc-qos-ethernet-4.10", .data = &dwc_qos_data },
{ .compatible = "snps,dwc-qos-ethernet-5.10a", .data = &dwc_qos_data },
{ .compatible = "nvidia,tegra186-eqos", .data = &tegra_eqos_data },
{ }
};

View file

@ -213,6 +213,24 @@ static const struct stmmac_hwif_entry {
.mmc = &dwmac_mmc_ops,
.setup = dwmac4_setup,
.quirks = NULL,
}, {
.gmac = false,
.gmac4 = true,
.xgmac = false,
.min_id = DWMAC_CORE_5_20,
.regs = {
.ptp_off = PTP_GMAC4_OFFSET,
.mmc_off = MMC_GMAC4_OFFSET,
},
.desc = &dwmac4_desc_ops,
.dma = &dwmac410_dma_ops,
.mac = &dwmac510_ops,
.hwtimestamp = &stmmac_ptp,
.mode = &dwmac4_ring_mode_ops,
.tc = &dwmac510_tc_ops,
.mmc = &dwmac_mmc_ops,
.setup = dwmac4_setup,
.quirks = NULL,
}, {
.gmac = false,
.gmac4 = false,

View file

@ -551,9 +551,20 @@ static int m88e1121_config_aneg_rgmii_delays(struct phy_device *phydev)
else
mscr = 0;
#if defined(CONFIG_FPGA_GMAC_SPEED10)
return phy_modify_paged(phydev, MII_MARVELL_MSCR_PAGE,
MII_88E1121_PHY_MSCR_REG,
MII_88E1121_PHY_MSCR_DELAY_MASK|BIT(6)|BIT(13),
mscr);
#elif defined(CONFIG_FPGA_GMAC_SPEED100)
return phy_modify_paged(phydev, MII_MARVELL_MSCR_PAGE,
MII_88E1121_PHY_MSCR_REG,
MII_88E1121_PHY_MSCR_DELAY_MASK|BIT(13), mscr);
#else
return phy_modify_paged(phydev, MII_MARVELL_MSCR_PAGE,
MII_88E1121_PHY_MSCR_REG,
MII_88E1121_PHY_MSCR_DELAY_MASK, mscr);
#endif
}
static int m88e1121_config_aneg(struct phy_device *phydev)

View file

@ -894,6 +894,48 @@ static int ksz9031_config_init(struct phy_device *phydev)
goto err_force_master;
}
}
#if defined(CONFIG_FPGA_GMAC_SPEED10)
/* set to 10M
bit [6, 13]
[1,1] = Reserved
[1,0] = 1000 Mbps
[0,1] = 100 Mbps
[0,0] = 10 Mbps
*/
result = phy_read(phydev, MII_BMCR);
result &=~(BIT(6)|BIT(13));
result = phy_write(phydev, MII_BMCR, result);
if (result < 0)
goto err_force_master;
/* remove Auto-Negotiation advertisements for 1000 Mbps full-/half-duplex*/
result = phy_read(phydev, MII_CTRL1000);
result &=~(BIT(8)|BIT(9));
result = phy_write(phydev, MII_CTRL1000, result);
if (result < 0)
goto err_force_master;
#elif defined(CONFIG_FPGA_GMAC_SPEED100)
/* set to 100M
bit [6, 13]
[1,1] = Reserved
[1,0] = 1000 Mbps
[0,1] = 100 Mbps
[0,0] = 10 Mbps
*/
result = phy_read(phydev, MII_BMCR);
result &=~BIT(6);
result |=BIT(13);
result = phy_write(phydev, MII_BMCR, result);
if (result < 0)
goto err_force_master;
/* remove Auto-Negotiation advertisements for 1000 Mbps full-/half-duplex*/
result = phy_read(phydev, MII_CTRL1000);
result &=~(BIT(8)|BIT(9));
result = phy_write(phydev, MII_CTRL1000, result);
if (result < 0)
goto err_force_master;
#endif
return ksz9031_center_flp_timing(phydev);

View file

@ -589,13 +589,24 @@ struct phy_device *phy_device_create(struct mii_bus *bus, int addr, u32 phy_id,
mdiodev->device_free = phy_mdio_device_free;
mdiodev->device_remove = phy_mdio_device_remove;
#if defined(CONFIG_FPGA_GMAC_SPEED10)
dev->speed = SPEED_10;
dev->duplex = DUPLEX_FULL;
dev->interface = PHY_INTERFACE_MODE_RGMII;
#elif defined(CONFIG_FPGA_GMAC_SPEED100)
dev->speed = SPEED_100;
dev->duplex = DUPLEX_FULL;
dev->interface = PHY_INTERFACE_MODE_RGMII;
#else
dev->speed = SPEED_UNKNOWN;
dev->duplex = DUPLEX_UNKNOWN;
dev->interface = PHY_INTERFACE_MODE_GMII;
#endif
dev->pause = 0;
dev->asym_pause = 0;
dev->link = 0;
dev->port = PORT_TP;
dev->interface = PHY_INTERFACE_MODE_GMII;
// dev->interface = PHY_INTERFACE_MODE_GMII;
dev->autoneg = AUTONEG_ENABLE;
@ -1910,6 +1921,13 @@ static int genphy_config_advert(struct phy_device *phydev)
if (err > 0)
changed = 1;
#if defined(CONFIG_FPGA_GMAC_SPEED10)
err = phy_write(phydev, MII_ADVERTISE, 0x61);
//Auto-Negotiation Advertisement 10M
#elif defined(CONFIG_FPGA_GMAC_SPEED100)
err = phy_write(phydev, MII_ADVERTISE, 0x181);
//Auto-Negotiation Advertisement 100M
#endif
bmsr = phy_read(phydev, MII_BMSR);
if (bmsr < 0)
return bmsr;
@ -1923,9 +1941,19 @@ static int genphy_config_advert(struct phy_device *phydev)
adv = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising);
#if defined(CONFIG_FPGA_GMAC_SPEED10)
err = phy_modify_changed(phydev, MII_CTRL1000,
ADVERTISE_1000FULL | ADVERTISE_1000HALF,
0);
#elif defined(CONFIG_FPGA_GMAC_SPEED100)
err = phy_modify_changed(phydev, MII_CTRL1000,
ADVERTISE_1000FULL | ADVERTISE_1000HALF,
0);
#else
err = phy_modify_changed(phydev, MII_CTRL1000,
ADVERTISE_1000FULL | ADVERTISE_1000HALF,
adv);
#endif
if (err < 0)
return err;
if (err > 0)

View file

@ -7,4 +7,20 @@ config SIFIVE_L2
help
Support for the L2 cache controller on SiFive platforms.
config SIFIVE_L2_FLUSH
bool "Support Level 2 Cache Controller Flush operation of SiFive Soc"
if SIFIVE_L2_FLUSH
config SIFIVE_L2_FLUSH_START
hex "Level 2 Cache Flush operation start"
default 0x80000000
default 0x40000000 if SOC_STARFIVE_JH7110
config SIFIVE_L2_FLUSH_SIZE
hex "Level 2 Cache Flush operation size"
default 0x800000000
default 0x400000000 if SOC_STARFIVE_JH7110
endif # SIFIVE_L2_FLUSH
endif

View file

@ -29,12 +29,15 @@
#define SIFIVE_L2_DATECCFAIL_HIGH 0x164
#define SIFIVE_L2_DATECCFAIL_COUNT 0x168
#define SIFIVE_L2_FLUSH64 0x200
#define SIFIVE_L2_CONFIG 0x00
#define SIFIVE_L2_WAYENABLE 0x08
#define SIFIVE_L2_ECCINJECTERR 0x40
#define SIFIVE_L2_MAX_ECCINTR 4
#define SIFIVE_L2_FLUSH64_LINE_LEN 64
static void __iomem *l2_base;
static int g_irq[SIFIVE_L2_MAX_ECCINTR];
static struct riscv_cacheinfo_ops l2_cache_ops;
@ -116,6 +119,41 @@ int unregister_sifive_l2_error_notifier(struct notifier_block *nb)
}
EXPORT_SYMBOL_GPL(unregister_sifive_l2_error_notifier);
#ifdef CONFIG_SIFIVE_L2_FLUSH
void sifive_l2_flush64_range(unsigned long start, unsigned long len)
{
unsigned long line;
if(!l2_base) {
pr_warn("L2CACHE: base addr invalid, skipping flush\n");
return;
}
/* TODO: if (len == 0), skipping flush or going on? */
if(!len) {
pr_debug("L2CACHE: flush64 range @ 0x%lx(len:0)\n", start);
return;
}
/* make sure the address is in the range */
if(start < CONFIG_SIFIVE_L2_FLUSH_START ||
(start + len) > (CONFIG_SIFIVE_L2_FLUSH_START +
CONFIG_SIFIVE_L2_FLUSH_SIZE)) {
pr_warn("L2CACHE: flush64 out of range: %lx(%lx), skip flush\n",
start, len);
return;
}
mb(); /* sync */
for (line = start; line < start + len;
line += SIFIVE_L2_FLUSH64_LINE_LEN) {
writeq(line, l2_base + SIFIVE_L2_FLUSH64);
mb();
}
}
EXPORT_SYMBOL_GPL(sifive_l2_flush64_range);
#endif
static int l2_largest_wayenabled(void)
{
return readl(l2_base + SIFIVE_L2_WAYENABLE) & 0xFF;

View file

@ -13,4 +13,8 @@ extern int unregister_sifive_l2_error_notifier(struct notifier_block *nb);
#define SIFIVE_L2_ERR_TYPE_CE 0
#define SIFIVE_L2_ERR_TYPE_UE 1
#ifdef CONFIG_SIFIVE_L2_FLUSH
void sifive_l2_flush64_range(unsigned long start, unsigned long len);
#endif
#endif /* __SOC_SIFIVE_L2_CACHE_H */

View file

@ -0,0 +1,17 @@
#ifndef STARFIVE_VIC7100_H
#define STARFIVE_VIC7100_H
#include <asm/io.h>
#include <soc/sifive/sifive_l2_cache.h>
/*cache.c*/
#define starfive_flush_dcache(start, len) \
sifive_l2_flush64_range(start, len)
void *dw_phys_to_virt(dma_addr_t phys);
dma_addr_t dw_virt_to_phys(void *vaddr);
int async_memcpy_single(dma_addr_t dst_dma, dma_addr_t src_dma, size_t size);
int async_memcpy_single_virt(void *dst, void *src, size_t size);
int async_memcpy_test(size_t size);
#endif /*STARFIVE_VIC7100_H*/

328
usr/gen_initramfs_list.sh Executable file
View file

@ -0,0 +1,328 @@
#!/bin/sh
# Copyright (C) Martin Schlemmer <azarah@nosferatu.za.org>
# Copyright (C) 2006 Sam Ravnborg <sam@ravnborg.org>
#
# Released under the terms of the GNU GPL
#
# Generate a cpio packed initramfs. It uses gen_init_cpio to generate
# the cpio archive, and then compresses it.
# The script may also be used to generate the inputfile used for gen_init_cpio
# This script assumes that gen_init_cpio is located in usr/ directory
# error out on errors
set -e
usage() {
cat << EOF
Usage:
$0 [-o <file>] [-u <uid>] [-g <gid>] {-d | <cpio_source>} ...
-o <file> Create compressed initramfs file named <file> using
gen_init_cpio and compressor depending on the extension
-u <uid> User ID to map to user ID 0 (root).
<uid> is only meaningful if <cpio_source> is a
directory. "squash" forces all files to uid 0.
-g <gid> Group ID to map to group ID 0 (root).
<gid> is only meaningful if <cpio_source> is a
directory. "squash" forces all files to gid 0.
<cpio_source> File list or directory for cpio archive.
If <cpio_source> is a .cpio file it will be used
as direct input to initramfs.
-d Output the default cpio list.
All options except -o and -l may be repeated and are interpreted
sequentially and immediately. -u and -g states are preserved across
<cpio_source> options so an explicit "-u 0 -g 0" is required
to reset the root/group mapping.
EOF
}
# awk style field access
# $1 - field number; rest is argument string
field() {
shift $1 ; echo $1
}
list_default_initramfs() {
# echo usr/kinit/kinit
:
}
default_initramfs() {
cat <<-EOF >> ${output}
# This is a very simple, default initramfs
dir /dev 0755 0 0
nod /dev/console 0600 0 0 c 5 1
dir /root 0700 0 0
# file /kinit usr/kinit/kinit 0755 0 0
# slink /init kinit 0755 0 0
EOF
}
filetype() {
local argv1="$1"
# symlink test must come before file test
if [ -L "${argv1}" ]; then
echo "slink"
elif [ -f "${argv1}" ]; then
echo "file"
elif [ -d "${argv1}" ]; then
echo "dir"
elif [ -b "${argv1}" -o -c "${argv1}" ]; then
echo "nod"
elif [ -p "${argv1}" ]; then
echo "pipe"
elif [ -S "${argv1}" ]; then
echo "sock"
else
echo "invalid"
fi
return 0
}
list_print_mtime() {
:
}
print_mtime() {
local my_mtime="0"
if [ -e "$1" ]; then
my_mtime=$(find "$1" -printf "%T@\n" | sort -r | head -n 1)
fi
echo "# Last modified: ${my_mtime}" >> ${output}
echo "" >> ${output}
}
list_parse() {
if [ -L "$1" ]; then
return
fi
echo "$1" | sed 's/:/\\:/g; s/$/ \\/'
}
# for each file print a line in following format
# <filetype> <name> <path to file> <octal mode> <uid> <gid>
# for links, devices etc the format differs. See gen_init_cpio for details
parse() {
local location="$1"
local name="/${location#${srcdir}}"
# change '//' into '/'
name=$(echo "$name" | sed -e 's://*:/:g')
local mode="$2"
local uid="$3"
local gid="$4"
local ftype=$(filetype "${location}")
# remap uid/gid to 0 if necessary
[ "$root_uid" = "squash" ] && uid=0 || [ "$uid" -eq "$root_uid" ] && uid=0
[ "$root_gid" = "squash" ] && gid=0 || [ "$gid" -eq "$root_gid" ] && gid=0
local str="${mode} ${uid} ${gid}"
[ "${ftype}" = "invalid" ] && return 0
[ "${location}" = "${srcdir}" ] && return 0
case "${ftype}" in
"file")
str="${ftype} ${name} ${location} ${str}"
;;
"nod")
local dev=`LC_ALL=C ls -l "${location}"`
local maj=`field 5 ${dev}`
local min=`field 6 ${dev}`
maj=${maj%,}
[ -b "${location}" ] && dev="b" || dev="c"
str="${ftype} ${name} ${str} ${dev} ${maj} ${min}"
;;
"slink")
local target=`readlink "${location}"`
str="${ftype} ${name} ${target} ${str}"
;;
*)
str="${ftype} ${name} ${str}"
;;
esac
echo "${str}" >> ${output}
return 0
}
unknown_option() {
printf "ERROR: unknown option \"$arg\"\n" >&2
printf "If the filename validly begins with '-', " >&2
printf "then it must be prefixed\n" >&2
printf "by './' so that it won't be interpreted as an option." >&2
printf "\n" >&2
usage >&2
exit 1
}
list_header() {
:
}
header() {
printf "\n#####################\n# $1\n" >> ${output}
}
# process one directory (incl sub-directories)
dir_filelist() {
${dep_list}header "$1"
srcdir=$(echo "$1" | sed -e 's://*:/:g')
dirlist=$(find "${srcdir}" -printf "%p %m %U %G\n" | LANG=C sort)
# If $dirlist is only one line, then the directory is empty
if [ "$(echo "${dirlist}" | wc -l)" -gt 1 ]; then
${dep_list}print_mtime "$1"
echo "${dirlist}" | \
while read x; do
${dep_list}parse ${x}
done
fi
}
# if only one file is specified and it is .cpio file then use it direct as fs
# if a directory is specified then add all files in given direcotry to fs
# if a regular file is specified assume it is in gen_initramfs format
input_file() {
source="$1"
if [ -f "$1" ]; then
${dep_list}header "$1"
is_cpio="$(echo "$1" | sed 's/^.*\.cpio\(\..*\)\{0,1\}/cpio/')"
if [ $2 -eq 0 -a ${is_cpio} = "cpio" ]; then
cpio_file=$1
echo "$1" | grep -q '^.*\.cpio\..*' && is_cpio_compressed="compressed"
[ ! -z ${dep_list} ] && echo "$1"
return 0
fi
if [ -z ${dep_list} ]; then
print_mtime "$1" >> ${output}
cat "$1" >> ${output}
else
echo "$1 \\"
cat "$1" | while read type dir file perm ; do
if [ "$type" = "file" ]; then
echo "$file \\";
fi
done
fi
elif [ -d "$1" ]; then
dir_filelist "$1"
else
echo " ${prog}: Cannot open '$1'" >&2
exit 1
fi
}
prog=$0
root_uid=0
root_gid=0
dep_list=
cpio_file=
cpio_list=
output="/dev/stdout"
output_file=""
is_cpio_compressed=
compr="gzip -n -9 -f"
arg="$1"
case "$arg" in
"-l") # files included in initramfs - used by kbuild
dep_list="list_"
echo "deps_initramfs := $0 \\"
shift
;;
"-o") # generate compressed cpio image named $1
shift
output_file="$1"
cpio_list="$(mktemp ${TMPDIR:-/tmp}/cpiolist.XXXXXX)"
output=${cpio_list}
echo "$output_file" | grep -q "\.gz$" \
&& [ -x "`which gzip 2> /dev/null`" ] \
&& compr="gzip -n -9 -f"
echo "$output_file" | grep -q "\.bz2$" \
&& [ -x "`which bzip2 2> /dev/null`" ] \
&& compr="bzip2 -9 -f"
echo "$output_file" | grep -q "\.lzma$" \
&& [ -x "`which lzma 2> /dev/null`" ] \
&& compr="lzma -9 -f"
echo "$output_file" | grep -q "\.xz$" \
&& [ -x "`which xz 2> /dev/null`" ] \
&& compr="xz --check=crc32 --lzma2=dict=1MiB"
echo "$output_file" | grep -q "\.lzo$" \
&& [ -x "`which lzop 2> /dev/null`" ] \
&& compr="lzop -9 -f"
echo "$output_file" | grep -q "\.lz4$" \
&& [ -x "`which lz4 2> /dev/null`" ] \
&& compr="lz4 -l -9 -f"
echo "$output_file" | grep -q "\.cpio$" && compr="cat"
shift
;;
esac
while [ $# -gt 0 ]; do
arg="$1"
shift
case "$arg" in
"-u") # map $1 to uid=0 (root)
root_uid="$1"
[ "$root_uid" = "-1" ] && root_uid=$(id -u || echo 0)
shift
;;
"-g") # map $1 to gid=0 (root)
root_gid="$1"
[ "$root_gid" = "-1" ] && root_gid=$(id -g || echo 0)
shift
;;
"-d") # display default initramfs list
default_list="$arg"
${dep_list}default_initramfs
;;
"-h")
usage
exit 0
;;
*)
case "$arg" in
"-"*)
unknown_option
;;
*) # input file/dir - process it
input_file "$arg" "$#"
;;
esac
;;
esac
done
# If output_file is set we will generate cpio archive and compress it
# we are careful to delete tmp files
if [ ! -z ${output_file} ]; then
if [ -z ${cpio_file} ]; then
timestamp=
if test -n "$KBUILD_BUILD_TIMESTAMP"; then
timestamp="$(date -d"$KBUILD_BUILD_TIMESTAMP" +%s || :)"
if test -n "$timestamp"; then
timestamp="-t $timestamp"
fi
fi
cpio_tfile="$(mktemp ${TMPDIR:-/tmp}/cpiofile.XXXXXX)"
usr/gen_init_cpio $timestamp ${cpio_list} > ${cpio_tfile}
else
cpio_tfile=${cpio_file}
fi
rm ${cpio_list}
if [ "${is_cpio_compressed}" = "compressed" ]; then
cat ${cpio_tfile} > ${output_file}
else
(cat ${cpio_tfile} | ${compr} - > ${output_file}) \
|| (rm -f ${output_file} ; false)
fi
[ -z ${cpio_file} ] && rm ${cpio_tfile}
fi
exit 0