4747#define MLXBF_EDAC_MAX_DIMM_PER_MC 2
4848#define MLXBF_EDAC_ERROR_GRAIN 8
4949
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+
5059/*
51- * Request MLNX_SIP_GET_DIMM_INFO
60+ * Request MLXBF_SIP_GET_DIMM_INFO
5261 *
5362 * Retrieve information about DIMM on a certain slot.
5463 *
5564 * Call register usage:
56- * a0: MLNX_SIP_GET_DIMM_INFO
65+ * a0: MLXBF_SIP_GET_DIMM_INFO
5766 * a1: (Memory controller index) << 16 | (Dimm index in memory controller)
5867 * a2-7: not used.
5968 *
6069 * Return status:
6170 * a0: MLXBF_DIMM_INFO defined below describing the DIMM.
6271 * a1-3: not used.
6372 */
64- #define MLNX_SIP_GET_DIMM_INFO 0x82000008
73+ #define MLXBF_SIP_GET_DIMM_INFO 0x82000008
6574
6675/* Format for the SMC response about the memory information */
6776#define MLXBF_DIMM_INFO__SIZE_GB GENMASK_ULL(15, 0)
7281#define MLXBF_DIMM_INFO__PACKAGE_X GENMASK_ULL(31, 24)
7382
7483struct bluefield_edac_priv {
84+ /* pointer to device structure */
85+ struct device * dev ;
7586 int dimm_ranks [MLXBF_EDAC_MAX_DIMM_PER_MC ];
7687 void __iomem * emi_base ;
7788 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 ;
7893};
7994
8095static u64 smc_call1 (u64 smc_op , u64 smc_arg )
@@ -86,6 +101,71 @@ static u64 smc_call1(u64 smc_op, u64 smc_arg)
86101 return res .a0 ;
87102}
88103
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+
89169/*
90170 * Gather the ECC information from the External Memory Interface registers
91171 * and report it to the edac handler.
@@ -99,7 +179,7 @@ static void bluefield_gather_report_ecc(struct mem_ctl_info *mci,
99179 u32 ecc_latch_select , dram_syndrom , serr , derr , syndrom ;
100180 enum hw_event_mc_err_type ecc_type ;
101181 u64 ecc_dimm_addr ;
102- int ecc_dimm ;
182+ int ecc_dimm , err ;
103183
104184 ecc_type = is_single_ecc ? HW_EVENT_ERR_CORRECTED :
105185 HW_EVENT_ERR_UNCORRECTED ;
@@ -109,14 +189,21 @@ static void bluefield_gather_report_ecc(struct mem_ctl_info *mci,
109189 * registers with information about the last ECC error occurrence.
110190 */
111191 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" );
113195
114196 /*
115197 * Verify that the ECC reported info in the registers is of the
116198 * same type as the one asked to report. If not, just report the
117199 * error without the detailed information.
118200 */
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+ return ;
205+ }
206+
120207 serr = FIELD_GET (MLXBF_SYNDROM__SERR , dram_syndrom );
121208 derr = FIELD_GET (MLXBF_SYNDROM__DERR , dram_syndrom );
122209 syndrom = FIELD_GET (MLXBF_SYNDROM__SYN , dram_syndrom );
@@ -127,13 +214,27 @@ static void bluefield_gather_report_ecc(struct mem_ctl_info *mci,
127214 return ;
128215 }
129216
130- dram_additional_info = readl (priv -> emi_base + MLXBF_ADD_INFO );
217+ err = bluefield_edac_readl (priv , MLXBF_ADD_INFO , & dram_additional_info );
218+ if (err ) {
219+ dev_err (priv -> dev , "DRAM additional info read failed.\n" );
220+ return ;
221+ }
222+
131223 err_prank = FIELD_GET (MLXBF_ADD_INFO__ERR_PRANK , dram_additional_info );
132224
133225 ecc_dimm = (err_prank >= 2 && priv -> dimm_ranks [0 ] <= 2 ) ? 1 : 0 ;
134226
135- edea0 = readl (priv -> emi_base + MLXBF_ERR_ADDR_0 );
136- edea1 = readl (priv -> emi_base + MLXBF_ERR_ADDR_1 );
227+ err = bluefield_edac_readl (priv , MLXBF_ERR_ADDR_0 , & edea0 );
228+ if (err ) {
229+ dev_err (priv -> dev , "Error addr 0 read failed.\n" );
230+ return ;
231+ }
232+
233+ err = bluefield_edac_readl (priv , MLXBF_ERR_ADDR_1 , & edea1 );
234+ if (err ) {
235+ dev_err (priv -> dev , "Error addr 1 read failed.\n" );
236+ return ;
237+ }
137238
138239 ecc_dimm_addr = ((u64 )edea1 << 32 ) | edea0 ;
139240
@@ -147,6 +248,7 @@ static void bluefield_edac_check(struct mem_ctl_info *mci)
147248{
148249 struct bluefield_edac_priv * priv = mci -> pvt_info ;
149250 u32 ecc_count , single_error_count , double_error_count , ecc_error = 0 ;
251+ int err ;
150252
151253 /*
152254 * The memory controller might not be initialized by the firmware
@@ -155,7 +257,12 @@ static void bluefield_edac_check(struct mem_ctl_info *mci)
155257 if (mci -> edac_cap == EDAC_FLAG_NONE )
156258 return ;
157259
158- ecc_count = readl (priv -> emi_base + MLXBF_ECC_CNT );
260+ err = bluefield_edac_readl (priv , MLXBF_ECC_CNT , & ecc_count );
261+ if (err ) {
262+ dev_err (priv -> dev , "ECC count read failed.\n" );
263+ return ;
264+ }
265+
159266 single_error_count = FIELD_GET (MLXBF_ECC_CNT__SERR_CNT , ecc_count );
160267 double_error_count = FIELD_GET (MLXBF_ECC_CNT__DERR_CNT , ecc_count );
161268
@@ -172,15 +279,18 @@ static void bluefield_edac_check(struct mem_ctl_info *mci)
172279 }
173280
174281 /* Write to clear reported errors. */
175- if (ecc_count )
176- writel (ecc_error , priv -> emi_base + MLXBF_ECC_ERR );
282+ if (ecc_count ) {
283+ err = bluefield_edac_writel (priv , MLXBF_ECC_ERR , ecc_error );
284+ if (err )
285+ dev_err (priv -> dev , "ECC Error write failed.\n" );
286+ }
177287}
178288
179289/* Initialize the DIMMs information for the given memory controller. */
180290static void bluefield_edac_init_dimms (struct mem_ctl_info * mci )
181291{
182292 struct bluefield_edac_priv * priv = mci -> pvt_info ;
183- int mem_ctrl_idx = mci -> mc_idx ;
293+ u64 mem_ctrl_idx = mci -> mc_idx ;
184294 struct dimm_info * dimm ;
185295 u64 smc_info , smc_arg ;
186296 int is_empty = 1 , i ;
@@ -189,7 +299,7 @@ static void bluefield_edac_init_dimms(struct mem_ctl_info *mci)
189299 dimm = mci -> dimms [i ];
190300
191301 smc_arg = mem_ctrl_idx << 16 | i ;
192- smc_info = smc_call1 (MLNX_SIP_GET_DIMM_INFO , smc_arg );
302+ smc_info = smc_call1 (MLXBF_SIP_GET_DIMM_INFO , smc_arg );
193303
194304 if (!FIELD_GET (MLXBF_DIMM_INFO__SIZE_GB , smc_info )) {
195305 dimm -> mtype = MEM_EMPTY ;
@@ -244,6 +354,7 @@ static int bluefield_edac_mc_probe(struct platform_device *pdev)
244354 struct bluefield_edac_priv * priv ;
245355 struct device * dev = & pdev -> dev ;
246356 struct edac_mc_layer layers [1 ];
357+ struct arm_smccc_res res ;
247358 struct mem_ctl_info * mci ;
248359 struct resource * emi_res ;
249360 unsigned int mc_idx , dimm_count ;
@@ -279,13 +390,43 @@ static int bluefield_edac_mc_probe(struct platform_device *pdev)
279390 return - ENOMEM ;
280391
281392 priv = mci -> pvt_info ;
393+ priv -> dev = dev ;
394+
395+ /*
396+ * The "sec_reg_block" property in the ACPI table determines the method
397+ * the driver uses to access the EMI registers:
398+ * a) property is not present - directly access registers via readl/writel
399+ * b) property is present - indirectly access registers via SMC calls
400+ * (assuming required Silicon Provider service version found)
401+ */
402+ if (device_property_read_u32 (dev , "sec_reg_block" , & priv -> sreg_tbl )) {
403+ priv -> svc_sreg_support = false;
404+ } else {
405+ /*
406+ * Check for minimum required Arm Silicon Provider (SiP) service
407+ * version, ensuring support of required SMC function IDs.
408+ */
409+ arm_smccc_smc (MLXBF_SIP_SVC_VERSION , 0 , 0 , 0 , 0 , 0 , 0 , 0 , & res );
410+ if (res .a0 == MLXBF_SVC_REQ_MAJOR &&
411+ res .a1 >= MLXBF_SVC_REQ_MINOR ) {
412+ priv -> svc_sreg_support = true;
413+ } else {
414+ dev_err (dev , "Required SMCs are not supported.\n" );
415+ ret = - EINVAL ;
416+ goto err ;
417+ }
418+ }
282419
283420 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 ;
421+ if (!priv -> svc_sreg_support ) {
422+ priv -> emi_base = devm_ioremap_resource (dev , emi_res );
423+ if (IS_ERR (priv -> emi_base )) {
424+ dev_err (dev , "failed to map EMI IO resource\n" );
425+ ret = PTR_ERR (priv -> emi_base );
426+ goto err ;
427+ }
428+ } else {
429+ priv -> emi_base = (void __iomem * )emi_res -> start ;
289430 }
290431
291432 mci -> pdev = dev ;
@@ -320,7 +461,6 @@ static int bluefield_edac_mc_probe(struct platform_device *pdev)
320461 edac_mc_free (mci );
321462
322463 return ret ;
323-
324464}
325465
326466static void bluefield_edac_mc_remove (struct platform_device * pdev )
0 commit comments