47
47
#define MLXBF_EDAC_MAX_DIMM_PER_MC 2
48
48
#define MLXBF_EDAC_ERROR_GRAIN 8
49
49
50
+ #define MLXBF_WRITE_REG_32 (0x82000009)
51
+ #define MLXBF_READ_REG_32 (0x8200000A)
52
+ #define MLXBF_SIP_SVC_VERSION (0x8200ff03)
53
+
54
+ #define MLXBF_SMCCC_ACCESS_VIOLATION (-4)
55
+
56
+ #define MLXBF_SVC_REQ_MAJOR 0
57
+ #define MLXBF_SVC_REQ_MINOR 3
58
+
50
59
/*
51
- * Request MLNX_SIP_GET_DIMM_INFO
60
+ * Request MLXBF_SIP_GET_DIMM_INFO
52
61
*
53
62
* Retrieve information about DIMM on a certain slot.
54
63
*
55
64
* Call register usage:
56
- * a0: MLNX_SIP_GET_DIMM_INFO
65
+ * a0: MLXBF_SIP_GET_DIMM_INFO
57
66
* a1: (Memory controller index) << 16 | (Dimm index in memory controller)
58
67
* a2-7: not used.
59
68
*
60
69
* Return status:
61
70
* a0: MLXBF_DIMM_INFO defined below describing the DIMM.
62
71
* a1-3: not used.
63
72
*/
64
- #define MLNX_SIP_GET_DIMM_INFO 0x82000008
73
+ #define MLXBF_SIP_GET_DIMM_INFO 0x82000008
65
74
66
75
/* Format for the SMC response about the memory information */
67
76
#define MLXBF_DIMM_INFO__SIZE_GB GENMASK_ULL(15, 0)
72
81
#define MLXBF_DIMM_INFO__PACKAGE_X GENMASK_ULL(31, 24)
73
82
74
83
struct bluefield_edac_priv {
84
+ /* pointer to device structure */
85
+ struct device * dev ;
75
86
int dimm_ranks [MLXBF_EDAC_MAX_DIMM_PER_MC ];
76
87
void __iomem * emi_base ;
77
88
int dimm_per_mc ;
89
+ /* access to secure regs supported */
90
+ bool svc_sreg_support ;
91
+ /* SMC table# for secure regs access */
92
+ u32 sreg_tbl ;
78
93
};
79
94
80
95
static u64 smc_call1 (u64 smc_op , u64 smc_arg )
@@ -86,6 +101,71 @@ static u64 smc_call1(u64 smc_op, u64 smc_arg)
86
101
return res .a0 ;
87
102
}
88
103
104
+ static int secure_readl (void __iomem * addr , u32 * result , u32 sreg_tbl )
105
+ {
106
+ struct arm_smccc_res res ;
107
+ int status ;
108
+
109
+ arm_smccc_smc (MLXBF_READ_REG_32 , sreg_tbl , (uintptr_t )addr ,
110
+ 0 , 0 , 0 , 0 , 0 , & res );
111
+
112
+ status = res .a0 ;
113
+
114
+ if (status == SMCCC_RET_NOT_SUPPORTED ||
115
+ status == MLXBF_SMCCC_ACCESS_VIOLATION )
116
+ return -1 ;
117
+
118
+ * result = (u32 )res .a1 ;
119
+ return 0 ;
120
+ }
121
+
122
+ static int secure_writel (void __iomem * addr , u32 data , u32 sreg_tbl )
123
+ {
124
+ struct arm_smccc_res res ;
125
+ int status ;
126
+
127
+ arm_smccc_smc (MLXBF_WRITE_REG_32 , sreg_tbl , data , (uintptr_t )addr ,
128
+ 0 , 0 , 0 , 0 , & res );
129
+
130
+ status = res .a0 ;
131
+
132
+ if (status == SMCCC_RET_NOT_SUPPORTED ||
133
+ status == MLXBF_SMCCC_ACCESS_VIOLATION )
134
+ return -1 ;
135
+ else
136
+ return 0 ;
137
+ }
138
+
139
+ static int bluefield_edac_readl (struct bluefield_edac_priv * priv , u32 offset , u32 * result )
140
+ {
141
+ void __iomem * addr ;
142
+ int err = 0 ;
143
+
144
+ addr = priv -> emi_base + offset ;
145
+
146
+ if (priv -> svc_sreg_support )
147
+ err = secure_readl (addr , result , priv -> sreg_tbl );
148
+ else
149
+ * result = readl (addr );
150
+
151
+ return err ;
152
+ }
153
+
154
+ static int bluefield_edac_writel (struct bluefield_edac_priv * priv , u32 offset , u32 data )
155
+ {
156
+ void __iomem * addr ;
157
+ int err = 0 ;
158
+
159
+ addr = priv -> emi_base + offset ;
160
+
161
+ if (priv -> svc_sreg_support )
162
+ err = secure_writel (addr , data , priv -> sreg_tbl );
163
+ else
164
+ writel (data , addr );
165
+
166
+ return err ;
167
+ }
168
+
89
169
/*
90
170
* Gather the ECC information from the External Memory Interface registers
91
171
* and report it to the edac handler.
@@ -99,7 +179,7 @@ static void bluefield_gather_report_ecc(struct mem_ctl_info *mci,
99
179
u32 ecc_latch_select , dram_syndrom , serr , derr , syndrom ;
100
180
enum hw_event_mc_err_type ecc_type ;
101
181
u64 ecc_dimm_addr ;
102
- int ecc_dimm ;
182
+ int ecc_dimm , err ;
103
183
104
184
ecc_type = is_single_ecc ? HW_EVENT_ERR_CORRECTED :
105
185
HW_EVENT_ERR_UNCORRECTED ;
@@ -109,14 +189,19 @@ static void bluefield_gather_report_ecc(struct mem_ctl_info *mci,
109
189
* registers with information about the last ECC error occurrence.
110
190
*/
111
191
ecc_latch_select = MLXBF_ECC_LATCH_SEL__START ;
112
- writel (ecc_latch_select , priv -> emi_base + MLXBF_ECC_LATCH_SEL );
192
+ err = bluefield_edac_writel (priv , MLXBF_ECC_LATCH_SEL , ecc_latch_select );
193
+ if (err )
194
+ dev_err (priv -> dev , "ECC latch select write failed.\n" );
113
195
114
196
/*
115
197
* Verify that the ECC reported info in the registers is of the
116
198
* same type as the one asked to report. If not, just report the
117
199
* error without the detailed information.
118
200
*/
119
- dram_syndrom = readl (priv -> emi_base + MLXBF_SYNDROM );
201
+ err = bluefield_edac_readl (priv , MLXBF_SYNDROM , & dram_syndrom );
202
+ if (err )
203
+ dev_err (priv -> dev , "DRAM syndrom read failed.\n" );
204
+
120
205
serr = FIELD_GET (MLXBF_SYNDROM__SERR , dram_syndrom );
121
206
derr = FIELD_GET (MLXBF_SYNDROM__DERR , dram_syndrom );
122
207
syndrom = FIELD_GET (MLXBF_SYNDROM__SYN , dram_syndrom );
@@ -127,13 +212,21 @@ static void bluefield_gather_report_ecc(struct mem_ctl_info *mci,
127
212
return ;
128
213
}
129
214
130
- dram_additional_info = readl (priv -> emi_base + MLXBF_ADD_INFO );
215
+ err = bluefield_edac_readl (priv , MLXBF_ADD_INFO , & dram_additional_info );
216
+ if (err )
217
+ dev_err (priv -> dev , "DRAM additional info read failed.\n" );
218
+
131
219
err_prank = FIELD_GET (MLXBF_ADD_INFO__ERR_PRANK , dram_additional_info );
132
220
133
221
ecc_dimm = (err_prank >= 2 && priv -> dimm_ranks [0 ] <= 2 ) ? 1 : 0 ;
134
222
135
- edea0 = readl (priv -> emi_base + MLXBF_ERR_ADDR_0 );
136
- edea1 = readl (priv -> emi_base + MLXBF_ERR_ADDR_1 );
223
+ err = bluefield_edac_readl (priv , MLXBF_ERR_ADDR_0 , & edea0 );
224
+ if (err )
225
+ dev_err (priv -> dev , "Error addr 0 read failed.\n" );
226
+
227
+ err = bluefield_edac_readl (priv , MLXBF_ERR_ADDR_1 , & edea1 );
228
+ if (err )
229
+ dev_err (priv -> dev , "Error addr 1 read failed.\n" );
137
230
138
231
ecc_dimm_addr = ((u64 )edea1 << 32 ) | edea0 ;
139
232
@@ -147,6 +240,7 @@ static void bluefield_edac_check(struct mem_ctl_info *mci)
147
240
{
148
241
struct bluefield_edac_priv * priv = mci -> pvt_info ;
149
242
u32 ecc_count , single_error_count , double_error_count , ecc_error = 0 ;
243
+ int err ;
150
244
151
245
/*
152
246
* The memory controller might not be initialized by the firmware
@@ -155,7 +249,10 @@ static void bluefield_edac_check(struct mem_ctl_info *mci)
155
249
if (mci -> edac_cap == EDAC_FLAG_NONE )
156
250
return ;
157
251
158
- ecc_count = readl (priv -> emi_base + MLXBF_ECC_CNT );
252
+ err = bluefield_edac_readl (priv , MLXBF_ECC_CNT , & ecc_count );
253
+ if (err )
254
+ dev_err (priv -> dev , "ECC count read failed.\n" );
255
+
159
256
single_error_count = FIELD_GET (MLXBF_ECC_CNT__SERR_CNT , ecc_count );
160
257
double_error_count = FIELD_GET (MLXBF_ECC_CNT__DERR_CNT , ecc_count );
161
258
@@ -172,15 +269,18 @@ static void bluefield_edac_check(struct mem_ctl_info *mci)
172
269
}
173
270
174
271
/* Write to clear reported errors. */
175
- if (ecc_count )
176
- writel (ecc_error , priv -> emi_base + MLXBF_ECC_ERR );
272
+ if (ecc_count ) {
273
+ err = bluefield_edac_writel (priv , MLXBF_ECC_ERR , ecc_error );
274
+ if (err )
275
+ dev_err (priv -> dev , "ECC Error write failed.\n" );
276
+ }
177
277
}
178
278
179
279
/* Initialize the DIMMs information for the given memory controller. */
180
280
static void bluefield_edac_init_dimms (struct mem_ctl_info * mci )
181
281
{
182
282
struct bluefield_edac_priv * priv = mci -> pvt_info ;
183
- int mem_ctrl_idx = mci -> mc_idx ;
283
+ u64 mem_ctrl_idx = mci -> mc_idx ;
184
284
struct dimm_info * dimm ;
185
285
u64 smc_info , smc_arg ;
186
286
int is_empty = 1 , i ;
@@ -189,7 +289,7 @@ static void bluefield_edac_init_dimms(struct mem_ctl_info *mci)
189
289
dimm = mci -> dimms [i ];
190
290
191
291
smc_arg = mem_ctrl_idx << 16 | i ;
192
- smc_info = smc_call1 (MLNX_SIP_GET_DIMM_INFO , smc_arg );
292
+ smc_info = smc_call1 (MLXBF_SIP_GET_DIMM_INFO , smc_arg );
193
293
194
294
if (!FIELD_GET (MLXBF_DIMM_INFO__SIZE_GB , smc_info )) {
195
295
dimm -> mtype = MEM_EMPTY ;
@@ -244,6 +344,7 @@ static int bluefield_edac_mc_probe(struct platform_device *pdev)
244
344
struct bluefield_edac_priv * priv ;
245
345
struct device * dev = & pdev -> dev ;
246
346
struct edac_mc_layer layers [1 ];
347
+ struct arm_smccc_res res ;
247
348
struct mem_ctl_info * mci ;
248
349
struct resource * emi_res ;
249
350
unsigned int mc_idx , dimm_count ;
@@ -279,13 +380,43 @@ static int bluefield_edac_mc_probe(struct platform_device *pdev)
279
380
return - ENOMEM ;
280
381
281
382
priv = mci -> pvt_info ;
383
+ priv -> dev = dev ;
384
+
385
+ /*
386
+ * The "sec_reg_block" property in the ACPI table determines the method
387
+ * the driver uses to access the EMI registers:
388
+ * a) property is not present - directly access registers via readl/writel
389
+ * b) property is present - indirectly access registers via SMC calls
390
+ * (assuming required Silicon Provider service version found)
391
+ */
392
+ if (device_property_read_u32 (dev , "sec_reg_block" , & priv -> sreg_tbl )) {
393
+ priv -> svc_sreg_support = false;
394
+ } else {
395
+ /*
396
+ * Check for minimum required Arm Silicon Provider (SiP) service
397
+ * version, ensuring support of required SMC function IDs.
398
+ */
399
+ arm_smccc_smc (MLXBF_SIP_SVC_VERSION , 0 , 0 , 0 , 0 , 0 , 0 , 0 , & res );
400
+ if (res .a0 == MLXBF_SVC_REQ_MAJOR &&
401
+ res .a1 >= MLXBF_SVC_REQ_MINOR ) {
402
+ priv -> svc_sreg_support = true;
403
+ } else {
404
+ dev_err (dev , "Required SMCs are not supported.\n" );
405
+ ret = - EINVAL ;
406
+ goto err ;
407
+ }
408
+ }
282
409
283
410
priv -> dimm_per_mc = dimm_count ;
284
- priv -> emi_base = devm_ioremap_resource (dev , emi_res );
285
- if (IS_ERR (priv -> emi_base )) {
286
- dev_err (dev , "failed to map EMI IO resource\n" );
287
- ret = PTR_ERR (priv -> emi_base );
288
- goto err ;
411
+ if (!priv -> svc_sreg_support ) {
412
+ priv -> emi_base = devm_ioremap_resource (dev , emi_res );
413
+ if (IS_ERR (priv -> emi_base )) {
414
+ dev_err (dev , "failed to map EMI IO resource\n" );
415
+ ret = PTR_ERR (priv -> emi_base );
416
+ goto err ;
417
+ }
418
+ } else {
419
+ priv -> emi_base = (void __iomem * )emi_res -> start ;
289
420
}
290
421
291
422
mci -> pdev = dev ;
@@ -320,7 +451,6 @@ static int bluefield_edac_mc_probe(struct platform_device *pdev)
320
451
edac_mc_free (mci );
321
452
322
453
return ret ;
323
-
324
454
}
325
455
326
456
static void bluefield_edac_mc_remove (struct platform_device * pdev )
0 commit comments