Pull more RISC-V updates from Palmer Dabbelt: - DT updates for the PolarFire SOC - a fix to correct the handling of write-only mappings - m{vetndor,arcd,imp}id is now in /proc/cpuinfo - the SiFive L2 cache controller support has been refactored to also support L3 caches - misc fixes, cleanups and improvements throughout the tree * tag 'riscv-for-linus-6.1-mw2' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux: (42 commits) MAINTAINERS: add RISC-V's patchwork RISC-V: Make port I/O string accessors actually work riscv: enable software resend of irqs RISC-V: Re-enable counter access from userspace riscv: vdso: fix NULL deference in vdso_join_timens() when vfork riscv: Add cache information in AUX vector soc: sifive: ccache: define the macro for the register shifts soc: sifive: ccache: use pr_fmt() to remove CCACHE: prefixes soc: sifive: ccache: reduce printing on init soc: sifive: ccache: determine the cache level from dts soc: sifive: ccache: Rename SiFive L2 cache to Composable cache. dt-bindings: sifive-ccache: change Sifive L2 cache to Composable cache riscv: check for kernel config option in t-head memory types errata riscv: use BIT() marco for cpufeature probing riscv: use BIT() macros in t-head errata init riscv: drop some idefs from CMO initialization riscv: cleanup svpbmt cpufeature probing riscv: Pass -mno-relax only on lld < 15.0.0 RISC-V: Avoid dereferening NULL regs in die() dt-bindings: riscv: add new riscv,isa strings for emulators ...
Unified · Split
| @@ -66,6 +66,11 @@ properties: · 65 unmodified lines | ||
| 66 | 66 | - enum: |
| 67 | 67 | - allwinner,sun20i-d1-plic |
| 68 | 68 | - const: thead,c900-plic |
| 69 | + - items: | |
| 70 | + - const: sifive,plic-1.0.0 | |
| 71 | + - const: riscv,plic0 | |
| 72 | + deprecated: true | |
| 73 | + description: For the QEMU virt machine only | |
| 69 | 74 | |
| 70 | 75 | reg: |
| 71 | 76 | maxItems: 1 |
| @@ -9,6 +9,7 @@ title: RISC-V bindings for 'cpus' DT nodes · 8 unmodified lines | ||
| 9 | 9 | maintainers: |
| 10 | 10 | - Paul Walmsley <paul.walmsley@sifive.com> |
| 11 | 11 | - Palmer Dabbelt <palmer@sifive.com> |
| 12 | + - Conor Dooley <conor@kernel.org> | |
| 12 | 13 | |
| 13 | 14 | description: | |
| 14 | 15 | This document uses some terminology common to the RISC-V community |
| @@ -79,9 +80,7 @@ properties: · 64 unmodified lines | ||
| 79 | 80 | insensitive, letters in the riscv,isa string must be all |
| 80 | 81 | lowercase to simplify parsing. |
| 81 | 82 | $ref: "/schemas/types.yaml#/definitions/string" |
| 82 | − enum: | |
| 83 | − - rv64imac | |
| 84 | − - rv64imafdc | |
| 83 | + pattern: ^rv(?:64|32)imaf?d?q?c?b?v?k?h?(?:_[hsxz](?:[a-z])+)*$ | |
| 85 | 84 | |
| 86 | 85 | # RISC-V requires 'timebase-frequency' in /cpus, so disallow it here |
| 87 | 86 | timebase-frequency: false |
| @@ -7,8 +7,8 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# · 6 unmodified lines | ||
| 7 | 7 | title: Microchip PolarFire SoC-based boards |
| 8 | 8 | |
| 9 | 9 | maintainers: |
| 10 | − - Cyril Jean <Cyril.Jean@microchip.com> | |
| 11 | − - Lewis Hanly <lewis.hanly@microchip.com> | |
| 10 | + - Conor Dooley <conor.dooley@microchip.com> | |
| 11 | + - Daire McNamara <daire.mcnamara@microchip.com> | |
| 12 | 12 | |
| 13 | 13 | description: |
| 14 | 14 | Microchip PolarFire SoC-based boards |
| @@ -17,12 +17,20 @@ properties: · 2 unmodified lines | ||
| 17 | 17 | $nodename: |
| 18 | 18 | const: '/' |
| 19 | 19 | compatible: |
| 20 | − items: | |
| 21 | − - enum: | |
| 22 | − - microchip,mpfs-icicle-kit | |
| 23 | − - microchip,mpfs-icicle-reference-rtlv2203 | |
| 24 | − - sundance,polarberry | |
| 25 | − - const: microchip,mpfs | |
| 20 | + oneOf: | |
| 21 | + - items: | |
| 22 | + - enum: | |
| 23 | + - microchip,mpfs-icicle-reference-rtlv2203 | |
| 24 | + - microchip,mpfs-icicle-reference-rtlv2210 | |
| 25 | + - const: microchip,mpfs-icicle-kit | |
| 26 | + - const: microchip,mpfs | |
| 27 | + | |
| 28 | + - items: | |
| 29 | + - enum: | |
| 30 | + - aries,m100pfsevp | |
| 31 | + - microchip,mpfs-sev-kit | |
| 32 | + - sundance,polarberry | |
| 33 | + - const: microchip,mpfs | |
| 26 | 34 | |
| 27 | 35 | additionalProperties: true |
| 28 | 36 | |
| @@ -2,18 +2,18 @@ · 1 unmodified line | ||
| 2 | 2 | # Copyright (C) 2020 SiFive, Inc. |
| 3 | 3 | %YAML 1.2 |
| 4 | 4 | --- |
| 5 | −$id: http://devicetree.org/schemas/riscv/sifive-l2-cache.yaml# | |
| 5 | +$id: http://devicetree.org/schemas/riscv/sifive,ccache0.yaml# | |
| 6 | 6 | $schema: http://devicetree.org/meta-schemas/core.yaml# |
| 7 | 7 | |
| 8 | −title: SiFive L2 Cache Controller | |
| 8 | +title: SiFive Composable Cache Controller | |
| 9 | 9 | |
| 10 | 10 | maintainers: |
| 11 | 11 | - Sagar Kadam <sagar.kadam@sifive.com> |
| 12 | 12 | - Paul Walmsley <paul.walmsley@sifive.com> |
| 13 | 13 | |
| 14 | 14 | description: |
| 15 | − The SiFive Level 2 Cache Controller is used to provide access to fast copies | |
| 16 | − of memory for masters in a Core Complex. The Level 2 Cache Controller also | |
| 15 | + The SiFive Composable Cache Controller is used to provide access to fast copies | |
| 16 | + of memory for masters in a Core Complex. The Composable Cache Controller also | |
| 17 | 17 | acts as directory-based coherency manager. |
| 18 | 18 | All the properties in ePAPR/DeviceTree specification applies for this platform. |
| 19 | 19 | |
| @@ -22,6 +22,7 @@ select: · 2 unmodified lines | ||
| 22 | 22 | compatible: |
| 23 | 23 | contains: |
| 24 | 24 | enum: |
| 25 | + - sifive,ccache0 | |
| 25 | 26 | - sifive,fu540-c000-ccache |
| 26 | 27 | - sifive,fu740-c000-ccache |
| 27 | 28 | |
| @@ -33,6 +34,7 @@ properties: · 5 unmodified lines | ||
| 33 | 34 | oneOf: |
| 34 | 35 | - items: |
| 35 | 36 | - enum: |
| 37 | + - sifive,ccache0 | |
| 36 | 38 | - sifive,fu540-c000-ccache |
| 37 | 39 | - sifive,fu740-c000-ccache |
| 38 | 40 | - const: cache |
| @@ -45,7 +47,7 @@ properties: · 6 unmodified lines | ||
| 45 | 47 | const: 64 |
| 46 | 48 | |
| 47 | 49 | cache-level: |
| 48 | − const: 2 | |
| 50 | + enum: [2, 3] | |
| 49 | 51 | |
| 50 | 52 | cache-sets: |
| 51 | 53 | enum: [1024, 2048] |
| @@ -115,6 +117,22 @@ allOf: · 63 unmodified lines | ||
| 115 | 117 | cache-sets: |
| 116 | 118 | const: 1024 |
| 117 | 119 | |
| 120 | + - if: | |
| 121 | + properties: | |
| 122 | + compatible: | |
| 123 | + contains: | |
| 124 | + const: sifive,ccache0 | |
| 125 | + | |
| 126 | + then: | |
| 127 | + properties: | |
| 128 | + cache-level: | |
| 129 | + enum: [2, 3] | |
| 130 | + | |
| 131 | + else: | |
| 132 | + properties: | |
| 133 | + cache-level: | |
| 134 | + const: 2 | |
| 135 | + | |
| 118 | 136 | additionalProperties: false |
| 119 | 137 | |
| 120 | 138 | required: |
| @@ -22,12 +22,18 @@ description: · 21 unmodified lines | ||
| 22 | 22 | |
| 23 | 23 | properties: |
| 24 | 24 | compatible: |
| 25 | − items: | |
| 26 | − - enum: | |
| 27 | − - sifive,fu540-c000-clint | |
| 28 | − - starfive,jh7100-clint | |
| 29 | − - canaan,k210-clint | |
| 30 | − - const: sifive,clint0 | |
| 25 | + oneOf: | |
| 26 | + - items: | |
| 27 | + - enum: | |
| 28 | + - sifive,fu540-c000-clint | |
| 29 | + - starfive,jh7100-clint | |
| 30 | + - canaan,k210-clint | |
| 31 | + - const: sifive,clint0 | |
| 32 | + - items: | |
| 33 | + - const: sifive,clint0 | |
| 34 | + - const: riscv,clint0 | |
| 35 | + deprecated: true | |
| 36 | + description: For the QEMU virt machine only | |
| 31 | 37 | |
| 32 | 38 | description: |
| 33 | 39 | Should be "<vendor>,<chip>-clint" and "sifive,clint<version>". |
| @@ -8,6 +8,7 @@ RISC-V architecture · 7 unmodified lines | ||
| 8 | 8 | boot-image-header |
| 9 | 9 | vm-layout |
| 10 | 10 | patch-acceptance |
| 11 | + uabi | |
| 11 | 12 | |
| 12 | 13 | features |
| 13 | 14 | |
| @@ -0,0 +1,6 @@ | ||
| 1 | +.. SPDX-License-Identifier: GPL-2.0 | |
| 2 | + | |
| 3 | +RISC-V Linux User ABI | |
| 4 | +===================== | |
| 5 | + | |
| 6 | +Misaligned accesses are supported in userspace, but they may perform poorly. | |
| @@ -17702,6 +17702,7 @@ M: Palmer Dabbelt <palmer@dabbelt.com> · 17701 unmodified lines | ||
| 17702 | 17702 | M: Albert Ou <aou@eecs.berkeley.edu> |
| 17703 | 17703 | L: linux-riscv@lists.infradead.org |
| 17704 | 17704 | S: Supported |
| 17705 | +Q: https://patchwork.kernel.org/project/linux-riscv/list/ | |
| 17705 | 17706 | P: Documentation/riscv/patch-acceptance.rst |
| 17706 | 17707 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux.git |
| 17707 | 17708 | F: arch/riscv/ |
| @@ -17713,12 +17714,13 @@ M: Conor Dooley <conor.dooley@microchip.com> · 5 unmodified lines | ||
| 17713 | 17714 | M: Daire McNamara <daire.mcnamara@microchip.com> |
| 17714 | 17715 | L: linux-riscv@lists.infradead.org |
| 17715 | 17716 | S: Supported |
| 17716 | −F: Documentation/devicetree/bindings/clock/microchip,mpfs.yaml | |
| 17717 | +F: Documentation/devicetree/bindings/clock/microchip,mpfs*.yaml | |
| 17717 | 17718 | F: Documentation/devicetree/bindings/gpio/microchip,mpfs-gpio.yaml |
| 17718 | 17719 | F: Documentation/devicetree/bindings/i2c/microchip,corei2c.yaml |
| 17719 | 17720 | F: Documentation/devicetree/bindings/mailbox/microchip,mpfs-mailbox.yaml |
| 17720 | 17721 | F: Documentation/devicetree/bindings/net/can/microchip,mpfs-can.yaml |
| 17721 | 17722 | F: Documentation/devicetree/bindings/pwm/microchip,corepwm.yaml |
| 17723 | +F: Documentation/devicetree/bindings/riscv/microchip.yaml | |
| 17722 | 17724 | F: Documentation/devicetree/bindings/soc/microchip/microchip,mpfs-sys-controller.yaml |
| 17723 | 17725 | F: Documentation/devicetree/bindings/spi/microchip,mpfs-spi.yaml |
| 17724 | 17726 | F: Documentation/devicetree/bindings/usb/microchip,mpfs-musb.yaml |
| @@ -70,6 +70,7 @@ config RISCV · 69 unmodified lines | ||
| 70 | 70 | select GENERIC_SMP_IDLE_THREAD |
| 71 | 71 | select GENERIC_TIME_VSYSCALL if MMU && 64BIT |
| 72 | 72 | select GENERIC_VDSO_TIME_NS if HAVE_GENERIC_VDSO |
| 73 | + select HARDIRQS_SW_RESEND | |
| 73 | 74 | select HAVE_ARCH_AUDITSYSCALL |
| 74 | 75 | select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL |
| 75 | 76 | select HAVE_ARCH_JUMP_LABEL_RELATIVE if !XIP_KERNEL |
| @@ -37,6 +37,7 @@ else · 36 unmodified lines | ||
| 37 | 37 | endif |
| 38 | 38 | |
| 39 | 39 | ifeq ($(CONFIG_LD_IS_LLD),y) |
| 40 | +ifeq ($(shell test $(CONFIG_LLD_VERSION) -lt 150000; echo $$?),0) | |
| 40 | 41 | KBUILD_CFLAGS += -mno-relax |
| 41 | 42 | KBUILD_AFLAGS += -mno-relax |
| 42 | 43 | ifndef CONFIG_AS_IS_LLVM |
| @@ -44,6 +45,7 @@ ifndef CONFIG_AS_IS_LLVM · 1 unmodified line | ||
| 44 | 45 | KBUILD_AFLAGS += -Wa,-mno-relax |
| 45 | 46 | endif |
| 46 | 47 | endif |
| 48 | +endif | |
| 47 | 49 | |
| 48 | 50 | # ISA string setting |
| 49 | 51 | riscv-march-$(CONFIG_ARCH_RV32I) := rv32ima |
| @@ -1,4 +1,6 @@ | ||
| 1 | 1 | # SPDX-License-Identifier: GPL-2.0 |
| 2 | 2 | dtb-$(CONFIG_SOC_MICROCHIP_POLARFIRE) += mpfs-icicle-kit.dtb |
| 3 | +dtb-$(CONFIG_SOC_MICROCHIP_POLARFIRE) += mpfs-m100pfsevp.dtb | |
| 3 | 4 | dtb-$(CONFIG_SOC_MICROCHIP_POLARFIRE) += mpfs-polarberry.dtb |
| 5 | +dtb-$(CONFIG_SOC_MICROCHIP_POLARFIRE) += mpfs-sev-kit.dtb | |
| 4 | 6 | obj-$(CONFIG_BUILTIN_DTB) += $(addsuffix .o, $(dtb-y)) |
| @@ -2,20 +2,21 @@ · 1 unmodified line | ||
| 2 | 2 | /* Copyright (c) 2020-2021 Microchip Technology Inc */ |
| 3 | 3 | |
| 4 | 4 | / { |
| 5 | − compatible = "microchip,mpfs-icicle-reference-rtlv2203", "microchip,mpfs"; | |
| 5 | + compatible = "microchip,mpfs-icicle-reference-rtlv2210", "microchip,mpfs-icicle-kit", | |
| 6 | + "microchip,mpfs"; | |
| 6 | 7 | |
| 7 | − core_pwm0: pwm@41000000 { | |
| 8 | + core_pwm0: pwm@40000000 { | |
| 8 | 9 | compatible = "microchip,corepwm-rtl-v4"; |
| 9 | − reg = <0x0 0x41000000 0x0 0xF0>; | |
| 10 | + reg = <0x0 0x40000000 0x0 0xF0>; | |
| 10 | 11 | microchip,sync-update-mask = /bits/ 32 <0>; |
| 11 | 12 | #pwm-cells = <2>; |
| 12 | 13 | clocks = <&fabric_clk3>; |
| 13 | 14 | status = "disabled"; |
| 14 | 15 | }; |
| 15 | 16 | |
| 16 | − i2c2: i2c@44000000 { | |
| 17 | + i2c2: i2c@40000200 { | |
| 17 | 18 | compatible = "microchip,corei2c-rtl-v7"; |
| 18 | − reg = <0x0 0x44000000 0x0 0x1000>; | |
| 19 | + reg = <0x0 0x40000200 0x0 0x100>; | |
| 19 | 20 | #address-cells = <1>; |
| 20 | 21 | #size-cells = <0>; |
| 21 | 22 | clocks = <&fabric_clk3>; |
| @@ -28,7 +29,7 @@ · 6 unmodified lines | ||
| 28 | 29 | fabric_clk3: fabric-clk3 { |
| 29 | 30 | compatible = "fixed-clock"; |
| 30 | 31 | #clock-cells = <0>; |
| 31 | − clock-frequency = <62500000>; | |
| 32 | + clock-frequency = <50000000>; | |
| 32 | 33 | }; |
| 33 | 34 | |
| 34 | 35 | fabric_clk1: fabric-clk1 { |
| @@ -36,4 +37,34 @@ · 1 unmodified line | ||
| 36 | 37 | #clock-cells = <0>; |
| 37 | 38 | clock-frequency = <125000000>; |
| 38 | 39 | }; |
| 40 | + | |
| 41 | + pcie: pcie@3000000000 { | |
| 42 | + compatible = "microchip,pcie-host-1.0"; | |
| 43 | + #address-cells = <0x3>; | |
| 44 | + #interrupt-cells = <0x1>; | |
| 45 | + #size-cells = <0x2>; | |
| 46 | + device_type = "pci"; | |
| 47 | + reg = <0x30 0x0 0x0 0x8000000>, <0x0 0x43000000 0x0 0x10000>; | |
| 48 | + reg-names = "cfg", "apb"; | |
| 49 | + bus-range = <0x0 0x7f>; | |
| 50 | + interrupt-parent = <&plic>; | |
| 51 | + interrupts = <119>; | |
| 52 | + interrupt-map = <0 0 0 1 &pcie_intc 0>, | |
| 53 | + <0 0 0 2 &pcie_intc 1>, | |
| 54 | + <0 0 0 3 &pcie_intc 2>, | |
| 55 | + <0 0 0 4 &pcie_intc 3>; | |
| 56 | + interrupt-map-mask = <0 0 0 7>; | |
| 57 | + clocks = <&fabric_clk1>, <&fabric_clk3>; | |
| 58 | + clock-names = "fic1", "fic3"; | |
| 59 | + ranges = <0x3000000 0x0 0x8000000 0x30 0x8000000 0x0 0x80000000>; | |
| 60 | + dma-ranges = <0x02000000 0x0 0x00000000 0x0 0x00000000 0x1 0x00000000>; | |
| 61 | + msi-parent = <&pcie>; | |
| 62 | + msi-controller; | |
| 63 | + status = "disabled"; | |
| 64 | + pcie_intc: interrupt-controller { | |
| 65 | + #address-cells = <0>; | |
| 66 | + #interrupt-cells = <1>; | |
| 67 | + interrupt-controller; | |
| 68 | + }; | |
| 69 | + }; | |
| 39 | 70 | }; |
| @@ -11,7 +11,8 @@ · 10 unmodified lines | ||
| 11 | 11 | |
| 12 | 12 | / { |
| 13 | 13 | model = "Microchip PolarFire-SoC Icicle Kit"; |
| 14 | − compatible = "microchip,mpfs-icicle-kit", "microchip,mpfs"; | |
| 14 | + compatible = "microchip,mpfs-icicle-reference-rtlv2210", "microchip,mpfs-icicle-kit", | |
| 15 | + "microchip,mpfs"; | |
| 15 | 16 | |
| 16 | 17 | aliases { |
| 17 | 18 | ethernet0 = &mac1; |
| @@ -32,15 +33,26 @@ · 14 unmodified lines | ||
| 32 | 33 | |
| 33 | 34 | ddrc_cache_lo: memory@80000000 { |
| 34 | 35 | device_type = "memory"; |
| 35 | − reg = <0x0 0x80000000 0x0 0x2e000000>; | |
| 36 | + reg = <0x0 0x80000000 0x0 0x40000000>; | |
| 36 | 37 | status = "okay"; |
| 37 | 38 | }; |
| 38 | 39 | |
| 39 | 40 | ddrc_cache_hi: memory@1000000000 { |
| 40 | 41 | device_type = "memory"; |
| 41 | − reg = <0x10 0x0 0x0 0x40000000>; | |
| 42 | + reg = <0x10 0x40000000 0x0 0x40000000>; | |
| 42 | 43 | status = "okay"; |
| 43 | 44 | }; |
| 45 | + | |
| 46 | + reserved-memory { | |
| 47 | + #address-cells = <2>; | |
| 48 | + #size-cells = <2>; | |
| 49 | + ranges; | |
| 50 | + | |
| 51 | + hss_payload: region@BFC00000 { | |
| 52 | + reg = <0x0 0xBFC00000 0x0 0x400000>; | |
| 53 | + no-map; | |
| 54 | + }; | |
| 55 | + }; | |
| 44 | 56 | }; |
| 45 | 57 | |
| 46 | 58 | &core_pwm0 { |
| @@ -0,0 +1,45 @@ | ||
| 1 | +// SPDX-License-Identifier: (GPL-2.0 OR MIT) | |
| 2 | +/* Copyright (c) 2022 Microchip Technology Inc */ | |
| 3 | + | |
| 4 | +/ { | |
| 5 | + fabric_clk3: fabric-clk3 { | |
| 6 | + compatible = "fixed-clock"; | |
| 7 | + #clock-cells = <0>; | |
| 8 | + clock-frequency = <62500000>; | |
| 9 | + }; | |
| 10 | + | |
| 11 | + fabric_clk1: fabric-clk1 { | |
| 12 | + compatible = "fixed-clock"; | |
| 13 | + #clock-cells = <0>; | |
| 14 | + clock-frequency = <125000000>; | |
| 15 | + }; | |
| 16 | + | |
| 17 | + pcie: pcie@2000000000 { | |
| 18 | + compatible = "microchip,pcie-host-1.0"; | |
| 19 | + #address-cells = <0x3>; | |
| 20 | + #interrupt-cells = <0x1>; | |
| 21 | + #size-cells = <0x2>; | |
| 22 | + device_type = "pci"; | |
| 23 | + reg = <0x20 0x0 0x0 0x8000000>, <0x0 0x43000000 0x0 0x10000>; | |
| 24 | + reg-names = "cfg", "apb"; | |
| 25 | + bus-range = <0x0 0x7f>; | |
| 26 | + interrupt-parent = <&plic>; | |
| 27 | + interrupts = <119>; | |
| 28 | + interrupt-map = <0 0 0 1 &pcie_intc 0>, | |
| 29 | + <0 0 0 2 &pcie_intc 1>, | |
| 30 | + <0 0 0 3 &pcie_intc 2>, | |
| 31 | + <0 0 0 4 &pcie_intc 3>; | |
| 32 | + interrupt-map-mask = <0 0 0 7>; | |
| 33 | + clocks = <&fabric_clk1>, <&fabric_clk1>, <&fabric_clk3>; | |
| 34 | + clock-names = "fic0", "fic1", "fic3"; | |
| 35 | + ranges = <0x3000000 0x0 0x8000000 0x20 0x8000000 0x0 0x80000000>; | |
| 36 | + msi-parent = <&pcie>; | |
| 37 | + msi-controller; | |
| 38 | + status = "disabled"; | |
| 39 | + pcie_intc: interrupt-controller { | |
| 40 | + #address-cells = <0>; | |
| 41 | + #interrupt-cells = <1>; | |
| 42 | + interrupt-controller; | |
| 43 | + }; | |
| 44 | + }; | |
| 45 | +}; | |
| @@ -0,0 +1,179 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0 | |
| 2 | +/* | |
| 3 | + * Original all-in-one devicetree: | |
| 4 | + * Copyright (C) 2021-2022 - Wolfgang Grandegger <wg@aries-embedded.de> | |
| 5 | + * Rewritten to use includes: | |
| 6 | + * Copyright (C) 2022 - Conor Dooley <conor.dooley@microchip.com> | |
| 7 | + */ | |
| 8 | +/dts-v1/; | |
| 9 | + | |
| 10 | +#include "mpfs.dtsi" | |
| 11 | +#include "mpfs-m100pfs-fabric.dtsi" | |
| 12 | + | |
| 13 | +/* Clock frequency (in Hz) of the rtcclk */ | |
| 14 | +#define MTIMER_FREQ 1000000 | |
| 15 | + | |
| 16 | +/ { | |
| 17 | + model = "Aries Embedded M100PFEVPS"; | |
| 18 | + compatible = "aries,m100pfsevp", "microchip,mpfs"; | |
| 19 | + | |
| 20 | + aliases { | |
| 21 | + ethernet0 = &mac0; | |
| 22 | + ethernet1 = &mac1; | |
| 23 | + serial0 = &mmuart0; | |
| 24 | + serial1 = &mmuart1; | |
| 25 | + serial2 = &mmuart2; | |
| 26 | + serial3 = &mmuart3; | |
| 27 | + serial4 = &mmuart4; | |
| 28 | + gpio0 = &gpio0; | |
| 29 | + gpio1 = &gpio2; | |
| 30 | + }; | |
| 31 | + | |
| 32 | + chosen { | |
| 33 | + stdout-path = "serial1:115200n8"; | |
| 34 | + }; | |
| 35 | + | |
| 36 | + cpus { | |
| 37 | + timebase-frequency = <MTIMER_FREQ>; | |
| 38 | + }; | |
| 39 | + | |
| 40 | + ddrc_cache_lo: memory@80000000 { | |
| 41 | + device_type = "memory"; | |
| 42 | + reg = <0x0 0x80000000 0x0 0x40000000>; | |
| 43 | + }; | |
| 44 | + ddrc_cache_hi: memory@1040000000 { | |
| 45 | + device_type = "memory"; | |
| 46 | + reg = <0x10 0x40000000 0x0 0x40000000>; | |
| 47 | + }; | |
| 48 | +}; | |
| 49 | + | |
| 50 | +&can0 { | |
| 51 | + status = "okay"; | |
| 52 | +}; | |
| 53 | + | |
| 54 | +&i2c0 { | |
| 55 | + status = "okay"; | |
| 56 | +}; | |
| 57 | + | |
| 58 | +&i2c1 { | |
| 59 | + status = "okay"; | |
| 60 | +}; | |
| 61 | + | |
| 62 | +&gpio0 { | |
| 63 | + interrupts = <13>, <14>, <15>, <16>, | |
| 64 | + <17>, <18>, <19>, <20>, | |
| 65 | + <21>, <22>, <23>, <24>, | |
| 66 | + <25>, <26>; | |
| 67 | + ngpios = <14>; | |
| 68 | + status = "okay"; | |
| 69 | + | |
| 70 | + pmic-irq-hog { | |
| 71 | + gpio-hog; | |
| 72 | + gpios = <13 0>; | |
| 73 | + input; | |
| 74 | + }; | |
| 75 | + | |
| 76 | + /* Set to low for eMMC, high for SD-card */ | |
| 77 | + mmc-sel-hog { | |
| 78 | + gpio-hog; | |
| 79 | + gpios = <12 0>; | |
| 80 | + output-high; | |
| 81 | + }; | |
| 82 | +}; | |
| 83 | + | |
| 84 | +&gpio2 { | |
| 85 | + interrupts = <13>, <14>, <15>, <16>, | |
| 86 | + <17>, <18>, <19>, <20>, | |
| 87 | + <21>, <22>, <23>, <24>, | |
| 88 | + <25>, <26>, <27>, <28>, | |
| 89 | + <29>, <30>, <31>, <32>, | |
| 90 | + <33>, <34>, <35>, <36>, | |
| 91 | + <37>, <38>, <39>, <40>, | |
| 92 | + <41>, <42>, <43>, <44>; | |
| 93 | + status = "okay"; | |
| 94 | +}; | |
| 95 | + | |
| 96 | +&mac0 { | |
| 97 | + status = "okay"; | |
| 98 | + phy-mode = "gmii"; | |
| 99 | + phy-handle = <&phy0>; | |
| 100 | + phy0: ethernet-phy@0 { | |
| 101 | + reg = <0>; | |
| 102 | + }; | |
| 103 | +}; | |
| 104 | + | |
| 105 | +&mac1 { | |
| 106 | + status = "okay"; | |
| 107 | + phy-mode = "gmii"; | |
| 108 | + phy-handle = <&phy1>; | |
| 109 | + phy1: ethernet-phy@0 { | |
| 110 | + reg = <0>; | |
| 111 | + }; | |
| 112 | +}; | |
| 113 | + | |
| 114 | +&mbox { | |
| 115 | + status = "okay"; | |
| 116 | +}; | |
| 117 | + | |
| 118 | +&mmc { | |
| 119 | + max-frequency = <50000000>; | |
| 120 | + bus-width = <4>; | |
| 121 | + cap-mmc-highspeed; | |
| 122 | + cap-sd-highspeed; | |
| 123 | + no-1-8-v; | |
| 124 | + sd-uhs-sdr12; | |
| 125 | + sd-uhs-sdr25; | |
| 126 | + sd-uhs-sdr50; | |
| 127 | + sd-uhs-sdr104; | |
| 128 | + disable-wp; | |
| 129 | + status = "okay"; | |
| 130 | +}; | |
| 131 | + | |
| 132 | +&mmuart1 { | |
| 133 | + status = "okay"; | |
| 134 | +}; | |
| 135 | + | |
| 136 | +&mmuart2 { | |
| 137 | + status = "okay"; | |
| 138 | +}; | |
| 139 | + | |
| 140 | +&mmuart3 { | |
| 141 | + status = "okay"; | |
| 142 | +}; | |
| 143 | + | |
| 144 | +&mmuart4 { | |
| 145 | + status = "okay"; | |
| 146 | +}; | |
| 147 | + | |
| 148 | +&pcie { | |
| 149 | + status = "okay"; | |
| 150 | +}; | |
| 151 | + | |
| 152 | +&qspi { | |
| 153 | + status = "okay"; | |
| 154 | +}; | |
| 155 | + | |
| 156 | +&refclk { | |
| 157 | + clock-frequency = <125000000>; | |
| 158 | +}; | |
| 159 | + | |
| 160 | +&rtc { | |
| 161 | + status = "okay"; | |
| 162 | +}; | |
| 163 | + | |
| 164 | +&spi0 { | |
| 165 | + status = "okay"; | |
| 166 | +}; | |
| 167 | + | |
| 168 | +&spi1 { | |
| 169 | + status = "okay"; | |
| 170 | +}; | |
| 171 | + | |
| 172 | +&syscontroller { | |
| 173 | + status = "okay"; | |
| 174 | +}; | |
| 175 | + | |
| 176 | +&usb { | |
| 177 | + status = "okay"; | |
| 178 | + dr_mode = "host"; | |
| 179 | +}; | |
| @@ -13,4 +13,33 @@ · 12 unmodified lines | ||
| 13 | 13 | #clock-cells = <0>; |
| 14 | 14 | clock-frequency = <125000000>; |
| 15 | 15 | }; |
| 16 | + | |
| 17 | + pcie: pcie@2000000000 { | |
| 18 | + compatible = "microchip,pcie-host-1.0"; | |
| 19 | + #address-cells = <0x3>; | |
| 20 | + #interrupt-cells = <0x1>; | |
| 21 | + #size-cells = <0x2>; | |
| 22 | + device_type = "pci"; | |
| 23 | + reg = <0x20 0x0 0x0 0x8000000>, <0x0 0x43000000 0x0 0x10000>; | |
| 24 | + reg-names = "cfg", "apb"; | |
| 25 | + bus-range = <0x0 0x7f>; | |
| 26 | + interrupt-parent = <&plic>; | |
| 27 | + interrupts = <119>; | |
| 28 | + interrupt-map = <0 0 0 1 &pcie_intc 0>, | |
| 29 | + <0 0 0 2 &pcie_intc 1>, | |
| 30 | + <0 0 0 3 &pcie_intc 2>, | |
| 31 | + <0 0 0 4 &pcie_intc 3>; | |
| 32 | + interrupt-map-mask = <0 0 0 7>; | |
| 33 | + clocks = <&fabric_clk1>, <&fabric_clk1>, <&fabric_clk3>; | |
| 34 | + clock-names = "fic0", "fic1", "fic3"; | |
| 35 | + ranges = <0x3000000 0x0 0x8000000 0x20 0x8000000 0x0 0x80000000>; | |
| 36 | + msi-parent = <&pcie>; | |
| 37 | + msi-controller; | |
| 38 | + status = "disabled"; | |
| 39 | + pcie_intc: interrupt-controller { | |
| 40 | + #address-cells = <0>; | |
| 41 | + #interrupt-cells = <1>; | |
| 42 | + interrupt-controller; | |
| 43 | + }; | |
| 44 | + }; | |
| 16 | 45 | }; |
| @@ -0,0 +1,45 @@ | ||
| 1 | +// SPDX-License-Identifier: (GPL-2.0 OR MIT) | |
| 2 | +/* Copyright (c) 2022 Microchip Technology Inc */ | |
| 3 | + | |
| 4 | +/ { | |
| 5 | + fabric_clk3: fabric-clk3 { | |
| 6 | + compatible = "fixed-clock"; | |
| 7 | + #clock-cells = <0>; | |
| 8 | + clock-frequency = <0>; | |
| 9 | + }; | |
| 10 | + | |
| 11 | + fabric_clk1: fabric-clk1 { | |
| 12 | + compatible = "fixed-clock"; | |
| 13 | + #clock-cells = <0>; | |
| 14 | + clock-frequency = <125000000>; | |
| 15 | + }; | |
| 16 | + | |
| 17 | + pcie: pcie@2000000000 { | |
| 18 | + compatible = "microchip,pcie-host-1.0"; | |
| 19 | + #address-cells = <0x3>; | |
| 20 | + #interrupt-cells = <0x1>; | |
| 21 | + #size-cells = <0x2>; | |
| 22 | + device_type = "pci"; | |
| 23 | + reg = <0x20 0x0 0x0 0x8000000>, <0x0 0x43000000 0x0 0x10000>; | |
| 24 | + reg-names = "cfg", "apb"; | |
| 25 | + bus-range = <0x0 0x7f>; | |
| 26 | + interrupt-parent = <&plic>; | |
| 27 | + interrupts = <119>; | |
| 28 | + interrupt-map = <0 0 0 1 &pcie_intc 0>, | |
| 29 | + <0 0 0 2 &pcie_intc 1>, | |
| 30 | + <0 0 0 3 &pcie_intc 2>, | |
| 31 | + <0 0 0 4 &pcie_intc 3>; | |
| 32 | + interrupt-map-mask = <0 0 0 7>; | |
| 33 | + clocks = <&fabric_clk1>, <&fabric_clk1>, <&fabric_clk3>; | |
| 34 | + clock-names = "fic0", "fic1", "fic3"; | |
| 35 | + ranges = <0x3000000 0x0 0x8000000 0x20 0x8000000 0x0 0x80000000>; | |
| 36 | + msi-parent = <&pcie>; | |
| 37 | + msi-controller; | |
| 38 | + status = "disabled"; | |
| 39 | + pcie_intc: interrupt-controller { | |
| 40 | + #address-cells = <0>; | |
| 41 | + #interrupt-cells = <1>; | |
| 42 | + interrupt-controller; | |
| 43 | + }; | |
| 44 | + }; | |
| 45 | +}; | |
| @@ -0,0 +1,145 @@ | ||
| 1 | +// SPDX-License-Identifier: (GPL-2.0 OR MIT) | |
| 2 | +/* Copyright (c) 2022 Microchip Technology Inc */ | |
| 3 | + | |
| 4 | +/dts-v1/; | |
| 5 | + | |
| 6 | +#include "mpfs.dtsi" | |
| 7 | +#include "mpfs-sev-kit-fabric.dtsi" | |
| 8 | + | |
| 9 | +/* Clock frequency (in Hz) of the rtcclk */ | |
| 10 | +#define MTIMER_FREQ 1000000 | |
| 11 | + | |
| 12 | +/ { | |
| 13 | + #address-cells = <2>; | |
| 14 | + #size-cells = <2>; | |
| 15 | + model = "Microchip PolarFire-SoC SEV Kit"; | |
| 16 | + compatible = "microchip,mpfs-sev-kit", "microchip,mpfs"; | |
| 17 | + | |
| 18 | + aliases { | |
| 19 | + ethernet0 = &mac1; | |
| 20 | + serial0 = &mmuart0; | |
| 21 | + serial1 = &mmuart1; | |
| 22 | + serial2 = &mmuart2; | |
| 23 | + serial3 = &mmuart3; | |
| 24 | + serial4 = &mmuart4; | |
| 25 | + }; | |
| 26 | + | |
| 27 | + chosen { | |
| 28 | + stdout-path = "serial1:115200n8"; | |
| 29 | + }; | |
| 30 | + | |
| 31 | + cpus { | |
| 32 | + timebase-frequency = <MTIMER_FREQ>; | |
| 33 | + }; | |
| 34 | + | |
| 35 | + reserved-memory { | |
| 36 | + #address-cells = <2>; | |
| 37 | + #size-cells = <2>; | |
| 38 | + ranges; | |
| 39 | + | |
| 40 | + fabricbuf0ddrc: buffer@80000000 { | |
| 41 | + compatible = "shared-dma-pool"; | |
| 42 | + reg = <0x0 0x80000000 0x0 0x2000000>; | |
| 43 | + }; | |
| 44 | + | |
| 45 | + fabricbuf1ddrnc: buffer@c4000000 { | |
| 46 | + compatible = "shared-dma-pool"; | |
| 47 | + reg = <0x0 0xc4000000 0x0 0x4000000>; | |
| 48 | + }; | |
| 49 | + | |
| 50 | + fabricbuf2ddrncwcb: buffer@d4000000 { | |
| 51 | + compatible = "shared-dma-pool"; | |
| 52 | + reg = <0x0 0xd4000000 0x0 0x4000000>; | |
| 53 | + }; | |
| 54 | + }; | |
| 55 | + | |
| 56 | + ddrc_cache: memory@1000000000 { | |
| 57 | + device_type = "memory"; | |
| 58 | + reg = <0x10 0x0 0x0 0x76000000>; | |
| 59 | + }; | |
| 60 | +}; | |
| 61 | + | |
| 62 | +&i2c0 { | |
| 63 | + status = "okay"; | |
| 64 | +}; | |
| 65 | + | |
| 66 | +&gpio2 { | |
| 67 | + interrupts = <53>, <53>, <53>, <53>, | |
| 68 | + <53>, <53>, <53>, <53>, | |
| 69 | + <53>, <53>, <53>, <53>, | |
| 70 | + <53>, <53>, <53>, <53>, | |
| 71 | + <53>, <53>, <53>, <53>, | |
| 72 | + <53>, <53>, <53>, <53>, | |
| 73 | + <53>, <53>, <53>, <53>, | |
| 74 | + <53>, <53>, <53>, <53>; | |
| 75 | + status = "okay"; | |
| 76 | +}; | |
| 77 | + | |
| 78 | +&mac0 { | |
| 79 | + status = "okay"; | |
| 80 | + phy-mode = "sgmii"; | |
| 81 | + phy-handle = <&phy0>; | |
| 82 | + phy1: ethernet-phy@9 { | |
| 83 | + reg = <9>; | |
| 84 | + }; | |
| 85 | + phy0: ethernet-phy@8 { | |
| 86 | + reg = <8>; | |
| 87 | + }; | |
| 88 | +}; | |
| 89 | + | |
| 90 | +&mac1 { | |
| 91 | + status = "okay"; | |
| 92 | + phy-mode = "sgmii"; | |
| 93 | + phy-handle = <&phy1>; | |
| 94 | +}; | |
| 95 | + | |
| 96 | +&mbox { | |
| 97 | + status = "okay"; | |
| 98 | +}; | |
| 99 | + | |
| 100 | +&mmc { | |
| 101 | + status = "okay"; | |
| 102 | + bus-width = <4>; | |
| 103 | + disable-wp; | |
| 104 | + cap-sd-highspeed; | |
| 105 | + cap-mmc-highspeed; | |
| 106 | + mmc-ddr-1_8v; | |
| 107 | + mmc-hs200-1_8v; | |
| 108 | + sd-uhs-sdr12; | |
| 109 | + sd-uhs-sdr25; | |
| 110 | + sd-uhs-sdr50; | |
| 111 | + sd-uhs-sdr104; | |
| 112 | +}; | |
| 113 | + | |
| 114 | +&mmuart1 { | |
| 115 | + status = "okay"; | |
| 116 | +}; | |
| 117 | + | |
| 118 | +&mmuart2 { | |
| 119 | + status = "okay"; | |
| 120 | +}; | |
| 121 | + | |
| 122 | +&mmuart3 { | |
| 123 | + status = "okay"; | |
| 124 | +}; | |
| 125 | + | |
| 126 | +&mmuart4 { | |
| 127 | + status = "okay"; | |
| 128 | +}; | |
| 129 | + | |
| 130 | +&refclk { | |
| 131 | + clock-frequency = <125000000>; | |
| 132 | +}; | |
| 133 | + | |
| 134 | +&rtc { | |
| 135 | + status = "okay"; | |
| 136 | +}; | |
| 137 | + | |
| 138 | +&syscontroller { | |
| 139 | + status = "okay"; | |
| 140 | +}; | |
| 141 | + | |
| 142 | +&usb { | |
| 143 | + status = "okay"; | |
| 144 | + dr_mode = "otg"; | |
| 145 | +}; | |
| @@ -330,7 +330,7 @@ · 329 unmodified lines | ||
| 330 | 330 | }; |
| 331 | 331 | |
| 332 | 332 | qspi: spi@21000000 { |
| 333 | − compatible = "microchip,mpfs-qspi"; | |
| 333 | + compatible = "microchip,mpfs-qspi", "microchip,coreqspi-rtl-v2"; | |
| 334 | 334 | #address-cells = <1>; |
| 335 | 335 | #size-cells = <0>; |
| 336 | 336 | reg = <0x0 0x21000000 0x0 0x1000>; |
| @@ -464,35 +464,6 @@ · 127 unmodified lines | ||
| 464 | 464 | status = "disabled"; |
| 465 | 465 | }; |
| 466 | 466 | |
| 467 | − pcie: pcie@2000000000 { | |
| 468 | − compatible = "microchip,pcie-host-1.0"; | |
| 469 | − #address-cells = <0x3>; | |
| 470 | − #interrupt-cells = <0x1>; | |
| 471 | − #size-cells = <0x2>; | |
| 472 | − device_type = "pci"; | |
| 473 | − reg = <0x20 0x0 0x0 0x8000000>, <0x0 0x43000000 0x0 0x10000>; | |
| 474 | − reg-names = "cfg", "apb"; | |
| 475 | − bus-range = <0x0 0x7f>; | |
| 476 | − interrupt-parent = <&plic>; | |
| 477 | − interrupts = <119>; | |
| 478 | − interrupt-map = <0 0 0 1 &pcie_intc 0>, | |
| 479 | − <0 0 0 2 &pcie_intc 1>, | |
| 480 | − <0 0 0 3 &pcie_intc 2>, | |
| 481 | − <0 0 0 4 &pcie_intc 3>; | |
| 482 | − interrupt-map-mask = <0 0 0 7>; | |
| 483 | − clocks = <&fabric_clk1>, <&fabric_clk1>, <&fabric_clk3>; | |
| 484 | − clock-names = "fic0", "fic1", "fic3"; | |
| 485 | − ranges = <0x3000000 0x0 0x8000000 0x20 0x8000000 0x0 0x80000000>; | |
| 486 | − msi-parent = <&pcie>; | |
| 487 | − msi-controller; | |
| 488 | − status = "disabled"; | |
| 489 | − pcie_intc: interrupt-controller { | |
| 490 | − #address-cells = <0>; | |
| 491 | − #interrupt-cells = <1>; | |
| 492 | − interrupt-controller; | |
| 493 | − }; | |
| 494 | − }; | |
| 495 | − | |
| 496 | 467 | mbox: mailbox@37020000 { |
| 497 | 468 | compatible = "microchip,mpfs-mailbox"; |
| 498 | 469 | reg = <0x0 0x37020000 0x0 0x1000>, <0x0 0x2000318C 0x0 0x40>; |
| @@ -17,6 +17,9 @@ · 16 unmodified lines | ||
| 17 | 17 | static bool errata_probe_pbmt(unsigned int stage, |
| 18 | 18 | unsigned long arch_id, unsigned long impid) |
| 19 | 19 | { |
| 20 | + if (!IS_ENABLED(CONFIG_ERRATA_THEAD_PBMT)) | |
| 21 | + return false; | |
| 22 | + | |
| 20 | 23 | if (arch_id != 0 || impid != 0) |
| 21 | 24 | return false; |
| 22 | 25 | |
| @@ -30,7 +33,9 @@ static bool errata_probe_pbmt(unsigned int stage, · 7 unmodified lines | ||
| 30 | 33 | static bool errata_probe_cmo(unsigned int stage, |
| 31 | 34 | unsigned long arch_id, unsigned long impid) |
| 32 | 35 | { |
| 33 | −#ifdef CONFIG_ERRATA_THEAD_CMO | |
| 36 | + if (!IS_ENABLED(CONFIG_ERRATA_THEAD_CMO)) | |
| 37 | + return false; | |
| 38 | + | |
| 34 | 39 | if (arch_id != 0 || impid != 0) |
| 35 | 40 | return false; |
| 36 | 41 | |
| @@ -40,9 +45,6 @@ static bool errata_probe_cmo(unsigned int stage, · 3 unmodified lines | ||
| 40 | 45 | riscv_cbom_block_size = L1_CACHE_BYTES; |
| 41 | 46 | riscv_noncoherent_supported(); |
| 42 | 47 | return true; |
| 43 | −#else | |
| 44 | − return false; | |
| 45 | −#endif | |
| 46 | 48 | } |
| 47 | 49 | |
| 48 | 50 | static u32 thead_errata_probe(unsigned int stage, |
| @@ -51,10 +53,10 @@ static u32 thead_errata_probe(unsigned int stage, · 2 unmodified lines | ||
| 51 | 53 | u32 cpu_req_errata = 0; |
| 52 | 54 | |
| 53 | 55 | if (errata_probe_pbmt(stage, archid, impid)) |
| 54 | − cpu_req_errata |= (1U << ERRATA_THEAD_PBMT); | |
| 56 | + cpu_req_errata |= BIT(ERRATA_THEAD_PBMT); | |
| 55 | 57 | |
| 56 | 58 | if (errata_probe_cmo(stage, archid, impid)) |
| 57 | − cpu_req_errata |= (1U << ERRATA_THEAD_CMO); | |
| 59 | + cpu_req_errata |= BIT(ERRATA_THEAD_CMO); | |
| 58 | 60 | |
| 59 | 61 | return cpu_req_errata; |
| 60 | 62 | } |
| @@ -55,6 +55,8 @@ static inline void riscv_init_cbom_blocksize(void) { } · 54 unmodified lines | ||
| 55 | 55 | |
| 56 | 56 | #ifdef CONFIG_RISCV_DMA_NONCOHERENT |
| 57 | 57 | void riscv_noncoherent_supported(void); |
| 58 | +#else | |
| 59 | +static inline void riscv_noncoherent_supported(void) {} | |
| 58 | 60 | #endif |
| 59 | 61 | |
| 60 | 62 | /* |
| @@ -99,6 +99,10 @@ do { \ · 98 unmodified lines | ||
| 99 | 99 | get_cache_size(2, CACHE_TYPE_UNIFIED)); \ |
| 100 | 100 | NEW_AUX_ENT(AT_L2_CACHEGEOMETRY, \ |
| 101 | 101 | get_cache_geometry(2, CACHE_TYPE_UNIFIED)); \ |
| 102 | + NEW_AUX_ENT(AT_L3_CACHESIZE, \ | |
| 103 | + get_cache_size(3, CACHE_TYPE_UNIFIED)); \ | |
| 104 | + NEW_AUX_ENT(AT_L3_CACHEGEOMETRY, \ | |
| 105 | + get_cache_geometry(3, CACHE_TYPE_UNIFIED)); \ | |
| 102 | 106 | } while (0) |
| 103 | 107 | #define ARCH_HAS_SETUP_ADDITIONAL_PAGES |
| 104 | 108 | struct linux_binprm; |
| @@ -101,9 +101,9 @@ __io_reads_ins(reads, u32, l, __io_br(), __io_ar(addr)) · 100 unmodified lines | ||
| 101 | 101 | __io_reads_ins(ins, u8, b, __io_pbr(), __io_par(addr)) |
| 102 | 102 | __io_reads_ins(ins, u16, w, __io_pbr(), __io_par(addr)) |
| 103 | 103 | __io_reads_ins(ins, u32, l, __io_pbr(), __io_par(addr)) |
| 104 | −#define insb(addr, buffer, count) __insb((void __iomem *)(long)addr, buffer, count) | |
| 105 | −#define insw(addr, buffer, count) __insw((void __iomem *)(long)addr, buffer, count) | |
| 106 | −#define insl(addr, buffer, count) __insl((void __iomem *)(long)addr, buffer, count) | |
| 104 | +#define insb(addr, buffer, count) __insb(PCI_IOBASE + (addr), buffer, count) | |
| 105 | +#define insw(addr, buffer, count) __insw(PCI_IOBASE + (addr), buffer, count) | |
| 106 | +#define insl(addr, buffer, count) __insl(PCI_IOBASE + (addr), buffer, count) | |
| 107 | 107 | |
| 108 | 108 | __io_writes_outs(writes, u8, b, __io_bw(), __io_aw()) |
| 109 | 109 | __io_writes_outs(writes, u16, w, __io_bw(), __io_aw()) |
| @@ -115,22 +115,22 @@ __io_writes_outs(writes, u32, l, __io_bw(), __io_aw()) · 5 unmodified lines | ||
| 115 | 115 | __io_writes_outs(outs, u8, b, __io_pbw(), __io_paw()) |
| 116 | 116 | __io_writes_outs(outs, u16, w, __io_pbw(), __io_paw()) |
| 117 | 117 | __io_writes_outs(outs, u32, l, __io_pbw(), __io_paw()) |
| 118 | −#define outsb(addr, buffer, count) __outsb((void __iomem *)(long)addr, buffer, count) | |
| 119 | −#define outsw(addr, buffer, count) __outsw((void __iomem *)(long)addr, buffer, count) | |
| 120 | −#define outsl(addr, buffer, count) __outsl((void __iomem *)(long)addr, buffer, count) | |
| 118 | +#define outsb(addr, buffer, count) __outsb(PCI_IOBASE + (addr), buffer, count) | |
| 119 | +#define outsw(addr, buffer, count) __outsw(PCI_IOBASE + (addr), buffer, count) | |
| 120 | +#define outsl(addr, buffer, count) __outsl(PCI_IOBASE + (addr), buffer, count) | |
| 121 | 121 | |
| 122 | 122 | #ifdef CONFIG_64BIT |
| 123 | 123 | __io_reads_ins(reads, u64, q, __io_br(), __io_ar(addr)) |
| 124 | 124 | #define readsq(addr, buffer, count) __readsq(addr, buffer, count) |
| 125 | 125 | |
| 126 | 126 | __io_reads_ins(ins, u64, q, __io_pbr(), __io_par(addr)) |
| 127 | −#define insq(addr, buffer, count) __insq((void __iomem *)addr, buffer, count) | |
| 127 | +#define insq(addr, buffer, count) __insq(PCI_IOBASE + (addr), buffer, count) | |
| 128 | 128 | |
| 129 | 129 | __io_writes_outs(writes, u64, q, __io_bw(), __io_aw()) |
| 130 | 130 | #define writesq(addr, buffer, count) __writesq(addr, buffer, count) |
| 131 | 131 | |
| 132 | 132 | __io_writes_outs(outs, u64, q, __io_pbr(), __io_paw()) |
| 133 | −#define outsq(addr, buffer, count) __outsq((void __iomem *)addr, buffer, count) | |
| 133 | +#define outsq(addr, buffer, count) __outsq(PCI_IOBASE + (addr), buffer, count) | |
| 134 | 134 | #endif |
| 135 | 135 | |
| 136 | 136 | #include <asm-generic/io.h> |
| @@ -16,7 +16,6 @@ typedef struct { · 15 unmodified lines | ||
| 16 | 16 | atomic_long_t id; |
| 17 | 17 | #endif |
| 18 | 18 | void *vdso; |
| 19 | − void *vdso_info; | |
| 20 | 19 | #ifdef CONFIG_SMP |
| 21 | 20 | /* A local icache flush is needed before user execution can resume. */ |
| 22 | 21 | cpumask_t icache_stale_mask; |
| @@ -30,8 +30,10 @@ · 29 unmodified lines | ||
| 30 | 30 | #define AT_L1D_CACHEGEOMETRY 43 |
| 31 | 31 | #define AT_L2_CACHESIZE 44 |
| 32 | 32 | #define AT_L2_CACHEGEOMETRY 45 |
| 33 | +#define AT_L3_CACHESIZE 46 | |
| 34 | +#define AT_L3_CACHEGEOMETRY 47 | |
| 33 | 35 | |
| 34 | 36 | /* entries in ARCH_DLINFO */ |
| 35 | −#define AT_VECTOR_SIZE_ARCH 7 | |
| 37 | +#define AT_VECTOR_SIZE_ARCH 9 | |
| 36 | 38 | |
| 37 | 39 | #endif /* _UAPI_ASM_RISCV_AUXVEC_H */ |
| @@ -3,10 +3,13 @@ · 2 unmodified lines | ||
| 3 | 3 | * Copyright (C) 2012 Regents of the University of California |
| 4 | 4 | */ |
| 5 | 5 | |
| 6 | +#include <linux/cpu.h> | |
| 6 | 7 | #include <linux/init.h> |
| 7 | 8 | #include <linux/seq_file.h> |
| 8 | 9 | #include <linux/of.h> |
| 10 | +#include <asm/csr.h> | |
| 9 | 11 | #include <asm/hwcap.h> |
| 12 | +#include <asm/sbi.h> | |
| 10 | 13 | #include <asm/smp.h> |
| 11 | 14 | #include <asm/pgtable.h> |
| 12 | 15 | |
| @@ -68,6 +71,50 @@ int riscv_of_parent_hartid(struct device_node *node, unsigned long *hartid) · 55 unmodified lines | ||
| 68 | 71 | } |
| 69 | 72 | |
| 70 | 73 | #ifdef CONFIG_PROC_FS |
| 74 | + | |
| 75 | +struct riscv_cpuinfo { | |
| 76 | + unsigned long mvendorid; | |
| 77 | + unsigned long marchid; | |
| 78 | + unsigned long mimpid; | |
| 79 | +}; | |
| 80 | +static DEFINE_PER_CPU(struct riscv_cpuinfo, riscv_cpuinfo); | |
| 81 | + | |
| 82 | +static int riscv_cpuinfo_starting(unsigned int cpu) | |
| 83 | +{ | |
| 84 | + struct riscv_cpuinfo *ci = this_cpu_ptr(&riscv_cpuinfo); | |
| 85 | + | |
| 86 | +#if IS_ENABLED(CONFIG_RISCV_SBI) | |
| 87 | + ci->mvendorid = sbi_spec_is_0_1() ? 0 : sbi_get_mvendorid(); | |
| 88 | + ci->marchid = sbi_spec_is_0_1() ? 0 : sbi_get_marchid(); | |
| 89 | + ci->mimpid = sbi_spec_is_0_1() ? 0 : sbi_get_mimpid(); | |
| 90 | +#elif IS_ENABLED(CONFIG_RISCV_M_MODE) | |
| 91 | + ci->mvendorid = csr_read(CSR_MVENDORID); | |
| 92 | + ci->marchid = csr_read(CSR_MARCHID); | |
| 93 | + ci->mimpid = csr_read(CSR_MIMPID); | |
| 94 | +#else | |
| 95 | + ci->mvendorid = 0; | |
| 96 | + ci->marchid = 0; | |
| 97 | + ci->mimpid = 0; | |
| 98 | +#endif | |
| 99 | + | |
| 100 | + return 0; | |
| 101 | +} | |
| 102 | + | |
| 103 | +static int __init riscv_cpuinfo_init(void) | |
| 104 | +{ | |
| 105 | + int ret; | |
| 106 | + | |
| 107 | + ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "riscv/cpuinfo:starting", | |
| 108 | + riscv_cpuinfo_starting, NULL); | |
| 109 | + if (ret < 0) { | |
| 110 | + pr_err("cpuinfo: failed to register hotplug callbacks.\n"); | |
| 111 | + return ret; | |
| 112 | + } | |
| 113 | + | |
| 114 | + return 0; | |
| 115 | +} | |
| 116 | +device_initcall(riscv_cpuinfo_init); | |
| 117 | + | |
| 71 | 118 | #define __RISCV_ISA_EXT_DATA(UPROP, EXTID) \ |
| 72 | 119 | { \ |
| 73 | 120 | .uprop = #UPROP, \ |
| @@ -186,6 +233,7 @@ static int c_show(struct seq_file *m, void *v) · 112 unmodified lines | ||
| 186 | 233 | { |
| 187 | 234 | unsigned long cpu_id = (unsigned long)v - 1; |
| 188 | 235 | struct device_node *node = of_get_cpu_node(cpu_id, NULL); |
| 236 | + struct riscv_cpuinfo *ci = per_cpu_ptr(&riscv_cpuinfo, cpu_id); | |
| 189 | 237 | const char *compat, *isa; |
| 190 | 238 | |
| 191 | 239 | seq_printf(m, "processor\t: %lu\n", cpu_id); |
| @@ -196,6 +244,9 @@ static int c_show(struct seq_file *m, void *v) · 4 unmodified lines | ||
| 196 | 244 | if (!of_property_read_string(node, "compatible", &compat) |
| 197 | 245 | && strcmp(compat, "riscv")) |
| 198 | 246 | seq_printf(m, "uarch\t\t: %s\n", compat); |
| 247 | + seq_printf(m, "mvendorid\t: 0x%lx\n", ci->mvendorid); | |
| 248 | + seq_printf(m, "marchid\t\t: 0x%lx\n", ci->marchid); | |
| 249 | + seq_printf(m, "mimpid\t\t: 0x%lx\n", ci->mimpid); | |
| 199 | 250 | seq_puts(m, "\n"); |
| 200 | 251 | of_node_put(node); |
| 201 | 252 | |
| @@ -254,35 +254,28 @@ void __init riscv_fill_hwcap(void) · 253 unmodified lines | ||
| 254 | 254 | #ifdef CONFIG_RISCV_ALTERNATIVE |
| 255 | 255 | static bool __init_or_module cpufeature_probe_svpbmt(unsigned int stage) |
| 256 | 256 | { |
| 257 | −#ifdef CONFIG_RISCV_ISA_SVPBMT | |
| 258 | − switch (stage) { | |
| 259 | − case RISCV_ALTERNATIVES_EARLY_BOOT: | |
| 257 | + if (!IS_ENABLED(CONFIG_RISCV_ISA_SVPBMT)) | |
| 258 | + return false; | |
| 259 | + | |
| 260 | + if (stage == RISCV_ALTERNATIVES_EARLY_BOOT) | |
| 260 | 261 | return false; |
| 261 | − default: | |
| 262 | − return riscv_isa_extension_available(NULL, SVPBMT); | |
| 263 | − } | |
| 264 | −#endif | |
| 265 | 262 | |
| 266 | − return false; | |
| 263 | + return riscv_isa_extension_available(NULL, SVPBMT); | |
| 267 | 264 | } |
| 268 | 265 | |
| 269 | 266 | static bool __init_or_module cpufeature_probe_zicbom(unsigned int stage) |
| 270 | 267 | { |
| 271 | −#ifdef CONFIG_RISCV_ISA_ZICBOM | |
| 272 | − switch (stage) { | |
| 273 | − case RISCV_ALTERNATIVES_EARLY_BOOT: | |
| 268 | + if (!IS_ENABLED(CONFIG_RISCV_ISA_ZICBOM)) | |
| 269 | + return false; | |
| 270 | + | |
| 271 | + if (stage == RISCV_ALTERNATIVES_EARLY_BOOT) | |
| 272 | + return false; | |
| 273 | + | |
| 274 | + if (!riscv_isa_extension_available(NULL, ZICBOM)) | |
| 274 | 275 | return false; |
| 275 | − default: | |
| 276 | − if (riscv_isa_extension_available(NULL, ZICBOM)) { | |
| 277 | − riscv_noncoherent_supported(); | |
| 278 | − return true; | |
| 279 | − } else { | |
| 280 | − return false; | |
| 281 | − } | |
| 282 | − } | |
| 283 | −#endif | |
| 284 | 276 | |
| 285 | − return false; | |
| 277 | + riscv_noncoherent_supported(); | |
| 278 | + return true; | |
| 286 | 279 | } |
| 287 | 280 | |
| 288 | 281 | /* |
| @@ -297,10 +290,10 @@ static u32 __init_or_module cpufeature_probe(unsigned int stage) · 8 unmodified lines | ||
| 297 | 290 | u32 cpu_req_feature = 0; |
| 298 | 291 | |
| 299 | 292 | if (cpufeature_probe_svpbmt(stage)) |
| 300 | − cpu_req_feature |= (1U << CPUFEATURE_SVPBMT); | |
| 293 | + cpu_req_feature |= BIT(CPUFEATURE_SVPBMT); | |
| 301 | 294 | |
| 302 | 295 | if (cpufeature_probe_zicbom(stage)) |
| 303 | − cpu_req_feature |= (1U << CPUFEATURE_ZICBOM); | |
| 296 | + cpu_req_feature |= BIT(CPUFEATURE_ZICBOM); | |
| 304 | 297 | |
| 305 | 298 | return cpu_req_feature; |
| 306 | 299 | } |
| @@ -252,10 +252,10 @@ static void __init parse_dtb(void) · 251 unmodified lines | ||
| 252 | 252 | pr_info("Machine model: %s\n", name); |
| 253 | 253 | dump_stack_set_arch_desc("%s (DT)", name); |
| 254 | 254 | } |
| 255 | − return; | |
| 255 | + } else { | |
| 256 | + pr_err("No DTB passed to the kernel\n"); | |
| 256 | 257 | } |
| 257 | 258 | |
| 258 | − pr_err("No DTB passed to the kernel\n"); | |
| 259 | 259 | #ifdef CONFIG_CMDLINE_FORCE |
| 260 | 260 | strscpy(boot_command_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE); |
| 261 | 261 | pr_info("Forcing kernel command line to: %s\n", boot_command_line); |
| @@ -18,9 +18,6 @@ static long riscv_sys_mmap(unsigned long addr, unsigned long len, · 17 unmodified lines | ||
| 18 | 18 | if (unlikely(offset & (~PAGE_MASK >> page_shift_offset))) |
| 19 | 19 | return -EINVAL; |
| 20 | 20 | |
| 21 | − if (unlikely((prot & PROT_WRITE) && !(prot & PROT_READ))) | |
| 22 | − return -EINVAL; | |
| 23 | − | |
| 24 | 21 | return ksys_mmap_pgoff(addr, len, prot, flags, fd, |
| 25 | 22 | offset >> (PAGE_SHIFT - page_shift_offset)); |
| 26 | 23 | } |
| @@ -33,6 +33,7 @@ void die(struct pt_regs *regs, const char *str) · 32 unmodified lines | ||
| 33 | 33 | { |
| 34 | 34 | static int die_counter; |
| 35 | 35 | int ret; |
| 36 | + long cause; | |
| 36 | 37 | |
| 37 | 38 | oops_enter(); |
| 38 | 39 | |
| @@ -42,11 +43,13 @@ void die(struct pt_regs *regs, const char *str) · 3 unmodified lines | ||
| 42 | 43 | |
| 43 | 44 | pr_emerg("%s [#%d]\n", str, ++die_counter); |
| 44 | 45 | print_modules(); |
| 45 | − show_regs(regs); | |
| 46 | + if (regs) | |
| 47 | + show_regs(regs); | |
| 46 | 48 | |
| 47 | − ret = notify_die(DIE_OOPS, str, regs, 0, regs->cause, SIGSEGV); | |
| 49 | + cause = regs ? regs->cause : -1; | |
| 50 | + ret = notify_die(DIE_OOPS, str, regs, 0, cause, SIGSEGV); | |
| 48 | 51 | |
| 49 | − if (regs && kexec_should_crash(current)) | |
| 52 | + if (kexec_should_crash(current)) | |
| 50 | 53 | crash_kexec(regs); |
| 51 | 54 | |
| 52 | 55 | bust_spinlocks(0); |
| @@ -60,6 +60,11 @@ struct __vdso_info { · 59 unmodified lines | ||
| 60 | 60 | struct vm_special_mapping *cm; |
| 61 | 61 | }; |
| 62 | 62 | |
| 63 | +static struct __vdso_info vdso_info; | |
| 64 | +#ifdef CONFIG_COMPAT | |
| 65 | +static struct __vdso_info compat_vdso_info; | |
| 66 | +#endif | |
| 67 | + | |
| 63 | 68 | static int vdso_mremap(const struct vm_special_mapping *sm, |
| 64 | 69 | struct vm_area_struct *new_vma) |
| 65 | 70 | { |
| @@ -115,15 +120,18 @@ int vdso_join_timens(struct task_struct *task, struct time_namespace *ns) · 49 unmodified lines | ||
| 115 | 120 | struct mm_struct *mm = task->mm; |
| 116 | 121 | struct vm_area_struct *vma; |
| 117 | 122 | VMA_ITERATOR(vmi, mm, 0); |
| 118 | − struct __vdso_info *vdso_info = mm->context.vdso_info; | |
| 119 | 123 | |
| 120 | 124 | mmap_read_lock(mm); |
| 121 | 125 | |
| 122 | 126 | for_each_vma(vmi, vma) { |
| 123 | 127 | unsigned long size = vma->vm_end - vma->vm_start; |
| 124 | 128 | |
| 125 | − if (vma_is_special_mapping(vma, vdso_info->dm)) | |
| 129 | + if (vma_is_special_mapping(vma, vdso_info.dm)) | |
| 126 | 130 | zap_page_range(vma, vma->vm_start, size); |
| 131 | +#ifdef CONFIG_COMPAT | |
| 132 | + if (vma_is_special_mapping(vma, compat_vdso_info.dm)) | |
| 133 | + zap_page_range(vma, vma->vm_start, size); | |
| 134 | +#endif | |
| 127 | 135 | } |
| 128 | 136 | |
| 129 | 137 | mmap_read_unlock(mm); |
| @@ -265,7 +273,6 @@ static int __setup_additional_pages(struct mm_struct *mm, · 135 unmodified lines | ||
| 265 | 273 | |
| 266 | 274 | vdso_base += VVAR_SIZE; |
| 267 | 275 | mm->context.vdso = (void *)vdso_base; |
| 268 | − mm->context.vdso_info = (void *)vdso_info; | |
| 269 | 276 | |
| 270 | 277 | ret = |
| 271 | 278 | _install_special_mapping(mm, vdso_base, vdso_text_len, |
| @@ -184,7 +184,8 @@ static inline bool access_error(unsigned long cause, struct vm_area_struct *vma) · 183 unmodified lines | ||
| 184 | 184 | } |
| 185 | 185 | break; |
| 186 | 186 | case EXC_LOAD_PAGE_FAULT: |
| 187 | − if (!(vma->vm_flags & VM_READ)) { | |
| 187 | + /* Write implies read */ | |
| 188 | + if (!(vma->vm_flags & (VM_READ | VM_WRITE))) { | |
| 188 | 189 | return true; |
| 189 | 190 | } |
| 190 | 191 | break; |
| @@ -473,7 +473,7 @@ config EDAC_ALTERA_SDMMC · 472 unmodified lines | ||
| 473 | 473 | |
| 474 | 474 | config EDAC_SIFIVE |
| 475 | 475 | bool "Sifive platform EDAC driver" |
| 476 | − depends on EDAC=y && SIFIVE_L2 | |
| 476 | + depends on EDAC=y && SIFIVE_CCACHE | |
| 477 | 477 | help |
| 478 | 478 | Support for error detection and correction on the SiFive SoCs. |
| 479 | 479 | |
| @@ -2,7 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | /* |
| 3 | 3 | * SiFive Platform EDAC Driver |
| 4 | 4 | * |
| 5 | − * Copyright (C) 2018-2019 SiFive, Inc. | |
| 5 | + * Copyright (C) 2018-2022 SiFive, Inc. | |
| 6 | 6 | * |
| 7 | 7 | * This driver is partially based on octeon_edac-pc.c |
| 8 | 8 | * |
| @@ -10,7 +10,7 @@ · 1 unmodified line | ||
| 10 | 10 | #include <linux/edac.h> |
| 11 | 11 | #include <linux/platform_device.h> |
| 12 | 12 | #include "edac_module.h" |
| 13 | −#include <soc/sifive/sifive_l2_cache.h> | |
| 13 | +#include <soc/sifive/sifive_ccache.h> | |
| 14 | 14 | |
| 15 | 15 | #define DRVNAME "sifive_edac" |
| 16 | 16 | |
| @@ -32,9 +32,9 @@ int ecc_err_event(struct notifier_block *this, unsigned long event, void *ptr) · 15 unmodified lines | ||
| 32 | 32 | |
| 33 | 33 | p = container_of(this, struct sifive_edac_priv, notifier); |
| 34 | 34 | |
| 35 | − if (event == SIFIVE_L2_ERR_TYPE_UE) | |
| 35 | + if (event == SIFIVE_CCACHE_ERR_TYPE_UE) | |
| 36 | 36 | edac_device_handle_ue(p->dci, 0, 0, msg); |
| 37 | − else if (event == SIFIVE_L2_ERR_TYPE_CE) | |
| 37 | + else if (event == SIFIVE_CCACHE_ERR_TYPE_CE) | |
| 38 | 38 | edac_device_handle_ce(p->dci, 0, 0, msg); |
| 39 | 39 | |
| 40 | 40 | return NOTIFY_OK; |
| @@ -67,7 +67,7 @@ static int ecc_register(struct platform_device *pdev) · 26 unmodified lines | ||
| 67 | 67 | goto err; |
| 68 | 68 | } |
| 69 | 69 | |
| 70 | − register_sifive_l2_error_notifier(&p->notifier); | |
| 70 | + register_sifive_ccache_error_notifier(&p->notifier); | |
| 71 | 71 | |
| 72 | 72 | return 0; |
| 73 | 73 | |
| @@ -81,7 +81,7 @@ static int ecc_unregister(struct platform_device *pdev) · 7 unmodified lines | ||
| 81 | 81 | { |
| 82 | 82 | struct sifive_edac_priv *p = platform_get_drvdata(pdev); |
| 83 | 83 | |
| 84 | − unregister_sifive_l2_error_notifier(&p->notifier); | |
| 84 | + unregister_sifive_ccache_error_notifier(&p->notifier); | |
| 85 | 85 | edac_device_del_device(&pdev->dev); |
| 86 | 86 | edac_device_free_ctl_info(p->dci); |
| 87 | 87 | |
| @@ -652,8 +652,11 @@ static int pmu_sbi_starting_cpu(unsigned int cpu, struct hlist_node *node) · 651 unmodified lines | ||
| 652 | 652 | struct riscv_pmu *pmu = hlist_entry_safe(node, struct riscv_pmu, node); |
| 653 | 653 | struct cpu_hw_events *cpu_hw_evt = this_cpu_ptr(pmu->hw_events); |
| 654 | 654 | |
| 655 | − /* Enable the access for TIME csr only from the user mode now */ | |
| 656 | − csr_write(CSR_SCOUNTEREN, 0x2); | |
| 655 | + /* | |
| 656 | + * Enable the access for CYCLE, TIME, and INSTRET CSRs from userspace, | |
| 657 | + * as is necessary to maintain uABI compatibility. | |
| 658 | + */ | |
| 659 | + csr_write(CSR_SCOUNTEREN, 0x7); | |
| 657 | 660 | |
| 658 | 661 | /* Stop all the counters so that they can be enabled from perf */ |
| 659 | 662 | pmu_sbi_stop_all(pmu); |
| @@ -2,9 +2,9 @@ · 1 unmodified line | ||
| 2 | 2 | |
| 3 | 3 | if SOC_SIFIVE |
| 4 | 4 | |
| 5 | −config SIFIVE_L2 | |
| 6 | − bool "Sifive L2 Cache controller" | |
| 5 | +config SIFIVE_CCACHE | |
| 6 | + bool "Sifive Composable Cache controller" | |
| 7 | 7 | help |
| 8 | − Support for the L2 cache controller on SiFive platforms. | |
| 8 | + Support for the composable cache controller on SiFive platforms. | |
| 9 | 9 | |
| 10 | 10 | endif |
| @@ -1,3 +1,3 @@ | ||
| 1 | 1 | # SPDX-License-Identifier: GPL-2.0 |
| 2 | 2 | |
| 3 | −obj-$(CONFIG_SIFIVE_L2) += sifive_l2_cache.o | |
| 3 | +obj-$(CONFIG_SIFIVE_CCACHE) += sifive_ccache.o | |
| @@ -0,0 +1,255 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0 | |
| 2 | +/* | |
| 3 | + * SiFive composable cache controller Driver | |
| 4 | + * | |
| 5 | + * Copyright (C) 2018-2022 SiFive, Inc. | |
| 6 | + * | |
| 7 | + */ | |
| 8 | + | |
| 9 | +#define pr_fmt(fmt) "CCACHE: " fmt | |
| 10 | + | |
| 11 | +#include <linux/debugfs.h> | |
| 12 | +#include <linux/interrupt.h> | |
| 13 | +#include <linux/of_irq.h> | |
| 14 | +#include <linux/of_address.h> | |
| 15 | +#include <linux/device.h> | |
| 16 | +#include <linux/bitfield.h> | |
| 17 | +#include <asm/cacheinfo.h> | |
| 18 | +#include <soc/sifive/sifive_ccache.h> | |
| 19 | + | |
| 20 | +#define SIFIVE_CCACHE_DIRECCFIX_LOW 0x100 | |
| 21 | +#define SIFIVE_CCACHE_DIRECCFIX_HIGH 0x104 | |
| 22 | +#define SIFIVE_CCACHE_DIRECCFIX_COUNT 0x108 | |
| 23 | + | |
| 24 | +#define SIFIVE_CCACHE_DIRECCFAIL_LOW 0x120 | |
| 25 | +#define SIFIVE_CCACHE_DIRECCFAIL_HIGH 0x124 | |
| 26 | +#define SIFIVE_CCACHE_DIRECCFAIL_COUNT 0x128 | |
| 27 | + | |
| 28 | +#define SIFIVE_CCACHE_DATECCFIX_LOW 0x140 | |
| 29 | +#define SIFIVE_CCACHE_DATECCFIX_HIGH 0x144 | |
| 30 | +#define SIFIVE_CCACHE_DATECCFIX_COUNT 0x148 | |
| 31 | + | |
| 32 | +#define SIFIVE_CCACHE_DATECCFAIL_LOW 0x160 | |
| 33 | +#define SIFIVE_CCACHE_DATECCFAIL_HIGH 0x164 | |
| 34 | +#define SIFIVE_CCACHE_DATECCFAIL_COUNT 0x168 | |
| 35 | + | |
| 36 | +#define SIFIVE_CCACHE_CONFIG 0x00 | |
| 37 | +#define SIFIVE_CCACHE_CONFIG_BANK_MASK GENMASK_ULL(7, 0) | |
| 38 | +#define SIFIVE_CCACHE_CONFIG_WAYS_MASK GENMASK_ULL(15, 8) | |
| 39 | +#define SIFIVE_CCACHE_CONFIG_SETS_MASK GENMASK_ULL(23, 16) | |
| 40 | +#define SIFIVE_CCACHE_CONFIG_BLKS_MASK GENMASK_ULL(31, 24) | |
| 41 | + | |
| 42 | +#define SIFIVE_CCACHE_WAYENABLE 0x08 | |
| 43 | +#define SIFIVE_CCACHE_ECCINJECTERR 0x40 | |
| 44 | + | |
| 45 | +#define SIFIVE_CCACHE_MAX_ECCINTR 4 | |
| 46 | + | |
| 47 | +static void __iomem *ccache_base; | |
| 48 | +static int g_irq[SIFIVE_CCACHE_MAX_ECCINTR]; | |
| 49 | +static struct riscv_cacheinfo_ops ccache_cache_ops; | |
| 50 | +static int level; | |
| 51 | + | |
| 52 | +enum { | |
| 53 | + DIR_CORR = 0, | |
| 54 | + DATA_CORR, | |
| 55 | + DATA_UNCORR, | |
| 56 | + DIR_UNCORR, | |
| 57 | +}; | |
| 58 | + | |
| 59 | +#ifdef CONFIG_DEBUG_FS | |
| 60 | +static struct dentry *sifive_test; | |
| 61 | + | |
| 62 | +static ssize_t ccache_write(struct file *file, const char __user *data, | |
| 63 | + size_t count, loff_t *ppos) | |
| 64 | +{ | |
| 65 | + unsigned int val; | |
| 66 | + | |
| 67 | + if (kstrtouint_from_user(data, count, 0, &val)) | |
| 68 | + return -EINVAL; | |
| 69 | + if ((val < 0xFF) || (val >= 0x10000 && val < 0x100FF)) | |
| 70 | + writel(val, ccache_base + SIFIVE_CCACHE_ECCINJECTERR); | |
| 71 | + else | |
| 72 | + return -EINVAL; | |
| 73 | + return count; | |
| 74 | +} | |
| 75 | + | |
| 76 | +static const struct file_operations ccache_fops = { | |
| 77 | + .owner = THIS_MODULE, | |
| 78 | + .open = simple_open, | |
| 79 | + .write = ccache_write | |
| 80 | +}; | |
| 81 | + | |
| 82 | +static void setup_sifive_debug(void) | |
| 83 | +{ | |
| 84 | + sifive_test = debugfs_create_dir("sifive_ccache_cache", NULL); | |
| 85 | + | |
| 86 | + debugfs_create_file("sifive_debug_inject_error", 0200, | |
| 87 | + sifive_test, NULL, &ccache_fops); | |
| 88 | +} | |
| 89 | +#endif | |
| 90 | + | |
| 91 | +static void ccache_config_read(void) | |
| 92 | +{ | |
| 93 | + u32 cfg; | |
| 94 | + | |
| 95 | + cfg = readl(ccache_base + SIFIVE_CCACHE_CONFIG); | |
| 96 | + pr_info("%llu banks, %llu ways, sets/bank=%llu, bytes/block=%llu\n", | |
| 97 | + FIELD_GET(SIFIVE_CCACHE_CONFIG_BANK_MASK, cfg), | |
| 98 | + FIELD_GET(SIFIVE_CCACHE_CONFIG_WAYS_MASK, cfg), | |
| 99 | + BIT_ULL(FIELD_GET(SIFIVE_CCACHE_CONFIG_SETS_MASK, cfg)), | |
| 100 | + BIT_ULL(FIELD_GET(SIFIVE_CCACHE_CONFIG_BLKS_MASK, cfg))); | |
| 101 | + | |
| 102 | + cfg = readl(ccache_base + SIFIVE_CCACHE_WAYENABLE); | |
| 103 | + pr_info("Index of the largest way enabled: %u\n", cfg); | |
| 104 | +} | |
| 105 | + | |
| 106 | +static const struct of_device_id sifive_ccache_ids[] = { | |
| 107 | + { .compatible = "sifive,fu540-c000-ccache" }, | |
| 108 | + { .compatible = "sifive,fu740-c000-ccache" }, | |
| 109 | + { .compatible = "sifive,ccache0" }, | |
| 110 | + { /* end of table */ } | |
| 111 | +}; | |
| 112 | + | |
| 113 | +static ATOMIC_NOTIFIER_HEAD(ccache_err_chain); | |
| 114 | + | |
| 115 | +int register_sifive_ccache_error_notifier(struct notifier_block *nb) | |
| 116 | +{ | |
| 117 | + return atomic_notifier_chain_register(&ccache_err_chain, nb); | |
| 118 | +} | |
| 119 | +EXPORT_SYMBOL_GPL(register_sifive_ccache_error_notifier); | |
| 120 | + | |
| 121 | +int unregister_sifive_ccache_error_notifier(struct notifier_block *nb) | |
| 122 | +{ | |
| 123 | + return atomic_notifier_chain_unregister(&ccache_err_chain, nb); | |
| 124 | +} | |
| 125 | +EXPORT_SYMBOL_GPL(unregister_sifive_ccache_error_notifier); | |
| 126 | + | |
| 127 | +static int ccache_largest_wayenabled(void) | |
| 128 | +{ | |
| 129 | + return readl(ccache_base + SIFIVE_CCACHE_WAYENABLE) & 0xFF; | |
| 130 | +} | |
| 131 | + | |
| 132 | +static ssize_t number_of_ways_enabled_show(struct device *dev, | |
| 133 | + struct device_attribute *attr, | |
| 134 | + char *buf) | |
| 135 | +{ | |
| 136 | + return sprintf(buf, "%u\n", ccache_largest_wayenabled()); | |
| 137 | +} | |
| 138 | + | |
| 139 | +static DEVICE_ATTR_RO(number_of_ways_enabled); | |
| 140 | + | |
| 141 | +static struct attribute *priv_attrs[] = { | |
| 142 | + &dev_attr_number_of_ways_enabled.attr, | |
| 143 | + NULL, | |
| 144 | +}; | |
| 145 | + | |
| 146 | +static const struct attribute_group priv_attr_group = { | |
| 147 | + .attrs = priv_attrs, | |
| 148 | +}; | |
| 149 | + | |
| 150 | +static const struct attribute_group *ccache_get_priv_group(struct cacheinfo | |
| 151 | + *this_leaf) | |
| 152 | +{ | |
| 153 | + /* We want to use private group for composable cache only */ | |
| 154 | + if (this_leaf->level == level) | |
| 155 | + return &priv_attr_group; | |
| 156 | + else | |
| 157 | + return NULL; | |
| 158 | +} | |
| 159 | + | |
| 160 | +static irqreturn_t ccache_int_handler(int irq, void *device) | |
| 161 | +{ | |
| 162 | + unsigned int add_h, add_l; | |
| 163 | + | |
| 164 | + if (irq == g_irq[DIR_CORR]) { | |
| 165 | + add_h = readl(ccache_base + SIFIVE_CCACHE_DIRECCFIX_HIGH); | |
| 166 | + add_l = readl(ccache_base + SIFIVE_CCACHE_DIRECCFIX_LOW); | |
| 167 | + pr_err("DirError @ 0x%08X.%08X\n", add_h, add_l); | |
| 168 | + /* Reading this register clears the DirError interrupt sig */ | |
| 169 | + readl(ccache_base + SIFIVE_CCACHE_DIRECCFIX_COUNT); | |
| 170 | + atomic_notifier_call_chain(&ccache_err_chain, | |
| 171 | + SIFIVE_CCACHE_ERR_TYPE_CE, | |
| 172 | + "DirECCFix"); | |
| 173 | + } | |
| 174 | + if (irq == g_irq[DIR_UNCORR]) { | |
| 175 | + add_h = readl(ccache_base + SIFIVE_CCACHE_DIRECCFAIL_HIGH); | |
| 176 | + add_l = readl(ccache_base + SIFIVE_CCACHE_DIRECCFAIL_LOW); | |
| 177 | + /* Reading this register clears the DirFail interrupt sig */ | |
| 178 | + readl(ccache_base + SIFIVE_CCACHE_DIRECCFAIL_COUNT); | |
| 179 | + atomic_notifier_call_chain(&ccache_err_chain, | |
| 180 | + SIFIVE_CCACHE_ERR_TYPE_UE, | |
| 181 | + "DirECCFail"); | |
| 182 | + panic("CCACHE: DirFail @ 0x%08X.%08X\n", add_h, add_l); | |
| 183 | + } | |
| 184 | + if (irq == g_irq[DATA_CORR]) { | |
| 185 | + add_h = readl(ccache_base + SIFIVE_CCACHE_DATECCFIX_HIGH); | |
| 186 | + add_l = readl(ccache_base + SIFIVE_CCACHE_DATECCFIX_LOW); | |
| 187 | + pr_err("DataError @ 0x%08X.%08X\n", add_h, add_l); | |
| 188 | + /* Reading this register clears the DataError interrupt sig */ | |
| 189 | + readl(ccache_base + SIFIVE_CCACHE_DATECCFIX_COUNT); | |
| 190 | + atomic_notifier_call_chain(&ccache_err_chain, | |
| 191 | + SIFIVE_CCACHE_ERR_TYPE_CE, | |
| 192 | + "DatECCFix"); | |
| 193 | + } | |
| 194 | + if (irq == g_irq[DATA_UNCORR]) { | |
| 195 | + add_h = readl(ccache_base + SIFIVE_CCACHE_DATECCFAIL_HIGH); | |
| 196 | + add_l = readl(ccache_base + SIFIVE_CCACHE_DATECCFAIL_LOW); | |
| 197 | + pr_err("DataFail @ 0x%08X.%08X\n", add_h, add_l); | |
| 198 | + /* Reading this register clears the DataFail interrupt sig */ | |
| 199 | + readl(ccache_base + SIFIVE_CCACHE_DATECCFAIL_COUNT); | |
| 200 | + atomic_notifier_call_chain(&ccache_err_chain, | |
| 201 | + SIFIVE_CCACHE_ERR_TYPE_UE, | |
| 202 | + "DatECCFail"); | |
| 203 | + } | |
| 204 | + | |
| 205 | + return IRQ_HANDLED; | |
| 206 | +} | |
| 207 | + | |
| 208 | +static int __init sifive_ccache_init(void) | |
| 209 | +{ | |
| 210 | + struct device_node *np; | |
| 211 | + struct resource res; | |
| 212 | + int i, rc, intr_num; | |
| 213 | + | |
| 214 | + np = of_find_matching_node(NULL, sifive_ccache_ids); | |
| 215 | + if (!np) | |
| 216 | + return -ENODEV; | |
| 217 | + | |
| 218 | + if (of_address_to_resource(np, 0, &res)) | |
| 219 | + return -ENODEV; | |
| 220 | + | |
| 221 | + ccache_base = ioremap(res.start, resource_size(&res)); | |
| 222 | + if (!ccache_base) | |
| 223 | + return -ENOMEM; | |
| 224 | + | |
| 225 | + if (of_property_read_u32(np, "cache-level", &level)) | |
| 226 | + return -ENOENT; | |
| 227 | + | |
| 228 | + intr_num = of_property_count_u32_elems(np, "interrupts"); | |
| 229 | + if (!intr_num) { | |
| 230 | + pr_err("No interrupts property\n"); | |
| 231 | + return -ENODEV; | |
| 232 | + } | |
| 233 | + | |
| 234 | + for (i = 0; i < intr_num; i++) { | |
| 235 | + g_irq[i] = irq_of_parse_and_map(np, i); | |
| 236 | + rc = request_irq(g_irq[i], ccache_int_handler, 0, "ccache_ecc", | |
| 237 | + NULL); | |
| 238 | + if (rc) { | |
| 239 | + pr_err("Could not request IRQ %d\n", g_irq[i]); | |
| 240 | + return rc; | |
| 241 | + } | |
| 242 | + } | |
| 243 | + | |
| 244 | + ccache_config_read(); | |
| 245 | + | |
| 246 | + ccache_cache_ops.get_priv_group = ccache_get_priv_group; | |
| 247 | + riscv_set_cacheinfo_ops(&ccache_cache_ops); | |
| 248 | + | |
| 249 | +#ifdef CONFIG_DEBUG_FS | |
| 250 | + setup_sifive_debug(); | |
| 251 | +#endif | |
| 252 | + return 0; | |
| 253 | +} | |
| 254 | + | |
| 255 | +device_initcall(sifive_ccache_init); | |
| @@ -1,237 +0,0 @@ | ||
| 1 | −// SPDX-License-Identifier: GPL-2.0 | |
| 2 | −/* | |
| 3 | − * SiFive L2 cache controller Driver | |
| 4 | − * | |
| 5 | − * Copyright (C) 2018-2019 SiFive, Inc. | |
| 6 | − * | |
| 7 | − */ | |
| 8 | −#include <linux/debugfs.h> | |
| 9 | −#include <linux/interrupt.h> | |
| 10 | −#include <linux/of_irq.h> | |
| 11 | −#include <linux/of_address.h> | |
| 12 | −#include <linux/device.h> | |
| 13 | −#include <asm/cacheinfo.h> | |
| 14 | −#include <soc/sifive/sifive_l2_cache.h> | |
| 15 | − | |
| 16 | −#define SIFIVE_L2_DIRECCFIX_LOW 0x100 | |
| 17 | −#define SIFIVE_L2_DIRECCFIX_HIGH 0x104 | |
| 18 | −#define SIFIVE_L2_DIRECCFIX_COUNT 0x108 | |
| 19 | − | |
| 20 | −#define SIFIVE_L2_DIRECCFAIL_LOW 0x120 | |
| 21 | −#define SIFIVE_L2_DIRECCFAIL_HIGH 0x124 | |
| 22 | −#define SIFIVE_L2_DIRECCFAIL_COUNT 0x128 | |
| 23 | − | |
| 24 | −#define SIFIVE_L2_DATECCFIX_LOW 0x140 | |
| 25 | −#define SIFIVE_L2_DATECCFIX_HIGH 0x144 | |
| 26 | −#define SIFIVE_L2_DATECCFIX_COUNT 0x148 | |
| 27 | − | |
| 28 | −#define SIFIVE_L2_DATECCFAIL_LOW 0x160 | |
| 29 | −#define SIFIVE_L2_DATECCFAIL_HIGH 0x164 | |
| 30 | −#define SIFIVE_L2_DATECCFAIL_COUNT 0x168 | |
| 31 | − | |
| 32 | −#define SIFIVE_L2_CONFIG 0x00 | |
| 33 | −#define SIFIVE_L2_WAYENABLE 0x08 | |
| 34 | −#define SIFIVE_L2_ECCINJECTERR 0x40 | |
| 35 | − | |
| 36 | −#define SIFIVE_L2_MAX_ECCINTR 4 | |
| 37 | − | |
| 38 | −static void __iomem *l2_base; | |
| 39 | −static int g_irq[SIFIVE_L2_MAX_ECCINTR]; | |
| 40 | −static struct riscv_cacheinfo_ops l2_cache_ops; | |
| 41 | − | |
| 42 | −enum { | |
| 43 | − DIR_CORR = 0, | |
| 44 | − DATA_CORR, | |
| 45 | − DATA_UNCORR, | |
| 46 | − DIR_UNCORR, | |
| 47 | −}; | |
| 48 | − | |
| 49 | −#ifdef CONFIG_DEBUG_FS | |
| 50 | −static struct dentry *sifive_test; | |
| 51 | − | |
| 52 | −static ssize_t l2_write(struct file *file, const char __user *data, | |
| 53 | − size_t count, loff_t *ppos) | |
| 54 | −{ | |
| 55 | − unsigned int val; | |
| 56 | − | |
| 57 | − if (kstrtouint_from_user(data, count, 0, &val)) | |
| 58 | − return -EINVAL; | |
| 59 | − if ((val < 0xFF) || (val >= 0x10000 && val < 0x100FF)) | |
| 60 | − writel(val, l2_base + SIFIVE_L2_ECCINJECTERR); | |
| 61 | − else | |
| 62 | − return -EINVAL; | |
| 63 | − return count; | |
| 64 | −} | |
| 65 | − | |
| 66 | −static const struct file_operations l2_fops = { | |
| 67 | − .owner = THIS_MODULE, | |
| 68 | − .open = simple_open, | |
| 69 | − .write = l2_write | |
| 70 | −}; | |
| 71 | − | |
| 72 | −static void setup_sifive_debug(void) | |
| 73 | −{ | |
| 74 | − sifive_test = debugfs_create_dir("sifive_l2_cache", NULL); | |
| 75 | − | |
| 76 | − debugfs_create_file("sifive_debug_inject_error", 0200, | |
| 77 | − sifive_test, NULL, &l2_fops); | |
| 78 | −} | |
| 79 | −#endif | |
| 80 | − | |
| 81 | −static void l2_config_read(void) | |
| 82 | −{ | |
| 83 | − u32 regval, val; | |
| 84 | − | |
| 85 | − regval = readl(l2_base + SIFIVE_L2_CONFIG); | |
| 86 | − val = regval & 0xFF; | |
| 87 | − pr_info("L2CACHE: No. of Banks in the cache: %d\n", val); | |
| 88 | − val = (regval & 0xFF00) >> 8; | |
| 89 | − pr_info("L2CACHE: No. of ways per bank: %d\n", val); | |
| 90 | − val = (regval & 0xFF0000) >> 16; | |
| 91 | − pr_info("L2CACHE: Sets per bank: %llu\n", (uint64_t)1 << val); | |
| 92 | − val = (regval & 0xFF000000) >> 24; | |
| 93 | − pr_info("L2CACHE: Bytes per cache block: %llu\n", (uint64_t)1 << val); | |
| 94 | − | |
| 95 | − regval = readl(l2_base + SIFIVE_L2_WAYENABLE); | |
| 96 | − pr_info("L2CACHE: Index of the largest way enabled: %d\n", regval); | |
| 97 | −} | |
| 98 | − | |
| 99 | −static const struct of_device_id sifive_l2_ids[] = { | |
| 100 | − { .compatible = "sifive,fu540-c000-ccache" }, | |
| 101 | − { .compatible = "sifive,fu740-c000-ccache" }, | |
| 102 | − { /* end of table */ }, | |
| 103 | −}; | |
| 104 | − | |
| 105 | −static ATOMIC_NOTIFIER_HEAD(l2_err_chain); | |
| 106 | − | |
| 107 | −int register_sifive_l2_error_notifier(struct notifier_block *nb) | |
| 108 | −{ | |
| 109 | − return atomic_notifier_chain_register(&l2_err_chain, nb); | |
| 110 | −} | |
| 111 | −EXPORT_SYMBOL_GPL(register_sifive_l2_error_notifier); | |
| 112 | − | |
| 113 | −int unregister_sifive_l2_error_notifier(struct notifier_block *nb) | |
| 114 | −{ | |
| 115 | − return atomic_notifier_chain_unregister(&l2_err_chain, nb); | |
| 116 | −} | |
| 117 | −EXPORT_SYMBOL_GPL(unregister_sifive_l2_error_notifier); | |
| 118 | − | |
| 119 | −static int l2_largest_wayenabled(void) | |
| 120 | −{ | |
| 121 | − return readl(l2_base + SIFIVE_L2_WAYENABLE) & 0xFF; | |
| 122 | −} | |
| 123 | − | |
| 124 | −static ssize_t number_of_ways_enabled_show(struct device *dev, | |
| 125 | − struct device_attribute *attr, | |
| 126 | − char *buf) | |
| 127 | −{ | |
| 128 | − return sprintf(buf, "%u\n", l2_largest_wayenabled()); | |
| 129 | −} | |
| 130 | − | |
| 131 | −static DEVICE_ATTR_RO(number_of_ways_enabled); | |
| 132 | − | |
| 133 | −static struct attribute *priv_attrs[] = { | |
| 134 | − &dev_attr_number_of_ways_enabled.attr, | |
| 135 | − NULL, | |
| 136 | −}; | |
| 137 | − | |
| 138 | −static const struct attribute_group priv_attr_group = { | |
| 139 | − .attrs = priv_attrs, | |
| 140 | −}; | |
| 141 | − | |
| 142 | −static const struct attribute_group *l2_get_priv_group(struct cacheinfo *this_leaf) | |
| 143 | −{ | |
| 144 | − /* We want to use private group for L2 cache only */ | |
| 145 | − if (this_leaf->level == 2) | |
| 146 | − return &priv_attr_group; | |
| 147 | − else | |
| 148 | − return NULL; | |
| 149 | −} | |
| 150 | − | |
| 151 | −static irqreturn_t l2_int_handler(int irq, void *device) | |
| 152 | −{ | |
| 153 | − unsigned int add_h, add_l; | |
| 154 | − | |
| 155 | − if (irq == g_irq[DIR_CORR]) { | |
| 156 | − add_h = readl(l2_base + SIFIVE_L2_DIRECCFIX_HIGH); | |
| 157 | − add_l = readl(l2_base + SIFIVE_L2_DIRECCFIX_LOW); | |
| 158 | − pr_err("L2CACHE: DirError @ 0x%08X.%08X\n", add_h, add_l); | |
| 159 | − /* Reading this register clears the DirError interrupt sig */ | |
| 160 | − readl(l2_base + SIFIVE_L2_DIRECCFIX_COUNT); | |
| 161 | − atomic_notifier_call_chain(&l2_err_chain, SIFIVE_L2_ERR_TYPE_CE, | |
| 162 | − "DirECCFix"); | |
| 163 | − } | |
| 164 | − if (irq == g_irq[DIR_UNCORR]) { | |
| 165 | − add_h = readl(l2_base + SIFIVE_L2_DIRECCFAIL_HIGH); | |
| 166 | − add_l = readl(l2_base + SIFIVE_L2_DIRECCFAIL_LOW); | |
| 167 | − /* Reading this register clears the DirFail interrupt sig */ | |
| 168 | − readl(l2_base + SIFIVE_L2_DIRECCFAIL_COUNT); | |
| 169 | − atomic_notifier_call_chain(&l2_err_chain, SIFIVE_L2_ERR_TYPE_UE, | |
| 170 | − "DirECCFail"); | |
| 171 | − panic("L2CACHE: DirFail @ 0x%08X.%08X\n", add_h, add_l); | |
| 172 | − } | |
| 173 | − if (irq == g_irq[DATA_CORR]) { | |
| 174 | − add_h = readl(l2_base + SIFIVE_L2_DATECCFIX_HIGH); | |
| 175 | − add_l = readl(l2_base + SIFIVE_L2_DATECCFIX_LOW); | |
| 176 | − pr_err("L2CACHE: DataError @ 0x%08X.%08X\n", add_h, add_l); | |
| 177 | − /* Reading this register clears the DataError interrupt sig */ | |
| 178 | − readl(l2_base + SIFIVE_L2_DATECCFIX_COUNT); | |
| 179 | − atomic_notifier_call_chain(&l2_err_chain, SIFIVE_L2_ERR_TYPE_CE, | |
| 180 | − "DatECCFix"); | |
| 181 | − } | |
| 182 | − if (irq == g_irq[DATA_UNCORR]) { | |
| 183 | − add_h = readl(l2_base + SIFIVE_L2_DATECCFAIL_HIGH); | |
| 184 | − add_l = readl(l2_base + SIFIVE_L2_DATECCFAIL_LOW); | |
| 185 | − pr_err("L2CACHE: DataFail @ 0x%08X.%08X\n", add_h, add_l); | |
| 186 | − /* Reading this register clears the DataFail interrupt sig */ | |
| 187 | − readl(l2_base + SIFIVE_L2_DATECCFAIL_COUNT); | |
| 188 | − atomic_notifier_call_chain(&l2_err_chain, SIFIVE_L2_ERR_TYPE_UE, | |
| 189 | − "DatECCFail"); | |
| 190 | − } | |
| 191 | − | |
| 192 | − return IRQ_HANDLED; | |
| 193 | −} | |
| 194 | − | |
| 195 | −static int __init sifive_l2_init(void) | |
| 196 | −{ | |
| 197 | − struct device_node *np; | |
| 198 | − struct resource res; | |
| 199 | − int i, rc, intr_num; | |
| 200 | − | |
| 201 | − np = of_find_matching_node(NULL, sifive_l2_ids); | |
| 202 | − if (!np) | |
| 203 | − return -ENODEV; | |
| 204 | − | |
| 205 | − if (of_address_to_resource(np, 0, &res)) | |
| 206 | − return -ENODEV; | |
| 207 | − | |
| 208 | − l2_base = ioremap(res.start, resource_size(&res)); | |
| 209 | − if (!l2_base) | |
| 210 | − return -ENOMEM; | |
| 211 | − | |
| 212 | − intr_num = of_property_count_u32_elems(np, "interrupts"); | |
| 213 | − if (!intr_num) { | |
| 214 | − pr_err("L2CACHE: no interrupts property\n"); | |
| 215 | − return -ENODEV; | |
| 216 | − } | |
| 217 | − | |
| 218 | − for (i = 0; i < intr_num; i++) { | |
| 219 | − g_irq[i] = irq_of_parse_and_map(np, i); | |
| 220 | − rc = request_irq(g_irq[i], l2_int_handler, 0, "l2_ecc", NULL); | |
| 221 | − if (rc) { | |
| 222 | − pr_err("L2CACHE: Could not request IRQ %d\n", g_irq[i]); | |
| 223 | − return rc; | |
| 224 | − } | |
| 225 | − } | |
| 226 | − | |
| 227 | − l2_config_read(); | |
| 228 | − | |
| 229 | − l2_cache_ops.get_priv_group = l2_get_priv_group; | |
| 230 | − riscv_set_cacheinfo_ops(&l2_cache_ops); | |
| 231 | − | |
| 232 | −#ifdef CONFIG_DEBUG_FS | |
| 233 | − setup_sifive_debug(); | |
| 234 | −#endif | |
| 235 | − return 0; | |
| 236 | −} | |
| 237 | −device_initcall(sifive_l2_init); | |
| @@ -0,0 +1,16 @@ | ||
| 1 | +/* SPDX-License-Identifier: GPL-2.0 */ | |
| 2 | +/* | |
| 3 | + * SiFive Composable Cache Controller header file | |
| 4 | + * | |
| 5 | + */ | |
| 6 | + | |
| 7 | +#ifndef __SOC_SIFIVE_CCACHE_H | |
| 8 | +#define __SOC_SIFIVE_CCACHE_H | |
| 9 | + | |
| 10 | +extern int register_sifive_ccache_error_notifier(struct notifier_block *nb); | |
| 11 | +extern int unregister_sifive_ccache_error_notifier(struct notifier_block *nb); | |
| 12 | + | |
| 13 | +#define SIFIVE_CCACHE_ERR_TYPE_CE 0 | |
| 14 | +#define SIFIVE_CCACHE_ERR_TYPE_UE 1 | |
| 15 | + | |
| 16 | +#endif /* __SOC_SIFIVE_CCACHE_H */ | |
| @@ -1,16 +0,0 @@ | ||
| 1 | −/* SPDX-License-Identifier: GPL-2.0 */ | |
| 2 | −/* | |
| 3 | − * SiFive L2 Cache Controller header file | |
| 4 | − * | |
| 5 | − */ | |
| 6 | − | |
| 7 | −#ifndef __SOC_SIFIVE_L2_CACHE_H | |
| 8 | −#define __SOC_SIFIVE_L2_CACHE_H | |
| 9 | − | |
| 10 | −extern int register_sifive_l2_error_notifier(struct notifier_block *nb); | |
| 11 | −extern int unregister_sifive_l2_error_notifier(struct notifier_block *nb); | |
| 12 | − | |
| 13 | −#define SIFIVE_L2_ERR_TYPE_CE 0 | |
| 14 | −#define SIFIVE_L2_ERR_TYPE_UE 1 | |
| 15 | − | |
| 16 | −#endif /* __SOC_SIFIVE_L2_CACHE_H */ | |