diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-06 18:36:13 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-06 18:36:13 -0400 |
commit | 8450493076cd1dc8465db688f919708b5be17d46 (patch) | |
tree | 25ad03937122d537ed4fab125c0ed968cead7f43 | |
parent | 311da4975894aab7a4bb94aa83f38f052d7ffda4 (diff) | |
parent | eaa3a1d46cfdbf1af50311e7a22f5d38c0418b56 (diff) |
Merge tag 'edac_for_4.18' of git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp
Pull EDAC updates from Borislav Petkov:
- Stratix10 SDRAM support to altera_edac (Thor Thayer)
- the usual misc fixes all over the place
[ Also, shared branch for socfpga_stratix10.dtsi file changes with the
socfpga tree ]
* tag 'edac_for_4.18' of git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp:
EDAC, ghes: Make platform-based whitelisting x86-only
EDAC, altera: Fix ARM64 build warning
EDAC, skx: Fix skx_edac build error when ACPI_NFIT=m
EDAC, ghes: Use BIT() macro
EDAC, ghes: Add DDR4 and NVDIMM memory types
EDAC, altera: Handle SDRAM Uncorrectable Errors on Stratix10
Documentation: dt: edac: Move Altera SOCFPGA EDAC file
EDAC, altera: Add support for Stratix10 SDRAM EDAC
Documentation: dt: socfpga: Add Stratix10 ECC Manager binding
EDAC, ghes: Remove unused argument to ghes_edac_report_mem_error()
arm64: dts: stratix10: add sdram ecc
EDAC, i7core: Fix spelling mistake: "redundacy" -> "redundancy"
EDAC, ghes: Add a null pointer check in ghes_edac_unregister()
ghes, EDAC: Fix ghes_edac registration
arm64: dts: stratix10: Change pad skew values for EMAC0 PHY driver
ARM: dts: consistently use 'atmel' as at24 manufacturer in cyclone5
arm64: dts: stratix10: Add PL330 DMAC to Stratix10 dts
arm64: dts: stratix10: enable i2c, add i2c periperals
arm64: dts: stratix10: use clock bindings for the Stratix10 platform
-rw-r--r-- | Documentation/devicetree/bindings/edac/socfpga-eccmgr.txt (renamed from Documentation/devicetree/bindings/arm/altera/socfpga-eccmgr.txt) | 35 | ||||
-rw-r--r-- | arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts | 6 | ||||
-rw-r--r-- | arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi | 83 | ||||
-rw-r--r-- | arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts | 44 | ||||
-rw-r--r-- | drivers/acpi/apei/ghes.c | 16 | ||||
-rw-r--r-- | drivers/edac/Kconfig | 3 | ||||
-rw-r--r-- | drivers/edac/altera_edac.c | 504 | ||||
-rw-r--r-- | drivers/edac/altera_edac.h | 132 | ||||
-rw-r--r-- | drivers/edac/ghes_edac.c | 55 | ||||
-rw-r--r-- | drivers/edac/i7core_edac.c | 2 | ||||
-rw-r--r-- | include/acpi/ghes.h | 7 |
11 files changed, 817 insertions, 70 deletions
diff --git a/Documentation/devicetree/bindings/arm/altera/socfpga-eccmgr.txt b/Documentation/devicetree/bindings/edac/socfpga-eccmgr.txt index 4a1714f96bab..5626560a6cfd 100644 --- a/Documentation/devicetree/bindings/arm/altera/socfpga-eccmgr.txt +++ b/Documentation/devicetree/bindings/edac/socfpga-eccmgr.txt | |||
@@ -231,3 +231,38 @@ Example: | |||
231 | <48 IRQ_TYPE_LEVEL_HIGH>; | 231 | <48 IRQ_TYPE_LEVEL_HIGH>; |
232 | }; | 232 | }; |
233 | }; | 233 | }; |
234 | |||
235 | Stratix10 SoCFPGA ECC Manager | ||
236 | The Stratix10 SoC ECC Manager handles the IRQs for each peripheral | ||
237 | in a shared register similar to the Arria10. However, ECC requires | ||
238 | access to registers that can only be read from Secure Monitor with | ||
239 | SMC calls. Therefore the device tree is slightly different. | ||
240 | |||
241 | Required Properties: | ||
242 | - compatible : Should be "altr,socfpga-s10-ecc-manager" | ||
243 | - interrupts : Should be single bit error interrupt, then double bit error | ||
244 | interrupt. | ||
245 | - interrupt-controller : boolean indicator that ECC Manager is an interrupt controller | ||
246 | - #interrupt-cells : must be set to 2. | ||
247 | |||
248 | Subcomponents: | ||
249 | |||
250 | SDRAM ECC | ||
251 | Required Properties: | ||
252 | - compatible : Should be "altr,sdram-edac-s10" | ||
253 | - interrupts : Should be single bit error interrupt, then double bit error | ||
254 | interrupt, in this order. | ||
255 | |||
256 | Example: | ||
257 | |||
258 | eccmgr { | ||
259 | compatible = "altr,socfpga-s10-ecc-manager"; | ||
260 | interrupts = <0 15 4>, <0 95 4>; | ||
261 | interrupt-controller; | ||
262 | #interrupt-cells = <2>; | ||
263 | |||
264 | sdramedac { | ||
265 | compatible = "altr,sdram-edac-s10"; | ||
266 | interrupts = <16 4>, <48 4>; | ||
267 | }; | ||
268 | }; | ||
diff --git a/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts b/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts index 2459d133f1be..f50b19447de6 100644 --- a/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts +++ b/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts | |||
@@ -161,7 +161,7 @@ | |||
161 | }; | 161 | }; |
162 | 162 | ||
163 | at24@50 { | 163 | at24@50 { |
164 | compatible = "at24,24c01"; | 164 | compatible = "atmel,24c01"; |
165 | pagesize = <8>; | 165 | pagesize = <8>; |
166 | reg = <0x50>; | 166 | reg = <0x50>; |
167 | }; | 167 | }; |
@@ -213,7 +213,7 @@ | |||
213 | #size-cells = <0>; | 213 | #size-cells = <0>; |
214 | reg = <6>; | 214 | reg = <6>; |
215 | eeprom@51 { | 215 | eeprom@51 { |
216 | compatible = "at,24c01"; | 216 | compatible = "atmel,24c01"; |
217 | pagesize = <8>; | 217 | pagesize = <8>; |
218 | reg = <0x51>; | 218 | reg = <0x51>; |
219 | }; | 219 | }; |
@@ -224,7 +224,7 @@ | |||
224 | #size-cells = <0>; | 224 | #size-cells = <0>; |
225 | reg = <7>; | 225 | reg = <7>; |
226 | eeprom@51 { | 226 | eeprom@51 { |
227 | compatible = "at,24c01"; | 227 | compatible = "atmel,24c01"; |
228 | pagesize = <8>; | 228 | pagesize = <8>; |
229 | reg = <0x51>; | 229 | reg = <0x51>; |
230 | }; | 230 | }; |
diff --git a/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi b/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi index c89d0c307f8d..e6b059378dc0 100644 --- a/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi +++ b/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi | |||
@@ -17,6 +17,7 @@ | |||
17 | /dts-v1/; | 17 | /dts-v1/; |
18 | #include <dt-bindings/reset/altr,rst-mgr-s10.h> | 18 | #include <dt-bindings/reset/altr,rst-mgr-s10.h> |
19 | #include <dt-bindings/gpio/gpio.h> | 19 | #include <dt-bindings/gpio/gpio.h> |
20 | #include <dt-bindings/clock/stratix10-clock.h> | ||
20 | 21 | ||
21 | / { | 22 | / { |
22 | compatible = "altr,socfpga-stratix10"; | 23 | compatible = "altr,socfpga-stratix10"; |
@@ -92,9 +93,32 @@ | |||
92 | interrupt-parent = <&intc>; | 93 | interrupt-parent = <&intc>; |
93 | ranges = <0 0 0 0xffffffff>; | 94 | ranges = <0 0 0 0xffffffff>; |
94 | 95 | ||
95 | clkmgr@ffd1000 { | 96 | clkmgr: clock-controller@ffd10000 { |
96 | compatible = "altr,clk-mgr"; | 97 | compatible = "intel,stratix10-clkmgr"; |
97 | reg = <0xffd10000 0x1000>; | 98 | reg = <0xffd10000 0x1000>; |
99 | #clock-cells = <1>; | ||
100 | }; | ||
101 | |||
102 | clocks { | ||
103 | cb_intosc_hs_div2_clk: cb-intosc-hs-div2-clk { | ||
104 | #clock-cells = <0>; | ||
105 | compatible = "fixed-clock"; | ||
106 | }; | ||
107 | |||
108 | cb_intosc_ls_clk: cb-intosc-ls-clk { | ||
109 | #clock-cells = <0>; | ||
110 | compatible = "fixed-clock"; | ||
111 | }; | ||
112 | |||
113 | f2s_free_clk: f2s-free-clk { | ||
114 | #clock-cells = <0>; | ||
115 | compatible = "fixed-clock"; | ||
116 | }; | ||
117 | |||
118 | osc1: osc1 { | ||
119 | #clock-cells = <0>; | ||
120 | compatible = "fixed-clock"; | ||
121 | }; | ||
98 | }; | 122 | }; |
99 | 123 | ||
100 | gmac0: ethernet@ff800000 { | 124 | gmac0: ethernet@ff800000 { |
@@ -105,6 +129,8 @@ | |||
105 | mac-address = [00 00 00 00 00 00]; | 129 | mac-address = [00 00 00 00 00 00]; |
106 | resets = <&rst EMAC0_RESET>; | 130 | resets = <&rst EMAC0_RESET>; |
107 | reset-names = "stmmaceth"; | 131 | reset-names = "stmmaceth"; |
132 | clocks = <&clkmgr STRATIX10_EMAC0_CLK>; | ||
133 | clock-names = "stmmaceth"; | ||
108 | status = "disabled"; | 134 | status = "disabled"; |
109 | }; | 135 | }; |
110 | 136 | ||
@@ -116,6 +142,8 @@ | |||
116 | mac-address = [00 00 00 00 00 00]; | 142 | mac-address = [00 00 00 00 00 00]; |
117 | resets = <&rst EMAC1_RESET>; | 143 | resets = <&rst EMAC1_RESET>; |
118 | reset-names = "stmmaceth"; | 144 | reset-names = "stmmaceth"; |
145 | clocks = <&clkmgr STRATIX10_EMAC1_CLK>; | ||
146 | clock-names = "stmmaceth"; | ||
119 | status = "disabled"; | 147 | status = "disabled"; |
120 | }; | 148 | }; |
121 | 149 | ||
@@ -127,6 +155,8 @@ | |||
127 | mac-address = [00 00 00 00 00 00]; | 155 | mac-address = [00 00 00 00 00 00]; |
128 | resets = <&rst EMAC2_RESET>; | 156 | resets = <&rst EMAC2_RESET>; |
129 | reset-names = "stmmaceth"; | 157 | reset-names = "stmmaceth"; |
158 | clocks = <&clkmgr STRATIX10_EMAC2_CLK>; | ||
159 | clock-names = "stmmaceth"; | ||
130 | status = "disabled"; | 160 | status = "disabled"; |
131 | }; | 161 | }; |
132 | 162 | ||
@@ -177,6 +207,7 @@ | |||
177 | reg = <0xffc02800 0x100>; | 207 | reg = <0xffc02800 0x100>; |
178 | interrupts = <0 103 4>; | 208 | interrupts = <0 103 4>; |
179 | resets = <&rst I2C0_RESET>; | 209 | resets = <&rst I2C0_RESET>; |
210 | clocks = <&clkmgr STRATIX10_L4_SP_CLK>; | ||
180 | status = "disabled"; | 211 | status = "disabled"; |
181 | }; | 212 | }; |
182 | 213 | ||
@@ -187,6 +218,7 @@ | |||
187 | reg = <0xffc02900 0x100>; | 218 | reg = <0xffc02900 0x100>; |
188 | interrupts = <0 104 4>; | 219 | interrupts = <0 104 4>; |
189 | resets = <&rst I2C1_RESET>; | 220 | resets = <&rst I2C1_RESET>; |
221 | clocks = <&clkmgr STRATIX10_L4_SP_CLK>; | ||
190 | status = "disabled"; | 222 | status = "disabled"; |
191 | }; | 223 | }; |
192 | 224 | ||
@@ -197,6 +229,7 @@ | |||
197 | reg = <0xffc02a00 0x100>; | 229 | reg = <0xffc02a00 0x100>; |
198 | interrupts = <0 105 4>; | 230 | interrupts = <0 105 4>; |
199 | resets = <&rst I2C2_RESET>; | 231 | resets = <&rst I2C2_RESET>; |
232 | clocks = <&clkmgr STRATIX10_L4_SP_CLK>; | ||
200 | status = "disabled"; | 233 | status = "disabled"; |
201 | }; | 234 | }; |
202 | 235 | ||
@@ -207,6 +240,7 @@ | |||
207 | reg = <0xffc02b00 0x100>; | 240 | reg = <0xffc02b00 0x100>; |
208 | interrupts = <0 106 4>; | 241 | interrupts = <0 106 4>; |
209 | resets = <&rst I2C3_RESET>; | 242 | resets = <&rst I2C3_RESET>; |
243 | clocks = <&clkmgr STRATIX10_L4_SP_CLK>; | ||
210 | status = "disabled"; | 244 | status = "disabled"; |
211 | }; | 245 | }; |
212 | 246 | ||
@@ -217,6 +251,7 @@ | |||
217 | reg = <0xffc02c00 0x100>; | 251 | reg = <0xffc02c00 0x100>; |
218 | interrupts = <0 107 4>; | 252 | interrupts = <0 107 4>; |
219 | resets = <&rst I2C4_RESET>; | 253 | resets = <&rst I2C4_RESET>; |
254 | clocks = <&clkmgr STRATIX10_L4_SP_CLK>; | ||
220 | status = "disabled"; | 255 | status = "disabled"; |
221 | }; | 256 | }; |
222 | 257 | ||
@@ -229,6 +264,9 @@ | |||
229 | fifo-depth = <0x400>; | 264 | fifo-depth = <0x400>; |
230 | resets = <&rst SDMMC_RESET>; | 265 | resets = <&rst SDMMC_RESET>; |
231 | reset-names = "reset"; | 266 | reset-names = "reset"; |
267 | clocks = <&clkmgr STRATIX10_L4_MP_CLK>, | ||
268 | <&clkmgr STRATIX10_SDMMC_CLK>; | ||
269 | clock-names = "biu", "ciu"; | ||
232 | status = "disabled"; | 270 | status = "disabled"; |
233 | }; | 271 | }; |
234 | 272 | ||
@@ -237,6 +275,25 @@ | |||
237 | reg = <0xffe00000 0x100000>; | 275 | reg = <0xffe00000 0x100000>; |
238 | }; | 276 | }; |
239 | 277 | ||
278 | pdma: pdma@ffda0000 { | ||
279 | compatible = "arm,pl330", "arm,primecell"; | ||
280 | reg = <0xffda0000 0x1000>; | ||
281 | interrupts = <0 81 4>, | ||
282 | <0 82 4>, | ||
283 | <0 83 4>, | ||
284 | <0 84 4>, | ||
285 | <0 85 4>, | ||
286 | <0 86 4>, | ||
287 | <0 87 4>, | ||
288 | <0 88 4>, | ||
289 | <0 89 4>; | ||
290 | #dma-cells = <1>; | ||
291 | #dma-channels = <8>; | ||
292 | #dma-requests = <32>; | ||
293 | clocks = <&clkmgr STRATIX10_L4_MAIN_CLK>; | ||
294 | clock-names = "apb_pclk"; | ||
295 | }; | ||
296 | |||
240 | rst: rstmgr@ffd11000 { | 297 | rst: rstmgr@ffd11000 { |
241 | #reset-cells = <1>; | 298 | #reset-cells = <1>; |
242 | compatible = "altr,rst-mgr"; | 299 | compatible = "altr,rst-mgr"; |
@@ -288,24 +345,32 @@ | |||
288 | compatible = "snps,dw-apb-timer"; | 345 | compatible = "snps,dw-apb-timer"; |
289 | interrupts = <0 113 4>; | 346 | interrupts = <0 113 4>; |
290 | reg = <0xffc03000 0x100>; | 347 | reg = <0xffc03000 0x100>; |
348 | clocks = <&clkmgr STRATIX10_L4_SP_CLK>; | ||
349 | clock-names = "timer"; | ||
291 | }; | 350 | }; |
292 | 351 | ||
293 | timer1: timer1@ffc03100 { | 352 | timer1: timer1@ffc03100 { |
294 | compatible = "snps,dw-apb-timer"; | 353 | compatible = "snps,dw-apb-timer"; |
295 | interrupts = <0 114 4>; | 354 | interrupts = <0 114 4>; |
296 | reg = <0xffc03100 0x100>; | 355 | reg = <0xffc03100 0x100>; |
356 | clocks = <&clkmgr STRATIX10_L4_SP_CLK>; | ||
357 | clock-names = "timer"; | ||
297 | }; | 358 | }; |
298 | 359 | ||
299 | timer2: timer2@ffd00000 { | 360 | timer2: timer2@ffd00000 { |
300 | compatible = "snps,dw-apb-timer"; | 361 | compatible = "snps,dw-apb-timer"; |
301 | interrupts = <0 115 4>; | 362 | interrupts = <0 115 4>; |
302 | reg = <0xffd00000 0x100>; | 363 | reg = <0xffd00000 0x100>; |
364 | clocks = <&clkmgr STRATIX10_L4_SP_CLK>; | ||
365 | clock-names = "timer"; | ||
303 | }; | 366 | }; |
304 | 367 | ||
305 | timer3: timer3@ffd00100 { | 368 | timer3: timer3@ffd00100 { |
306 | compatible = "snps,dw-apb-timer"; | 369 | compatible = "snps,dw-apb-timer"; |
307 | interrupts = <0 116 4>; | 370 | interrupts = <0 116 4>; |
308 | reg = <0xffd00100 0x100>; | 371 | reg = <0xffd00100 0x100>; |
372 | clocks = <&clkmgr STRATIX10_L4_SP_CLK>; | ||
373 | clock-names = "timer"; | ||
309 | }; | 374 | }; |
310 | 375 | ||
311 | uart0: serial0@ffc02000 { | 376 | uart0: serial0@ffc02000 { |
@@ -315,6 +380,7 @@ | |||
315 | reg-shift = <2>; | 380 | reg-shift = <2>; |
316 | reg-io-width = <4>; | 381 | reg-io-width = <4>; |
317 | resets = <&rst UART0_RESET>; | 382 | resets = <&rst UART0_RESET>; |
383 | clocks = <&clkmgr STRATIX10_L4_SP_CLK>; | ||
318 | status = "disabled"; | 384 | status = "disabled"; |
319 | }; | 385 | }; |
320 | 386 | ||
@@ -325,6 +391,7 @@ | |||
325 | reg-shift = <2>; | 391 | reg-shift = <2>; |
326 | reg-io-width = <4>; | 392 | reg-io-width = <4>; |
327 | resets = <&rst UART1_RESET>; | 393 | resets = <&rst UART1_RESET>; |
394 | clocks = <&clkmgr STRATIX10_L4_SP_CLK>; | ||
328 | status = "disabled"; | 395 | status = "disabled"; |
329 | }; | 396 | }; |
330 | 397 | ||
@@ -387,5 +454,17 @@ | |||
387 | resets = <&rst WATCHDOG3_RESET>; | 454 | resets = <&rst WATCHDOG3_RESET>; |
388 | status = "disabled"; | 455 | status = "disabled"; |
389 | }; | 456 | }; |
457 | |||
458 | eccmgr { | ||
459 | compatible = "altr,socfpga-s10-ecc-manager"; | ||
460 | interrupts = <0 15 4>, <0 95 4>; | ||
461 | interrupt-controller; | ||
462 | #interrupt-cells = <2>; | ||
463 | |||
464 | sdramedac { | ||
465 | compatible = "altr,sdram-edac-s10"; | ||
466 | interrupts = <16 4>, <48 4>; | ||
467 | }; | ||
468 | }; | ||
390 | }; | 469 | }; |
391 | }; | 470 | }; |
diff --git a/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts b/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts index eaf13fe29287..f9b1ef12db48 100644 --- a/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts +++ b/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts | |||
@@ -50,6 +50,21 @@ | |||
50 | /* We expect the bootloader to fill in the reg */ | 50 | /* We expect the bootloader to fill in the reg */ |
51 | reg = <0 0 0 0>; | 51 | reg = <0 0 0 0>; |
52 | }; | 52 | }; |
53 | |||
54 | ref_033v: 033-v-ref { | ||
55 | compatible = "regulator-fixed"; | ||
56 | regulator-name = "0.33V"; | ||
57 | regulator-min-microvolt = <330000>; | ||
58 | regulator-max-microvolt = <330000>; | ||
59 | }; | ||
60 | |||
61 | soc { | ||
62 | clocks { | ||
63 | osc1 { | ||
64 | clock-frequency = <25000000>; | ||
65 | }; | ||
66 | }; | ||
67 | }; | ||
53 | }; | 68 | }; |
54 | 69 | ||
55 | &gpio1 { | 70 | &gpio1 { |
@@ -79,7 +94,7 @@ | |||
79 | rxd2-skew-ps = <420>; /* 0ps */ | 94 | rxd2-skew-ps = <420>; /* 0ps */ |
80 | rxd3-skew-ps = <420>; /* 0ps */ | 95 | rxd3-skew-ps = <420>; /* 0ps */ |
81 | txen-skew-ps = <0>; /* -420ps */ | 96 | txen-skew-ps = <0>; /* -420ps */ |
82 | txc-skew-ps = <1860>; /* 960ps */ | 97 | txc-skew-ps = <900>; /* 0ps */ |
83 | rxdv-skew-ps = <420>; /* 0ps */ | 98 | rxdv-skew-ps = <420>; /* 0ps */ |
84 | rxc-skew-ps = <1680>; /* 780ps */ | 99 | rxc-skew-ps = <1680>; /* 780ps */ |
85 | }; | 100 | }; |
@@ -105,3 +120,30 @@ | |||
105 | &watchdog0 { | 120 | &watchdog0 { |
106 | status = "okay"; | 121 | status = "okay"; |
107 | }; | 122 | }; |
123 | |||
124 | &i2c1 { | ||
125 | status = "okay"; | ||
126 | clock-frequency = <100000>; | ||
127 | |||
128 | adc@14 { | ||
129 | compatible = "lltc,ltc2497"; | ||
130 | reg = <0x14>; | ||
131 | vref-supply = <&ref_033v>; | ||
132 | }; | ||
133 | |||
134 | temp@4c { | ||
135 | compatible = "maxim,max1619"; | ||
136 | reg = <0x4c>; | ||
137 | }; | ||
138 | |||
139 | eeprom@51 { | ||
140 | compatible = "atmel,24c32"; | ||
141 | reg = <0x51>; | ||
142 | pagesize = <32>; | ||
143 | }; | ||
144 | |||
145 | rtc@68 { | ||
146 | compatible = "dallas,ds1339"; | ||
147 | reg = <0x68>; | ||
148 | }; | ||
149 | }; | ||
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index 1efefe919555..02c6fd9caff7 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c | |||
@@ -481,7 +481,7 @@ static void ghes_do_proc(struct ghes *ghes, | |||
481 | if (guid_equal(sec_type, &CPER_SEC_PLATFORM_MEM)) { | 481 | if (guid_equal(sec_type, &CPER_SEC_PLATFORM_MEM)) { |
482 | struct cper_sec_mem_err *mem_err = acpi_hest_get_payload(gdata); | 482 | struct cper_sec_mem_err *mem_err = acpi_hest_get_payload(gdata); |
483 | 483 | ||
484 | ghes_edac_report_mem_error(ghes, sev, mem_err); | 484 | ghes_edac_report_mem_error(sev, mem_err); |
485 | 485 | ||
486 | arch_apei_report_mem_error(sev, mem_err); | 486 | arch_apei_report_mem_error(sev, mem_err); |
487 | ghes_handle_memory_failure(gdata, sev); | 487 | ghes_handle_memory_failure(gdata, sev); |
@@ -1087,10 +1087,6 @@ static int ghes_probe(struct platform_device *ghes_dev) | |||
1087 | goto err; | 1087 | goto err; |
1088 | } | 1088 | } |
1089 | 1089 | ||
1090 | rc = ghes_edac_register(ghes, &ghes_dev->dev); | ||
1091 | if (rc < 0) | ||
1092 | goto err; | ||
1093 | |||
1094 | switch (generic->notify.type) { | 1090 | switch (generic->notify.type) { |
1095 | case ACPI_HEST_NOTIFY_POLLED: | 1091 | case ACPI_HEST_NOTIFY_POLLED: |
1096 | timer_setup(&ghes->timer, ghes_poll_func, TIMER_DEFERRABLE); | 1092 | timer_setup(&ghes->timer, ghes_poll_func, TIMER_DEFERRABLE); |
@@ -1102,14 +1098,14 @@ static int ghes_probe(struct platform_device *ghes_dev) | |||
1102 | if (rc) { | 1098 | if (rc) { |
1103 | pr_err(GHES_PFX "Failed to map GSI to IRQ for generic hardware error source: %d\n", | 1099 | pr_err(GHES_PFX "Failed to map GSI to IRQ for generic hardware error source: %d\n", |
1104 | generic->header.source_id); | 1100 | generic->header.source_id); |
1105 | goto err_edac_unreg; | 1101 | goto err; |
1106 | } | 1102 | } |
1107 | rc = request_irq(ghes->irq, ghes_irq_func, IRQF_SHARED, | 1103 | rc = request_irq(ghes->irq, ghes_irq_func, IRQF_SHARED, |
1108 | "GHES IRQ", ghes); | 1104 | "GHES IRQ", ghes); |
1109 | if (rc) { | 1105 | if (rc) { |
1110 | pr_err(GHES_PFX "Failed to register IRQ for generic hardware error source: %d\n", | 1106 | pr_err(GHES_PFX "Failed to register IRQ for generic hardware error source: %d\n", |
1111 | generic->header.source_id); | 1107 | generic->header.source_id); |
1112 | goto err_edac_unreg; | 1108 | goto err; |
1113 | } | 1109 | } |
1114 | break; | 1110 | break; |
1115 | 1111 | ||
@@ -1132,14 +1128,16 @@ static int ghes_probe(struct platform_device *ghes_dev) | |||
1132 | default: | 1128 | default: |
1133 | BUG(); | 1129 | BUG(); |
1134 | } | 1130 | } |
1131 | |||
1135 | platform_set_drvdata(ghes_dev, ghes); | 1132 | platform_set_drvdata(ghes_dev, ghes); |
1136 | 1133 | ||
1134 | ghes_edac_register(ghes, &ghes_dev->dev); | ||
1135 | |||
1137 | /* Handle any pending errors right away */ | 1136 | /* Handle any pending errors right away */ |
1138 | ghes_proc(ghes); | 1137 | ghes_proc(ghes); |
1139 | 1138 | ||
1140 | return 0; | 1139 | return 0; |
1141 | err_edac_unreg: | 1140 | |
1142 | ghes_edac_unregister(ghes); | ||
1143 | err: | 1141 | err: |
1144 | if (ghes) { | 1142 | if (ghes) { |
1145 | ghes_fini(ghes); | 1143 | ghes_fini(ghes); |
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index da2da53bca6d..57304b2e989f 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig | |||
@@ -232,6 +232,7 @@ config EDAC_SBRIDGE | |||
232 | config EDAC_SKX | 232 | config EDAC_SKX |
233 | tristate "Intel Skylake server Integrated MC" | 233 | tristate "Intel Skylake server Integrated MC" |
234 | depends on PCI && X86_64 && X86_MCE_INTEL && PCI_MMCONFIG | 234 | depends on PCI && X86_64 && X86_MCE_INTEL && PCI_MMCONFIG |
235 | depends on ACPI_NFIT || !ACPI_NFIT # if ACPI_NFIT=m, EDAC_SKX can't be y | ||
235 | select DMI | 236 | select DMI |
236 | help | 237 | help |
237 | Support for error detection and correction the Intel | 238 | Support for error detection and correction the Intel |
@@ -374,7 +375,7 @@ config EDAC_THUNDERX | |||
374 | 375 | ||
375 | config EDAC_ALTERA | 376 | config EDAC_ALTERA |
376 | bool "Altera SOCFPGA ECC" | 377 | bool "Altera SOCFPGA ECC" |
377 | depends on EDAC=y && ARCH_SOCFPGA | 378 | depends on EDAC=y && (ARCH_SOCFPGA || ARCH_STRATIX10) |
378 | help | 379 | help |
379 | Support for error detection and correction on the | 380 | Support for error detection and correction on the |
380 | Altera SOCs. This must be selected for SDRAM ECC. | 381 | Altera SOCs. This must be selected for SDRAM ECC. |
diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c index 11d6419788c2..d0d5c4dbe097 100644 --- a/drivers/edac/altera_edac.c +++ b/drivers/edac/altera_edac.c | |||
@@ -1,20 +1,8 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
3 | * Copyright (C) 2017-2018, Intel Corporation. All rights reserved | ||
2 | * Copyright Altera Corporation (C) 2014-2016. All rights reserved. | 4 | * Copyright Altera Corporation (C) 2014-2016. All rights reserved. |
3 | * Copyright 2011-2012 Calxeda, Inc. | 5 | * Copyright 2011-2012 Calxeda, Inc. |
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms and conditions of the GNU General Public License, | ||
7 | * version 2, as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
16 | * | ||
17 | * Adapted from the highbank_mc_edac driver. | ||
18 | */ | 6 | */ |
19 | 7 | ||
20 | #include <asm/cacheflush.h> | 8 | #include <asm/cacheflush.h> |
@@ -26,6 +14,7 @@ | |||
26 | #include <linux/irqchip/chained_irq.h> | 14 | #include <linux/irqchip/chained_irq.h> |
27 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
28 | #include <linux/mfd/syscon.h> | 16 | #include <linux/mfd/syscon.h> |
17 | #include <linux/notifier.h> | ||
29 | #include <linux/of_address.h> | 18 | #include <linux/of_address.h> |
30 | #include <linux/of_irq.h> | 19 | #include <linux/of_irq.h> |
31 | #include <linux/of_platform.h> | 20 | #include <linux/of_platform.h> |
@@ -80,6 +69,25 @@ static const struct altr_sdram_prv_data a10_data = { | |||
80 | .ue_set_mask = A10_DIAGINT_TDERRA_MASK, | 69 | .ue_set_mask = A10_DIAGINT_TDERRA_MASK, |
81 | }; | 70 | }; |
82 | 71 | ||
72 | static const struct altr_sdram_prv_data s10_data = { | ||
73 | .ecc_ctrl_offset = S10_ECCCTRL1_OFST, | ||
74 | .ecc_ctl_en_mask = A10_ECCCTRL1_ECC_EN, | ||
75 | .ecc_stat_offset = S10_INTSTAT_OFST, | ||
76 | .ecc_stat_ce_mask = A10_INTSTAT_SBEERR, | ||
77 | .ecc_stat_ue_mask = A10_INTSTAT_DBEERR, | ||
78 | .ecc_saddr_offset = S10_SERRADDR_OFST, | ||
79 | .ecc_daddr_offset = S10_DERRADDR_OFST, | ||
80 | .ecc_irq_en_offset = S10_ERRINTEN_OFST, | ||
81 | .ecc_irq_en_mask = A10_ECC_IRQ_EN_MASK, | ||
82 | .ecc_irq_clr_offset = S10_INTSTAT_OFST, | ||
83 | .ecc_irq_clr_mask = (A10_INTSTAT_SBEERR | A10_INTSTAT_DBEERR), | ||
84 | .ecc_cnt_rst_offset = S10_ECCCTRL1_OFST, | ||
85 | .ecc_cnt_rst_mask = A10_ECC_CNT_RESET_MASK, | ||
86 | .ce_ue_trgr_offset = S10_DIAGINTTEST_OFST, | ||
87 | .ce_set_mask = A10_DIAGINT_TSERRA_MASK, | ||
88 | .ue_set_mask = A10_DIAGINT_TDERRA_MASK, | ||
89 | }; | ||
90 | |||
83 | /*********************** EDAC Memory Controller Functions ****************/ | 91 | /*********************** EDAC Memory Controller Functions ****************/ |
84 | 92 | ||
85 | /* The SDRAM controller uses the EDAC Memory Controller framework. */ | 93 | /* The SDRAM controller uses the EDAC Memory Controller framework. */ |
@@ -231,6 +239,7 @@ static unsigned long get_total_mem(void) | |||
231 | static const struct of_device_id altr_sdram_ctrl_of_match[] = { | 239 | static const struct of_device_id altr_sdram_ctrl_of_match[] = { |
232 | { .compatible = "altr,sdram-edac", .data = &c5_data}, | 240 | { .compatible = "altr,sdram-edac", .data = &c5_data}, |
233 | { .compatible = "altr,sdram-edac-a10", .data = &a10_data}, | 241 | { .compatible = "altr,sdram-edac-a10", .data = &a10_data}, |
242 | { .compatible = "altr,sdram-edac-s10", .data = &s10_data}, | ||
234 | {}, | 243 | {}, |
235 | }; | 244 | }; |
236 | MODULE_DEVICE_TABLE(of, altr_sdram_ctrl_of_match); | 245 | MODULE_DEVICE_TABLE(of, altr_sdram_ctrl_of_match); |
@@ -477,6 +486,292 @@ static int altr_sdram_remove(struct platform_device *pdev) | |||
477 | return 0; | 486 | return 0; |
478 | } | 487 | } |
479 | 488 | ||
489 | /**************** Stratix 10 EDAC Memory Controller Functions ************/ | ||
490 | |||
491 | /** | ||
492 | * s10_protected_reg_write | ||
493 | * Write to a protected SMC register. | ||
494 | * @context: Not used. | ||
495 | * @reg: Address of register | ||
496 | * @value: Value to write | ||
497 | * Return: INTEL_SIP_SMC_STATUS_OK (0) on success | ||
498 | * INTEL_SIP_SMC_REG_ERROR on error | ||
499 | * INTEL_SIP_SMC_RETURN_UNKNOWN_FUNCTION if not supported | ||
500 | */ | ||
501 | static int s10_protected_reg_write(void *context, unsigned int reg, | ||
502 | unsigned int val) | ||
503 | { | ||
504 | struct arm_smccc_res result; | ||
505 | |||
506 | arm_smccc_smc(INTEL_SIP_SMC_REG_WRITE, reg, val, 0, 0, | ||
507 | 0, 0, 0, &result); | ||
508 | |||
509 | return (int)result.a0; | ||
510 | } | ||
511 | |||
512 | /** | ||
513 | * s10_protected_reg_read | ||
514 | * Read the status of a protected SMC register | ||
515 | * @context: Not used. | ||
516 | * @reg: Address of register | ||
517 | * @value: Value read. | ||
518 | * Return: INTEL_SIP_SMC_STATUS_OK (0) on success | ||
519 | * INTEL_SIP_SMC_REG_ERROR on error | ||
520 | * INTEL_SIP_SMC_RETURN_UNKNOWN_FUNCTION if not supported | ||
521 | */ | ||
522 | static int s10_protected_reg_read(void *context, unsigned int reg, | ||
523 | unsigned int *val) | ||
524 | { | ||
525 | struct arm_smccc_res result; | ||
526 | |||
527 | arm_smccc_smc(INTEL_SIP_SMC_REG_READ, reg, 0, 0, 0, | ||
528 | 0, 0, 0, &result); | ||
529 | |||
530 | *val = (unsigned int)result.a1; | ||
531 | |||
532 | return (int)result.a0; | ||
533 | } | ||
534 | |||
535 | static bool s10_sdram_writeable_reg(struct device *dev, unsigned int reg) | ||
536 | { | ||
537 | switch (reg) { | ||
538 | case S10_ECCCTRL1_OFST: | ||
539 | case S10_ERRINTEN_OFST: | ||
540 | case S10_INTMODE_OFST: | ||
541 | case S10_INTSTAT_OFST: | ||
542 | case S10_DIAGINTTEST_OFST: | ||
543 | case S10_SYSMGR_ECC_INTMASK_VAL_OFST: | ||
544 | case S10_SYSMGR_ECC_INTMASK_SET_OFST: | ||
545 | case S10_SYSMGR_ECC_INTMASK_CLR_OFST: | ||
546 | return true; | ||
547 | } | ||
548 | return false; | ||
549 | } | ||
550 | |||
551 | static bool s10_sdram_readable_reg(struct device *dev, unsigned int reg) | ||
552 | { | ||
553 | switch (reg) { | ||
554 | case S10_ECCCTRL1_OFST: | ||
555 | case S10_ERRINTEN_OFST: | ||
556 | case S10_INTMODE_OFST: | ||
557 | case S10_INTSTAT_OFST: | ||
558 | case S10_DERRADDR_OFST: | ||
559 | case S10_SERRADDR_OFST: | ||
560 | case S10_DIAGINTTEST_OFST: | ||
561 | case S10_SYSMGR_ECC_INTMASK_VAL_OFST: | ||
562 | case S10_SYSMGR_ECC_INTMASK_SET_OFST: | ||
563 | case S10_SYSMGR_ECC_INTMASK_CLR_OFST: | ||
564 | case S10_SYSMGR_ECC_INTSTAT_SERR_OFST: | ||
565 | case S10_SYSMGR_ECC_INTSTAT_DERR_OFST: | ||
566 | return true; | ||
567 | } | ||
568 | return false; | ||
569 | } | ||
570 | |||
571 | static bool s10_sdram_volatile_reg(struct device *dev, unsigned int reg) | ||
572 | { | ||
573 | switch (reg) { | ||
574 | case S10_ECCCTRL1_OFST: | ||
575 | case S10_ERRINTEN_OFST: | ||
576 | case S10_INTMODE_OFST: | ||
577 | case S10_INTSTAT_OFST: | ||
578 | case S10_DERRADDR_OFST: | ||
579 | case S10_SERRADDR_OFST: | ||
580 | case S10_DIAGINTTEST_OFST: | ||
581 | case S10_SYSMGR_ECC_INTMASK_VAL_OFST: | ||
582 | case S10_SYSMGR_ECC_INTMASK_SET_OFST: | ||
583 | case S10_SYSMGR_ECC_INTMASK_CLR_OFST: | ||
584 | case S10_SYSMGR_ECC_INTSTAT_SERR_OFST: | ||
585 | case S10_SYSMGR_ECC_INTSTAT_DERR_OFST: | ||
586 | return true; | ||
587 | } | ||
588 | return false; | ||
589 | } | ||
590 | |||
591 | static const struct regmap_config s10_sdram_regmap_cfg = { | ||
592 | .name = "s10_ddr", | ||
593 | .reg_bits = 32, | ||
594 | .reg_stride = 4, | ||
595 | .val_bits = 32, | ||
596 | .max_register = 0xffffffff, | ||
597 | .writeable_reg = s10_sdram_writeable_reg, | ||
598 | .readable_reg = s10_sdram_readable_reg, | ||
599 | .volatile_reg = s10_sdram_volatile_reg, | ||
600 | .reg_read = s10_protected_reg_read, | ||
601 | .reg_write = s10_protected_reg_write, | ||
602 | .use_single_rw = true, | ||
603 | }; | ||
604 | |||
605 | static int altr_s10_sdram_probe(struct platform_device *pdev) | ||
606 | { | ||
607 | const struct of_device_id *id; | ||
608 | struct edac_mc_layer layers[2]; | ||
609 | struct mem_ctl_info *mci; | ||
610 | struct altr_sdram_mc_data *drvdata; | ||
611 | const struct altr_sdram_prv_data *priv; | ||
612 | struct regmap *regmap; | ||
613 | struct dimm_info *dimm; | ||
614 | u32 read_reg; | ||
615 | int irq, ret = 0; | ||
616 | unsigned long mem_size; | ||
617 | |||
618 | id = of_match_device(altr_sdram_ctrl_of_match, &pdev->dev); | ||
619 | if (!id) | ||
620 | return -ENODEV; | ||
621 | |||
622 | /* Grab specific offsets and masks for Stratix10 */ | ||
623 | priv = of_match_node(altr_sdram_ctrl_of_match, | ||
624 | pdev->dev.of_node)->data; | ||
625 | |||
626 | regmap = devm_regmap_init(&pdev->dev, NULL, (void *)priv, | ||
627 | &s10_sdram_regmap_cfg); | ||
628 | if (IS_ERR(regmap)) | ||
629 | return PTR_ERR(regmap); | ||
630 | |||
631 | /* Validate the SDRAM controller has ECC enabled */ | ||
632 | if (regmap_read(regmap, priv->ecc_ctrl_offset, &read_reg) || | ||
633 | ((read_reg & priv->ecc_ctl_en_mask) != priv->ecc_ctl_en_mask)) { | ||
634 | edac_printk(KERN_ERR, EDAC_MC, | ||
635 | "No ECC/ECC disabled [0x%08X]\n", read_reg); | ||
636 | return -ENODEV; | ||
637 | } | ||
638 | |||
639 | /* Grab memory size from device tree. */ | ||
640 | mem_size = get_total_mem(); | ||
641 | if (!mem_size) { | ||
642 | edac_printk(KERN_ERR, EDAC_MC, "Unable to calculate memory size\n"); | ||
643 | return -ENODEV; | ||
644 | } | ||
645 | |||
646 | /* Ensure the SDRAM Interrupt is disabled */ | ||
647 | if (regmap_update_bits(regmap, priv->ecc_irq_en_offset, | ||
648 | priv->ecc_irq_en_mask, 0)) { | ||
649 | edac_printk(KERN_ERR, EDAC_MC, | ||
650 | "Error disabling SDRAM ECC IRQ\n"); | ||
651 | return -ENODEV; | ||
652 | } | ||
653 | |||
654 | /* Toggle to clear the SDRAM Error count */ | ||
655 | if (regmap_update_bits(regmap, priv->ecc_cnt_rst_offset, | ||
656 | priv->ecc_cnt_rst_mask, | ||
657 | priv->ecc_cnt_rst_mask)) { | ||
658 | edac_printk(KERN_ERR, EDAC_MC, | ||
659 | "Error clearing SDRAM ECC count\n"); | ||
660 | return -ENODEV; | ||
661 | } | ||
662 | |||
663 | if (regmap_update_bits(regmap, priv->ecc_cnt_rst_offset, | ||
664 | priv->ecc_cnt_rst_mask, 0)) { | ||
665 | edac_printk(KERN_ERR, EDAC_MC, | ||
666 | "Error clearing SDRAM ECC count\n"); | ||
667 | return -ENODEV; | ||
668 | } | ||
669 | |||
670 | irq = platform_get_irq(pdev, 0); | ||
671 | if (irq < 0) { | ||
672 | edac_printk(KERN_ERR, EDAC_MC, | ||
673 | "No irq %d in DT\n", irq); | ||
674 | return -ENODEV; | ||
675 | } | ||
676 | |||
677 | layers[0].type = EDAC_MC_LAYER_CHIP_SELECT; | ||
678 | layers[0].size = 1; | ||
679 | layers[0].is_virt_csrow = true; | ||
680 | layers[1].type = EDAC_MC_LAYER_CHANNEL; | ||
681 | layers[1].size = 1; | ||
682 | layers[1].is_virt_csrow = false; | ||
683 | mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, | ||
684 | sizeof(struct altr_sdram_mc_data)); | ||
685 | if (!mci) | ||
686 | return -ENOMEM; | ||
687 | |||
688 | mci->pdev = &pdev->dev; | ||
689 | drvdata = mci->pvt_info; | ||
690 | drvdata->mc_vbase = regmap; | ||
691 | drvdata->data = priv; | ||
692 | platform_set_drvdata(pdev, mci); | ||
693 | |||
694 | if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL)) { | ||
695 | edac_printk(KERN_ERR, EDAC_MC, | ||
696 | "Unable to get managed device resource\n"); | ||
697 | ret = -ENOMEM; | ||
698 | goto free; | ||
699 | } | ||
700 | |||
701 | mci->mtype_cap = MEM_FLAG_DDR3; | ||
702 | mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; | ||
703 | mci->edac_cap = EDAC_FLAG_SECDED; | ||
704 | mci->mod_name = EDAC_MOD_STR; | ||
705 | mci->ctl_name = dev_name(&pdev->dev); | ||
706 | mci->scrub_mode = SCRUB_SW_SRC; | ||
707 | mci->dev_name = dev_name(&pdev->dev); | ||
708 | |||
709 | dimm = *mci->dimms; | ||
710 | dimm->nr_pages = ((mem_size - 1) >> PAGE_SHIFT) + 1; | ||
711 | dimm->grain = 8; | ||
712 | dimm->dtype = DEV_X8; | ||
713 | dimm->mtype = MEM_DDR3; | ||
714 | dimm->edac_mode = EDAC_SECDED; | ||
715 | |||
716 | ret = edac_mc_add_mc(mci); | ||
717 | if (ret < 0) | ||
718 | goto err; | ||
719 | |||
720 | ret = devm_request_irq(&pdev->dev, irq, altr_sdram_mc_err_handler, | ||
721 | IRQF_SHARED, dev_name(&pdev->dev), mci); | ||
722 | if (ret < 0) { | ||
723 | edac_mc_printk(mci, KERN_ERR, | ||
724 | "Unable to request irq %d\n", irq); | ||
725 | ret = -ENODEV; | ||
726 | goto err2; | ||
727 | } | ||
728 | |||
729 | if (regmap_write(regmap, S10_SYSMGR_ECC_INTMASK_CLR_OFST, | ||
730 | S10_DDR0_IRQ_MASK)) { | ||
731 | edac_printk(KERN_ERR, EDAC_MC, | ||
732 | "Error clearing SDRAM ECC count\n"); | ||
733 | return -ENODEV; | ||
734 | } | ||
735 | |||
736 | if (regmap_update_bits(drvdata->mc_vbase, priv->ecc_irq_en_offset, | ||
737 | priv->ecc_irq_en_mask, priv->ecc_irq_en_mask)) { | ||
738 | edac_mc_printk(mci, KERN_ERR, | ||
739 | "Error enabling SDRAM ECC IRQ\n"); | ||
740 | ret = -ENODEV; | ||
741 | goto err2; | ||
742 | } | ||
743 | |||
744 | altr_sdr_mc_create_debugfs_nodes(mci); | ||
745 | |||
746 | devres_close_group(&pdev->dev, NULL); | ||
747 | |||
748 | return 0; | ||
749 | |||
750 | err2: | ||
751 | edac_mc_del_mc(&pdev->dev); | ||
752 | err: | ||
753 | devres_release_group(&pdev->dev, NULL); | ||
754 | free: | ||
755 | edac_mc_free(mci); | ||
756 | edac_printk(KERN_ERR, EDAC_MC, | ||
757 | "EDAC Probe Failed; Error %d\n", ret); | ||
758 | |||
759 | return ret; | ||
760 | } | ||
761 | |||
762 | static int altr_s10_sdram_remove(struct platform_device *pdev) | ||
763 | { | ||
764 | struct mem_ctl_info *mci = platform_get_drvdata(pdev); | ||
765 | |||
766 | edac_mc_del_mc(&pdev->dev); | ||
767 | edac_mc_free(mci); | ||
768 | platform_set_drvdata(pdev, NULL); | ||
769 | |||
770 | return 0; | ||
771 | } | ||
772 | |||
773 | /************** </Stratix10 EDAC Memory Controller Functions> ***********/ | ||
774 | |||
480 | /* | 775 | /* |
481 | * If you want to suspend, need to disable EDAC by removing it | 776 | * If you want to suspend, need to disable EDAC by removing it |
482 | * from the device tree or defconfig. | 777 | * from the device tree or defconfig. |
@@ -508,6 +803,20 @@ static struct platform_driver altr_sdram_edac_driver = { | |||
508 | 803 | ||
509 | module_platform_driver(altr_sdram_edac_driver); | 804 | module_platform_driver(altr_sdram_edac_driver); |
510 | 805 | ||
806 | static struct platform_driver altr_s10_sdram_edac_driver = { | ||
807 | .probe = altr_s10_sdram_probe, | ||
808 | .remove = altr_s10_sdram_remove, | ||
809 | .driver = { | ||
810 | .name = "altr_s10_sdram_edac", | ||
811 | #ifdef CONFIG_PM | ||
812 | .pm = &altr_sdram_pm_ops, | ||
813 | #endif | ||
814 | .of_match_table = altr_sdram_ctrl_of_match, | ||
815 | }, | ||
816 | }; | ||
817 | |||
818 | module_platform_driver(altr_s10_sdram_edac_driver); | ||
819 | |||
511 | /************************* EDAC Parent Probe *************************/ | 820 | /************************* EDAC Parent Probe *************************/ |
512 | 821 | ||
513 | static const struct of_device_id altr_edac_device_of_match[]; | 822 | static const struct of_device_id altr_edac_device_of_match[]; |
@@ -1106,7 +1415,7 @@ static void *ocram_alloc_mem(size_t size, void **other) | |||
1106 | 1415 | ||
1107 | static void ocram_free_mem(void *p, size_t size, void *other) | 1416 | static void ocram_free_mem(void *p, size_t size, void *other) |
1108 | { | 1417 | { |
1109 | gen_pool_free((struct gen_pool *)other, (u32)p, size); | 1418 | gen_pool_free((struct gen_pool *)other, (unsigned long)p, size); |
1110 | } | 1419 | } |
1111 | 1420 | ||
1112 | static const struct edac_device_prv_data ocramecc_data = { | 1421 | static const struct edac_device_prv_data ocramecc_data = { |
@@ -1925,6 +2234,171 @@ static struct platform_driver altr_edac_a10_driver = { | |||
1925 | }; | 2234 | }; |
1926 | module_platform_driver(altr_edac_a10_driver); | 2235 | module_platform_driver(altr_edac_a10_driver); |
1927 | 2236 | ||
2237 | /************** Stratix 10 EDAC Device Controller Functions> ************/ | ||
2238 | |||
2239 | #define to_s10edac(p, m) container_of(p, struct altr_stratix10_edac, m) | ||
2240 | |||
2241 | /* | ||
2242 | * The double bit error is handled through SError which is fatal. This is | ||
2243 | * called as a panic notifier to printout ECC error info as part of the panic. | ||
2244 | */ | ||
2245 | static int s10_edac_dberr_handler(struct notifier_block *this, | ||
2246 | unsigned long event, void *ptr) | ||
2247 | { | ||
2248 | struct altr_stratix10_edac *edac = to_s10edac(this, panic_notifier); | ||
2249 | int err_addr, dberror; | ||
2250 | |||
2251 | s10_protected_reg_read(edac, S10_SYSMGR_ECC_INTSTAT_DERR_OFST, | ||
2252 | &dberror); | ||
2253 | /* Remember the UE Errors for a reboot */ | ||
2254 | s10_protected_reg_write(edac, S10_SYSMGR_UE_VAL_OFST, dberror); | ||
2255 | if (dberror & S10_DDR0_IRQ_MASK) { | ||
2256 | s10_protected_reg_read(edac, S10_DERRADDR_OFST, &err_addr); | ||
2257 | /* Remember the UE Error address */ | ||
2258 | s10_protected_reg_write(edac, S10_SYSMGR_UE_ADDR_OFST, | ||
2259 | err_addr); | ||
2260 | edac_printk(KERN_ERR, EDAC_MC, | ||
2261 | "EDAC: [Uncorrectable errors @ 0x%08X]\n\n", | ||
2262 | err_addr); | ||
2263 | } | ||
2264 | |||
2265 | return NOTIFY_DONE; | ||
2266 | } | ||
2267 | |||
2268 | static void altr_edac_s10_irq_handler(struct irq_desc *desc) | ||
2269 | { | ||
2270 | struct altr_stratix10_edac *edac = irq_desc_get_handler_data(desc); | ||
2271 | struct irq_chip *chip = irq_desc_get_chip(desc); | ||
2272 | int irq = irq_desc_get_irq(desc); | ||
2273 | int bit, sm_offset, irq_status; | ||
2274 | |||
2275 | sm_offset = S10_SYSMGR_ECC_INTSTAT_SERR_OFST; | ||
2276 | |||
2277 | chained_irq_enter(chip, desc); | ||
2278 | |||
2279 | s10_protected_reg_read(NULL, sm_offset, &irq_status); | ||
2280 | |||
2281 | for_each_set_bit(bit, (unsigned long *)&irq_status, 32) { | ||
2282 | irq = irq_linear_revmap(edac->domain, bit); | ||
2283 | if (irq) | ||
2284 | generic_handle_irq(irq); | ||
2285 | } | ||
2286 | |||
2287 | chained_irq_exit(chip, desc); | ||
2288 | } | ||
2289 | |||
2290 | static void s10_eccmgr_irq_mask(struct irq_data *d) | ||
2291 | { | ||
2292 | struct altr_stratix10_edac *edac = irq_data_get_irq_chip_data(d); | ||
2293 | |||
2294 | s10_protected_reg_write(edac, S10_SYSMGR_ECC_INTMASK_SET_OFST, | ||
2295 | BIT(d->hwirq)); | ||
2296 | } | ||
2297 | |||
2298 | static void s10_eccmgr_irq_unmask(struct irq_data *d) | ||
2299 | { | ||
2300 | struct altr_stratix10_edac *edac = irq_data_get_irq_chip_data(d); | ||
2301 | |||
2302 | s10_protected_reg_write(edac, S10_SYSMGR_ECC_INTMASK_CLR_OFST, | ||
2303 | BIT(d->hwirq)); | ||
2304 | } | ||
2305 | |||
2306 | static int s10_eccmgr_irqdomain_map(struct irq_domain *d, unsigned int irq, | ||
2307 | irq_hw_number_t hwirq) | ||
2308 | { | ||
2309 | struct altr_stratix10_edac *edac = d->host_data; | ||
2310 | |||
2311 | irq_set_chip_and_handler(irq, &edac->irq_chip, handle_simple_irq); | ||
2312 | irq_set_chip_data(irq, edac); | ||
2313 | irq_set_noprobe(irq); | ||
2314 | |||
2315 | return 0; | ||
2316 | } | ||
2317 | |||
2318 | static const struct irq_domain_ops s10_eccmgr_ic_ops = { | ||
2319 | .map = s10_eccmgr_irqdomain_map, | ||
2320 | .xlate = irq_domain_xlate_twocell, | ||
2321 | }; | ||
2322 | |||
2323 | static int altr_edac_s10_probe(struct platform_device *pdev) | ||
2324 | { | ||
2325 | struct altr_stratix10_edac *edac; | ||
2326 | struct device_node *child; | ||
2327 | int dberror, err_addr; | ||
2328 | |||
2329 | edac = devm_kzalloc(&pdev->dev, sizeof(*edac), GFP_KERNEL); | ||
2330 | if (!edac) | ||
2331 | return -ENOMEM; | ||
2332 | |||
2333 | edac->dev = &pdev->dev; | ||
2334 | platform_set_drvdata(pdev, edac); | ||
2335 | INIT_LIST_HEAD(&edac->s10_ecc_devices); | ||
2336 | |||
2337 | edac->irq_chip.name = pdev->dev.of_node->name; | ||
2338 | edac->irq_chip.irq_mask = s10_eccmgr_irq_mask; | ||
2339 | edac->irq_chip.irq_unmask = s10_eccmgr_irq_unmask; | ||
2340 | edac->domain = irq_domain_add_linear(pdev->dev.of_node, 64, | ||
2341 | &s10_eccmgr_ic_ops, edac); | ||
2342 | if (!edac->domain) { | ||
2343 | dev_err(&pdev->dev, "Error adding IRQ domain\n"); | ||
2344 | return -ENOMEM; | ||
2345 | } | ||
2346 | |||
2347 | edac->sb_irq = platform_get_irq(pdev, 0); | ||
2348 | if (edac->sb_irq < 0) { | ||
2349 | dev_err(&pdev->dev, "No SBERR IRQ resource\n"); | ||
2350 | return edac->sb_irq; | ||
2351 | } | ||
2352 | |||
2353 | irq_set_chained_handler_and_data(edac->sb_irq, | ||
2354 | altr_edac_s10_irq_handler, | ||
2355 | edac); | ||
2356 | |||
2357 | edac->panic_notifier.notifier_call = s10_edac_dberr_handler; | ||
2358 | atomic_notifier_chain_register(&panic_notifier_list, | ||
2359 | &edac->panic_notifier); | ||
2360 | |||
2361 | /* Printout a message if uncorrectable error previously. */ | ||
2362 | s10_protected_reg_read(edac, S10_SYSMGR_UE_VAL_OFST, &dberror); | ||
2363 | if (dberror) { | ||
2364 | s10_protected_reg_read(edac, S10_SYSMGR_UE_ADDR_OFST, | ||
2365 | &err_addr); | ||
2366 | edac_printk(KERN_ERR, EDAC_DEVICE, | ||
2367 | "Previous Boot UE detected[0x%X] @ 0x%X\n", | ||
2368 | dberror, err_addr); | ||
2369 | /* Reset the sticky registers */ | ||
2370 | s10_protected_reg_write(edac, S10_SYSMGR_UE_VAL_OFST, 0); | ||
2371 | s10_protected_reg_write(edac, S10_SYSMGR_UE_ADDR_OFST, 0); | ||
2372 | } | ||
2373 | |||
2374 | for_each_child_of_node(pdev->dev.of_node, child) { | ||
2375 | if (!of_device_is_available(child)) | ||
2376 | continue; | ||
2377 | |||
2378 | if (of_device_is_compatible(child, "altr,sdram-edac-s10")) | ||
2379 | of_platform_populate(pdev->dev.of_node, | ||
2380 | altr_sdram_ctrl_of_match, | ||
2381 | NULL, &pdev->dev); | ||
2382 | } | ||
2383 | |||
2384 | return 0; | ||
2385 | } | ||
2386 | |||
2387 | static const struct of_device_id altr_edac_s10_of_match[] = { | ||
2388 | { .compatible = "altr,socfpga-s10-ecc-manager" }, | ||
2389 | {}, | ||
2390 | }; | ||
2391 | MODULE_DEVICE_TABLE(of, altr_edac_s10_of_match); | ||
2392 | |||
2393 | static struct platform_driver altr_edac_s10_driver = { | ||
2394 | .probe = altr_edac_s10_probe, | ||
2395 | .driver = { | ||
2396 | .name = "socfpga_s10_ecc_manager", | ||
2397 | .of_match_table = altr_edac_s10_of_match, | ||
2398 | }, | ||
2399 | }; | ||
2400 | module_platform_driver(altr_edac_s10_driver); | ||
2401 | |||
1928 | MODULE_LICENSE("GPL v2"); | 2402 | MODULE_LICENSE("GPL v2"); |
1929 | MODULE_AUTHOR("Thor Thayer"); | 2403 | MODULE_AUTHOR("Thor Thayer"); |
1930 | MODULE_DESCRIPTION("EDAC Driver for Altera Memories"); | 2404 | MODULE_DESCRIPTION("EDAC Driver for Altera Memories"); |
diff --git a/drivers/edac/altera_edac.h b/drivers/edac/altera_edac.h index cbc96290f743..81f0554e09de 100644 --- a/drivers/edac/altera_edac.h +++ b/drivers/edac/altera_edac.h | |||
@@ -1,23 +1,13 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
1 | /* | 2 | /* |
2 | * | 3 | * Copyright (C) 2017-2018, Intel Corporation |
3 | * Copyright (C) 2015 Altera Corporation | 4 | * Copyright (C) 2015 Altera Corporation |
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms and conditions of the GNU General Public License, | ||
7 | * version 2, as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
16 | */ | 5 | */ |
17 | 6 | ||
18 | #ifndef _ALTERA_EDAC_H | 7 | #ifndef _ALTERA_EDAC_H |
19 | #define _ALTERA_EDAC_H | 8 | #define _ALTERA_EDAC_H |
20 | 9 | ||
10 | #include <linux/arm-smccc.h> | ||
21 | #include <linux/edac.h> | 11 | #include <linux/edac.h> |
22 | #include <linux/types.h> | 12 | #include <linux/types.h> |
23 | 13 | ||
@@ -94,6 +84,7 @@ | |||
94 | /* SDRAM Controller Address Width Register */ | 84 | /* SDRAM Controller Address Width Register */ |
95 | #define CV_DRAMADDRW 0xFFC2502C | 85 | #define CV_DRAMADDRW 0xFFC2502C |
96 | #define A10_DRAMADDRW 0xFFCFA0A8 | 86 | #define A10_DRAMADDRW 0xFFCFA0A8 |
87 | #define S10_DRAMADDRW 0xF80110E0 | ||
97 | 88 | ||
98 | /* SDRAM Controller Address Widths Field Register */ | 89 | /* SDRAM Controller Address Widths Field Register */ |
99 | #define DRAMADDRW_COLBIT_MASK 0x001F | 90 | #define DRAMADDRW_COLBIT_MASK 0x001F |
@@ -115,6 +106,7 @@ | |||
115 | /* SDRAM Controller Interface Data Width Register */ | 106 | /* SDRAM Controller Interface Data Width Register */ |
116 | #define CV_DRAMIFWIDTH 0xFFC25030 | 107 | #define CV_DRAMIFWIDTH 0xFFC25030 |
117 | #define A10_DRAMIFWIDTH 0xFFCFB008 | 108 | #define A10_DRAMIFWIDTH 0xFFCFB008 |
109 | #define S10_DRAMIFWIDTH 0xF8011008 | ||
118 | 110 | ||
119 | /* SDRAM Controller Interface Data Width Defines */ | 111 | /* SDRAM Controller Interface Data Width Defines */ |
120 | #define CV_DRAMIFWIDTH_16B_ECC 24 | 112 | #define CV_DRAMIFWIDTH_16B_ECC 24 |
@@ -164,6 +156,34 @@ | |||
164 | #define A10_INTMASK_CLR_OFST 0x10 | 156 | #define A10_INTMASK_CLR_OFST 0x10 |
165 | #define A10_DDR0_IRQ_MASK BIT(17) | 157 | #define A10_DDR0_IRQ_MASK BIT(17) |
166 | 158 | ||
159 | /************* Stratix10 Defines **************/ | ||
160 | |||
161 | /* SDRAM Controller EccCtrl Register */ | ||
162 | #define S10_ECCCTRL1_OFST 0xF8011100 | ||
163 | |||
164 | /* SDRAM Controller DRAM IRQ Register */ | ||
165 | #define S10_ERRINTEN_OFST 0xF8011110 | ||
166 | |||
167 | /* SDRAM Interrupt Mode Register */ | ||
168 | #define S10_INTMODE_OFST 0xF801111C | ||
169 | |||
170 | /* SDRAM Controller Error Status Register */ | ||
171 | #define S10_INTSTAT_OFST 0xF8011120 | ||
172 | |||
173 | /* SDRAM Controller ECC Error Address Register */ | ||
174 | #define S10_DERRADDR_OFST 0xF801112C | ||
175 | #define S10_SERRADDR_OFST 0xF8011130 | ||
176 | |||
177 | /* SDRAM Controller ECC Diagnostic Register */ | ||
178 | #define S10_DIAGINTTEST_OFST 0xF8011124 | ||
179 | |||
180 | /* SDRAM Single Bit Error Count Compare Set Register */ | ||
181 | #define S10_SERRCNTREG_OFST 0xF801113C | ||
182 | |||
183 | /* Sticky registers for Uncorrected Errors */ | ||
184 | #define S10_SYSMGR_UE_VAL_OFST 0xFFD12220 | ||
185 | #define S10_SYSMGR_UE_ADDR_OFST 0xFFD12224 | ||
186 | |||
167 | struct altr_sdram_prv_data { | 187 | struct altr_sdram_prv_data { |
168 | int ecc_ctrl_offset; | 188 | int ecc_ctrl_offset; |
169 | int ecc_ctl_en_mask; | 189 | int ecc_ctl_en_mask; |
@@ -296,6 +316,18 @@ struct altr_sdram_mc_data { | |||
296 | /* A10 ECC Controller memory initialization timeout */ | 316 | /* A10 ECC Controller memory initialization timeout */ |
297 | #define ALTR_A10_ECC_INIT_WATCHDOG_10US 10000 | 317 | #define ALTR_A10_ECC_INIT_WATCHDOG_10US 10000 |
298 | 318 | ||
319 | /************* Stratix10 Defines **************/ | ||
320 | |||
321 | /* Stratix10 ECC Manager Defines */ | ||
322 | #define S10_SYSMGR_ECC_INTMASK_VAL_OFST 0xFFD12090 | ||
323 | #define S10_SYSMGR_ECC_INTMASK_SET_OFST 0xFFD12094 | ||
324 | #define S10_SYSMGR_ECC_INTMASK_CLR_OFST 0xFFD12098 | ||
325 | |||
326 | #define S10_SYSMGR_ECC_INTSTAT_SERR_OFST 0xFFD1209C | ||
327 | #define S10_SYSMGR_ECC_INTSTAT_DERR_OFST 0xFFD120A0 | ||
328 | |||
329 | #define S10_DDR0_IRQ_MASK BIT(16) | ||
330 | |||
299 | struct altr_edac_device_dev; | 331 | struct altr_edac_device_dev; |
300 | 332 | ||
301 | struct edac_device_prv_data { | 333 | struct edac_device_prv_data { |
@@ -340,4 +372,78 @@ struct altr_arria10_edac { | |||
340 | struct list_head a10_ecc_devices; | 372 | struct list_head a10_ecc_devices; |
341 | }; | 373 | }; |
342 | 374 | ||
375 | /* | ||
376 | * Functions specified by ARM SMC Calling convention: | ||
377 | * | ||
378 | * FAST call executes atomic operations, returns when the requested operation | ||
379 | * has completed. | ||
380 | * STD call starts a operation which can be preempted by a non-secure | ||
381 | * interrupt. The call can return before the requested operation has | ||
382 | * completed. | ||
383 | * | ||
384 | * a0..a7 is used as register names in the descriptions below, on arm32 | ||
385 | * that translates to r0..r7 and on arm64 to w0..w7. | ||
386 | */ | ||
387 | |||
388 | #define INTEL_SIP_SMC_STD_CALL_VAL(func_num) \ | ||
389 | ARM_SMCCC_CALL_VAL(ARM_SMCCC_STD_CALL, ARM_SMCCC_SMC_64, \ | ||
390 | ARM_SMCCC_OWNER_SIP, (func_num)) | ||
391 | |||
392 | #define INTEL_SIP_SMC_FAST_CALL_VAL(func_num) \ | ||
393 | ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_64, \ | ||
394 | ARM_SMCCC_OWNER_SIP, (func_num)) | ||
395 | |||
396 | #define INTEL_SIP_SMC_RETURN_UNKNOWN_FUNCTION 0xFFFFFFFF | ||
397 | #define INTEL_SIP_SMC_STATUS_OK 0x0 | ||
398 | #define INTEL_SIP_SMC_REG_ERROR 0x5 | ||
399 | |||
400 | /* | ||
401 | * Request INTEL_SIP_SMC_REG_READ | ||
402 | * | ||
403 | * Read a protected register using SMCCC | ||
404 | * | ||
405 | * Call register usage: | ||
406 | * a0: INTEL_SIP_SMC_REG_READ. | ||
407 | * a1: register address. | ||
408 | * a2-7: not used. | ||
409 | * | ||
410 | * Return status: | ||
411 | * a0: INTEL_SIP_SMC_STATUS_OK, INTEL_SIP_SMC_REG_ERROR, or | ||
412 | * INTEL_SIP_SMC_RETURN_UNKNOWN_FUNCTION | ||
413 | * a1: Value in the register | ||
414 | * a2-3: not used. | ||
415 | */ | ||
416 | #define INTEL_SIP_SMC_FUNCID_REG_READ 7 | ||
417 | #define INTEL_SIP_SMC_REG_READ \ | ||
418 | INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_REG_READ) | ||
419 | |||
420 | /* | ||
421 | * Request INTEL_SIP_SMC_REG_WRITE | ||
422 | * | ||
423 | * Write a protected register using SMCCC | ||
424 | * | ||
425 | * Call register usage: | ||
426 | * a0: INTEL_SIP_SMC_REG_WRITE. | ||
427 | * a1: register address | ||
428 | * a2: value to program into register. | ||
429 | * a3-7: not used. | ||
430 | * | ||
431 | * Return status: | ||
432 | * a0: INTEL_SIP_SMC_STATUS_OK, INTEL_SIP_SMC_REG_ERROR, or | ||
433 | * INTEL_SIP_SMC_RETURN_UNKNOWN_FUNCTION | ||
434 | * a1-3: not used. | ||
435 | */ | ||
436 | #define INTEL_SIP_SMC_FUNCID_REG_WRITE 8 | ||
437 | #define INTEL_SIP_SMC_REG_WRITE \ | ||
438 | INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_REG_WRITE) | ||
439 | |||
440 | struct altr_stratix10_edac { | ||
441 | struct device *dev; | ||
442 | int sb_irq; | ||
443 | struct irq_domain *domain; | ||
444 | struct irq_chip irq_chip; | ||
445 | struct list_head s10_ecc_devices; | ||
446 | struct notifier_block panic_notifier; | ||
447 | }; | ||
448 | |||
343 | #endif /* #ifndef _ALTERA_EDAC_H */ | 449 | #endif /* #ifndef _ALTERA_EDAC_H */ |
diff --git a/drivers/edac/ghes_edac.c b/drivers/edac/ghes_edac.c index 68b6ee18bea6..473aeec4b1da 100644 --- a/drivers/edac/ghes_edac.c +++ b/drivers/edac/ghes_edac.c | |||
@@ -91,6 +91,7 @@ static void ghes_edac_dmidecode(const struct dmi_header *dh, void *arg) | |||
91 | struct dimm_info *dimm = EDAC_DIMM_PTR(mci->layers, mci->dimms, | 91 | struct dimm_info *dimm = EDAC_DIMM_PTR(mci->layers, mci->dimms, |
92 | mci->n_layers, | 92 | mci->n_layers, |
93 | dimm_fill->count, 0, 0); | 93 | dimm_fill->count, 0, 0); |
94 | u16 rdr_mask = BIT(7) | BIT(13); | ||
94 | 95 | ||
95 | if (entry->size == 0xffff) { | 96 | if (entry->size == 0xffff) { |
96 | pr_info("Can't get DIMM%i size\n", | 97 | pr_info("Can't get DIMM%i size\n", |
@@ -99,22 +100,21 @@ static void ghes_edac_dmidecode(const struct dmi_header *dh, void *arg) | |||
99 | } else if (entry->size == 0x7fff) { | 100 | } else if (entry->size == 0x7fff) { |
100 | dimm->nr_pages = MiB_TO_PAGES(entry->extended_size); | 101 | dimm->nr_pages = MiB_TO_PAGES(entry->extended_size); |
101 | } else { | 102 | } else { |
102 | if (entry->size & 1 << 15) | 103 | if (entry->size & BIT(15)) |
103 | dimm->nr_pages = MiB_TO_PAGES((entry->size & | 104 | dimm->nr_pages = MiB_TO_PAGES((entry->size & 0x7fff) << 10); |
104 | 0x7fff) << 10); | ||
105 | else | 105 | else |
106 | dimm->nr_pages = MiB_TO_PAGES(entry->size); | 106 | dimm->nr_pages = MiB_TO_PAGES(entry->size); |
107 | } | 107 | } |
108 | 108 | ||
109 | switch (entry->memory_type) { | 109 | switch (entry->memory_type) { |
110 | case 0x12: | 110 | case 0x12: |
111 | if (entry->type_detail & 1 << 13) | 111 | if (entry->type_detail & BIT(13)) |
112 | dimm->mtype = MEM_RDDR; | 112 | dimm->mtype = MEM_RDDR; |
113 | else | 113 | else |
114 | dimm->mtype = MEM_DDR; | 114 | dimm->mtype = MEM_DDR; |
115 | break; | 115 | break; |
116 | case 0x13: | 116 | case 0x13: |
117 | if (entry->type_detail & 1 << 13) | 117 | if (entry->type_detail & BIT(13)) |
118 | dimm->mtype = MEM_RDDR2; | 118 | dimm->mtype = MEM_RDDR2; |
119 | else | 119 | else |
120 | dimm->mtype = MEM_DDR2; | 120 | dimm->mtype = MEM_DDR2; |
@@ -123,20 +123,29 @@ static void ghes_edac_dmidecode(const struct dmi_header *dh, void *arg) | |||
123 | dimm->mtype = MEM_FB_DDR2; | 123 | dimm->mtype = MEM_FB_DDR2; |
124 | break; | 124 | break; |
125 | case 0x18: | 125 | case 0x18: |
126 | if (entry->type_detail & 1 << 13) | 126 | if (entry->type_detail & BIT(12)) |
127 | dimm->mtype = MEM_NVDIMM; | ||
128 | else if (entry->type_detail & BIT(13)) | ||
127 | dimm->mtype = MEM_RDDR3; | 129 | dimm->mtype = MEM_RDDR3; |
128 | else | 130 | else |
129 | dimm->mtype = MEM_DDR3; | 131 | dimm->mtype = MEM_DDR3; |
130 | break; | 132 | break; |
133 | case 0x1a: | ||
134 | if (entry->type_detail & BIT(12)) | ||
135 | dimm->mtype = MEM_NVDIMM; | ||
136 | else if (entry->type_detail & BIT(13)) | ||
137 | dimm->mtype = MEM_RDDR4; | ||
138 | else | ||
139 | dimm->mtype = MEM_DDR4; | ||
140 | break; | ||
131 | default: | 141 | default: |
132 | if (entry->type_detail & 1 << 6) | 142 | if (entry->type_detail & BIT(6)) |
133 | dimm->mtype = MEM_RMBS; | 143 | dimm->mtype = MEM_RMBS; |
134 | else if ((entry->type_detail & ((1 << 7) | (1 << 13))) | 144 | else if ((entry->type_detail & rdr_mask) == rdr_mask) |
135 | == ((1 << 7) | (1 << 13))) | ||
136 | dimm->mtype = MEM_RDR; | 145 | dimm->mtype = MEM_RDR; |
137 | else if (entry->type_detail & 1 << 7) | 146 | else if (entry->type_detail & BIT(7)) |
138 | dimm->mtype = MEM_SDR; | 147 | dimm->mtype = MEM_SDR; |
139 | else if (entry->type_detail & 1 << 9) | 148 | else if (entry->type_detail & BIT(9)) |
140 | dimm->mtype = MEM_EDO; | 149 | dimm->mtype = MEM_EDO; |
141 | else | 150 | else |
142 | dimm->mtype = MEM_UNKNOWN; | 151 | dimm->mtype = MEM_UNKNOWN; |
@@ -172,8 +181,7 @@ static void ghes_edac_dmidecode(const struct dmi_header *dh, void *arg) | |||
172 | } | 181 | } |
173 | } | 182 | } |
174 | 183 | ||
175 | void ghes_edac_report_mem_error(struct ghes *ghes, int sev, | 184 | void ghes_edac_report_mem_error(int sev, struct cper_sec_mem_err *mem_err) |
176 | struct cper_sec_mem_err *mem_err) | ||
177 | { | 185 | { |
178 | enum hw_event_mc_err_type type; | 186 | enum hw_event_mc_err_type type; |
179 | struct edac_raw_error_desc *e; | 187 | struct edac_raw_error_desc *e; |
@@ -183,10 +191,8 @@ void ghes_edac_report_mem_error(struct ghes *ghes, int sev, | |||
183 | char *p; | 191 | char *p; |
184 | u8 grain_bits; | 192 | u8 grain_bits; |
185 | 193 | ||
186 | if (!pvt) { | 194 | if (!pvt) |
187 | pr_err("Internal error: Can't find EDAC structure\n"); | ||
188 | return; | 195 | return; |
189 | } | ||
190 | 196 | ||
191 | /* | 197 | /* |
192 | * We can do the locking below because GHES defers error processing | 198 | * We can do the locking below because GHES defers error processing |
@@ -434,12 +440,16 @@ int ghes_edac_register(struct ghes *ghes, struct device *dev) | |||
434 | struct mem_ctl_info *mci; | 440 | struct mem_ctl_info *mci; |
435 | struct edac_mc_layer layers[1]; | 441 | struct edac_mc_layer layers[1]; |
436 | struct ghes_edac_dimm_fill dimm_fill; | 442 | struct ghes_edac_dimm_fill dimm_fill; |
437 | int idx; | 443 | int idx = -1; |
438 | 444 | ||
439 | /* Check if safe to enable on this system */ | 445 | if (IS_ENABLED(CONFIG_X86)) { |
440 | idx = acpi_match_platform_list(plat_list); | 446 | /* Check if safe to enable on this system */ |
441 | if (!force_load && idx < 0) | 447 | idx = acpi_match_platform_list(plat_list); |
442 | return 0; | 448 | if (!force_load && idx < 0) |
449 | return -ENODEV; | ||
450 | } else { | ||
451 | idx = 0; | ||
452 | } | ||
443 | 453 | ||
444 | /* | 454 | /* |
445 | * We have only one logical memory controller to which all DIMMs belong. | 455 | * We have only one logical memory controller to which all DIMMs belong. |
@@ -519,6 +529,9 @@ void ghes_edac_unregister(struct ghes *ghes) | |||
519 | { | 529 | { |
520 | struct mem_ctl_info *mci; | 530 | struct mem_ctl_info *mci; |
521 | 531 | ||
532 | if (!ghes_pvt) | ||
533 | return; | ||
534 | |||
522 | mci = ghes_pvt->mci; | 535 | mci = ghes_pvt->mci; |
523 | edac_mc_del_mc(mci->pdev); | 536 | edac_mc_del_mc(mci->pdev); |
524 | edac_mc_free(mci); | 537 | edac_mc_free(mci); |
diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index 8c5540160a23..4d0ea3563d47 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c | |||
@@ -1743,7 +1743,7 @@ static void i7core_mce_output_error(struct mem_ctl_info *mci, | |||
1743 | err = "write parity error"; | 1743 | err = "write parity error"; |
1744 | break; | 1744 | break; |
1745 | case 19: | 1745 | case 19: |
1746 | err = "redundacy loss"; | 1746 | err = "redundancy loss"; |
1747 | break; | 1747 | break; |
1748 | case 20: | 1748 | case 20: |
1749 | err = "reserved"; | 1749 | err = "reserved"; |
diff --git a/include/acpi/ghes.h b/include/acpi/ghes.h index 8feb0c866ee0..1624e2be485c 100644 --- a/include/acpi/ghes.h +++ b/include/acpi/ghes.h | |||
@@ -55,22 +55,21 @@ enum { | |||
55 | /* From drivers/edac/ghes_edac.c */ | 55 | /* From drivers/edac/ghes_edac.c */ |
56 | 56 | ||
57 | #ifdef CONFIG_EDAC_GHES | 57 | #ifdef CONFIG_EDAC_GHES |
58 | void ghes_edac_report_mem_error(struct ghes *ghes, int sev, | 58 | void ghes_edac_report_mem_error(int sev, struct cper_sec_mem_err *mem_err); |
59 | struct cper_sec_mem_err *mem_err); | ||
60 | 59 | ||
61 | int ghes_edac_register(struct ghes *ghes, struct device *dev); | 60 | int ghes_edac_register(struct ghes *ghes, struct device *dev); |
62 | 61 | ||
63 | void ghes_edac_unregister(struct ghes *ghes); | 62 | void ghes_edac_unregister(struct ghes *ghes); |
64 | 63 | ||
65 | #else | 64 | #else |
66 | static inline void ghes_edac_report_mem_error(struct ghes *ghes, int sev, | 65 | static inline void ghes_edac_report_mem_error(int sev, |
67 | struct cper_sec_mem_err *mem_err) | 66 | struct cper_sec_mem_err *mem_err) |
68 | { | 67 | { |
69 | } | 68 | } |
70 | 69 | ||
71 | static inline int ghes_edac_register(struct ghes *ghes, struct device *dev) | 70 | static inline int ghes_edac_register(struct ghes *ghes, struct device *dev) |
72 | { | 71 | { |
73 | return 0; | 72 | return -ENODEV; |
74 | } | 73 | } |
75 | 74 | ||
76 | static inline void ghes_edac_unregister(struct ghes *ghes) | 75 | static inline void ghes_edac_unregister(struct ghes *ghes) |