diff options
author | yanhong.wang <yanhong.wang@starfivetech.com> | 2021-11-18 09:06:27 +0300 |
---|---|---|
committer | yanhong.wang <yanhong.wang@starfivetech.com> | 2021-11-18 09:06:27 +0300 |
commit | be5046fcbfb555a5cdb0a81b4a4f9bcf22196b0c (patch) | |
tree | 3f59f31e8ee017d5d890a0f0693c3d4a08fff08d | |
parent | 2555693dd85c7a726eed570736bf6e1c4c7116ed (diff) | |
download | linux-be5046fcbfb555a5cdb0a81b4a4f9bcf22196b0c.tar.xz |
[board]:Init board config for JH7110
-rw-r--r-- | arch/riscv/Kconfig.socs | 76 | ||||
-rw-r--r-- | arch/riscv/boot/dts/Makefile | 1 | ||||
-rw-r--r-- | arch/riscv/boot/dts/starfive/Makefile | 2 | ||||
-rw-r--r-- | arch/riscv/boot/dts/starfive/starfive_jh7110.dts | 432 | ||||
-rw-r--r-- | arch/riscv/boot/dts/starfive/starfive_jh7110_audio.dtsi | 88 | ||||
-rw-r--r-- | arch/riscv/boot/dts/starfive/starfive_jh7110_clk.dtsi | 149 | ||||
-rw-r--r-- | arch/riscv/configs/starfive_jh7110_defconfig | 235 | ||||
-rw-r--r-- | drivers/gpio/Kconfig | 7 | ||||
-rw-r--r-- | drivers/gpio/Makefile | 1 | ||||
-rw-r--r-- | drivers/gpio/gpio-starfive-jh7110.c | 792 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/hwif.c | 18 | ||||
-rw-r--r-- | drivers/net/phy/marvell.c | 11 | ||||
-rw-r--r-- | drivers/net/phy/micrel.c | 42 | ||||
-rw-r--r-- | drivers/net/phy/phy_device.c | 30 | ||||
-rw-r--r-- | drivers/soc/sifive/Kconfig | 16 | ||||
-rw-r--r-- | drivers/soc/sifive/sifive_l2_cache.c | 38 | ||||
-rw-r--r-- | include/soc/sifive/sifive_l2_cache.h | 4 | ||||
-rw-r--r-- | include/soc/starfive/vic7100.h | 17 | ||||
-rwxr-xr-x | usr/gen_initramfs_list.sh | 328 |
20 files changed, 2287 insertions, 1 deletions
diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs index 30676ebb16eb..31428dcf9fbf 100644 --- a/arch/riscv/Kconfig.socs +++ b/arch/riscv/Kconfig.socs @@ -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 diff --git a/arch/riscv/boot/dts/Makefile b/arch/riscv/boot/dts/Makefile index fe996b88319e..5c9fcae54ba4 100644 --- a/arch/riscv/boot/dts/Makefile +++ b/arch/riscv/boot/dts/Makefile @@ -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)) diff --git a/arch/riscv/boot/dts/starfive/Makefile b/arch/riscv/boot/dts/starfive/Makefile new file mode 100644 index 000000000000..10246550ce79 --- /dev/null +++ b/arch/riscv/boot/dts/starfive/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_SOC_STARFIVE_JH7110) += starfive_jh7110.dtb diff --git a/arch/riscv/boot/dts/starfive/starfive_jh7110.dts b/arch/riscv/boot/dts/starfive/starfive_jh7110.dts new file mode 100644 index 000000000000..21a9ce742d8b --- /dev/null +++ b/arch/riscv/boot/dts/starfive/starfive_jh7110.dts @@ -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"; + }; + }; +}; diff --git a/arch/riscv/boot/dts/starfive/starfive_jh7110_audio.dtsi b/arch/riscv/boot/dts/starfive/starfive_jh7110_audio.dtsi new file mode 100644 index 000000000000..3c551196efb2 --- /dev/null +++ b/arch/riscv/boot/dts/starfive/starfive_jh7110_audio.dtsi @@ -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>; + }; + }; +};
\ No newline at end of file diff --git a/arch/riscv/boot/dts/starfive/starfive_jh7110_clk.dtsi b/arch/riscv/boot/dts/starfive/starfive_jh7110_clk.dtsi new file mode 100644 index 000000000000..b0c1f4d71ce6 --- /dev/null +++ b/arch/riscv/boot/dts/starfive/starfive_jh7110_clk.dtsi @@ -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>; + }; +}; diff --git a/arch/riscv/configs/starfive_jh7110_defconfig b/arch/riscv/configs/starfive_jh7110_defconfig new file mode 100644 index 000000000000..cdedbdd53160 --- /dev/null +++ b/arch/riscv/configs/starfive_jh7110_defconfig @@ -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 diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index fae5141251e5..1dc803d2c03a 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -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" diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index fbcda637d5e1..8e44616bb8ca 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -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 diff --git a/drivers/gpio/gpio-starfive-jh7110.c b/drivers/gpio/gpio-starfive-jh7110.c new file mode 100644 index 000000000000..2ca62b0e978e --- /dev/null +++ b/drivers/gpio/gpio-starfive-jh7110.c @@ -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"); diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c index bc91fd867dcd..3730c5d66843 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c @@ -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 }, { } }; diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.c b/drivers/net/ethernet/stmicro/stmmac/hwif.c index bb7114f970f8..ab7dbb6dc6e5 100644 --- a/drivers/net/ethernet/stmicro/stmmac/hwif.c +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.c @@ -215,6 +215,24 @@ static const struct stmmac_hwif_entry { .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, .xgmac = true, .min_id = DWXGMAC_CORE_2_10, diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 4fcfca4e1702..d650fb2333da 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -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) diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index 5c928f827173..dc4965cf1697 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c @@ -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); diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 4f9990b47a37..a711be508190 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -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) diff --git a/drivers/soc/sifive/Kconfig b/drivers/soc/sifive/Kconfig index 58cf8c40d08d..7d67517f3299 100644 --- a/drivers/soc/sifive/Kconfig +++ b/drivers/soc/sifive/Kconfig @@ -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 diff --git a/drivers/soc/sifive/sifive_l2_cache.c b/drivers/soc/sifive/sifive_l2_cache.c index 59640a1d0b28..bf824d52b9b8 100644 --- a/drivers/soc/sifive/sifive_l2_cache.c +++ b/drivers/soc/sifive/sifive_l2_cache.c @@ -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; diff --git a/include/soc/sifive/sifive_l2_cache.h b/include/soc/sifive/sifive_l2_cache.h index 92ade10ed67e..04dcac10b5cd 100644 --- a/include/soc/sifive/sifive_l2_cache.h +++ b/include/soc/sifive/sifive_l2_cache.h @@ -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 */ diff --git a/include/soc/starfive/vic7100.h b/include/soc/starfive/vic7100.h new file mode 100644 index 000000000000..4e8ca798cf13 --- /dev/null +++ b/include/soc/starfive/vic7100.h @@ -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*/ diff --git a/usr/gen_initramfs_list.sh b/usr/gen_initramfs_list.sh new file mode 100755 index 000000000000..0aad760fcd8c --- /dev/null +++ b/usr/gen_initramfs_list.sh @@ -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 |