@@ -2146,6 +2146,35 @@ static const struct irq_domain_ops a10_eccmgr_ic_ops = {
2146
2146
.xlate = irq_domain_xlate_twocell ,
2147
2147
};
2148
2148
2149
+ /************** Stratix 10 EDAC Double Bit Error Handler ************/
2150
+ #define to_a10edac (p , m ) container_of(p, struct altr_arria10_edac, m)
2151
+
2152
+ /*
2153
+ * The double bit error is handled through SError which is fatal. This is
2154
+ * called as a panic notifier to printout ECC error info as part of the panic.
2155
+ */
2156
+ static int s10_edac_dberr_handler (struct notifier_block * this ,
2157
+ unsigned long event , void * ptr )
2158
+ {
2159
+ struct altr_arria10_edac * edac = to_a10edac (this , panic_notifier );
2160
+ int err_addr , dberror ;
2161
+
2162
+ regmap_read (edac -> ecc_mgr_map , S10_SYSMGR_ECC_INTSTAT_DERR_OFST ,
2163
+ & dberror );
2164
+ regmap_write (edac -> ecc_mgr_map , S10_SYSMGR_UE_VAL_OFST , dberror );
2165
+ if (dberror & S10_DDR0_IRQ_MASK ) {
2166
+ regmap_read (edac -> ecc_mgr_map , S10_DERRADDR_OFST , & err_addr );
2167
+ regmap_write (edac -> ecc_mgr_map , S10_SYSMGR_UE_ADDR_OFST ,
2168
+ err_addr );
2169
+ edac_printk (KERN_ERR , EDAC_MC ,
2170
+ "EDAC: [Uncorrectable errors @ 0x%08X]\n\n" ,
2171
+ err_addr );
2172
+ }
2173
+
2174
+ return NOTIFY_DONE ;
2175
+ }
2176
+
2177
+ /****************** Arria 10 EDAC Probe Function *********************/
2149
2178
static int altr_edac_a10_probe (struct platform_device * pdev )
2150
2179
{
2151
2180
struct altr_arria10_edac * edac ;
@@ -2159,8 +2188,33 @@ static int altr_edac_a10_probe(struct platform_device *pdev)
2159
2188
platform_set_drvdata (pdev , edac );
2160
2189
INIT_LIST_HEAD (& edac -> a10_ecc_devices );
2161
2190
2162
- edac -> ecc_mgr_map = syscon_regmap_lookup_by_phandle (pdev -> dev .of_node ,
2191
+ if (socfpga_is_a10 ()) {
2192
+ edac -> ecc_mgr_map =
2193
+ syscon_regmap_lookup_by_phandle (pdev -> dev .of_node ,
2163
2194
"altr,sysmgr-syscon" );
2195
+ } else {
2196
+ struct device_node * sysmgr_np ;
2197
+ struct resource res ;
2198
+ void __iomem * base ;
2199
+
2200
+ sysmgr_np = of_parse_phandle (pdev -> dev .of_node ,
2201
+ "altr,sysmgr-syscon" , 0 );
2202
+ if (!sysmgr_np ) {
2203
+ edac_printk (KERN_ERR , EDAC_DEVICE ,
2204
+ "Unable to find altr,sysmgr-syscon\n" );
2205
+ return - ENODEV ;
2206
+ }
2207
+
2208
+ if (of_address_to_resource (sysmgr_np , 0 , & res ))
2209
+ return - ENOMEM ;
2210
+
2211
+ /* Need physical address for SMCC call */
2212
+ base = (void __iomem * )res .start ;
2213
+
2214
+ edac -> ecc_mgr_map = devm_regmap_init (& pdev -> dev , NULL , base ,
2215
+ & s10_sdram_regmap_cfg );
2216
+ }
2217
+
2164
2218
if (IS_ERR (edac -> ecc_mgr_map )) {
2165
2219
edac_printk (KERN_ERR , EDAC_DEVICE ,
2166
2220
"Unable to get syscon altr,sysmgr-syscon\n" );
@@ -2187,14 +2241,38 @@ static int altr_edac_a10_probe(struct platform_device *pdev)
2187
2241
altr_edac_a10_irq_handler ,
2188
2242
edac );
2189
2243
2190
- edac -> db_irq = platform_get_irq (pdev , 1 );
2191
- if (edac -> db_irq < 0 ) {
2192
- dev_err (& pdev -> dev , "No DBERR IRQ resource\n" );
2193
- return edac -> db_irq ;
2244
+ if (socfpga_is_a10 ()) {
2245
+ edac -> db_irq = platform_get_irq (pdev , 1 );
2246
+ if (edac -> db_irq < 0 ) {
2247
+ dev_err (& pdev -> dev , "No DBERR IRQ resource\n" );
2248
+ return edac -> db_irq ;
2249
+ }
2250
+ irq_set_chained_handler_and_data (edac -> db_irq ,
2251
+ altr_edac_a10_irq_handler ,
2252
+ edac );
2253
+ } else {
2254
+ int dberror , err_addr ;
2255
+
2256
+ edac -> panic_notifier .notifier_call = s10_edac_dberr_handler ;
2257
+ atomic_notifier_chain_register (& panic_notifier_list ,
2258
+ & edac -> panic_notifier );
2259
+
2260
+ /* Printout a message if uncorrectable error previously. */
2261
+ regmap_read (edac -> ecc_mgr_map , S10_SYSMGR_UE_VAL_OFST ,
2262
+ & dberror );
2263
+ if (dberror ) {
2264
+ regmap_read (edac -> ecc_mgr_map , S10_SYSMGR_UE_ADDR_OFST ,
2265
+ & err_addr );
2266
+ edac_printk (KERN_ERR , EDAC_DEVICE ,
2267
+ "Previous Boot UE detected[0x%X] @ 0x%X\n" ,
2268
+ dberror , err_addr );
2269
+ /* Reset the sticky registers */
2270
+ regmap_write (edac -> ecc_mgr_map ,
2271
+ S10_SYSMGR_UE_VAL_OFST , 0 );
2272
+ regmap_write (edac -> ecc_mgr_map ,
2273
+ S10_SYSMGR_UE_ADDR_OFST , 0 );
2274
+ }
2194
2275
}
2195
- irq_set_chained_handler_and_data (edac -> db_irq ,
2196
- altr_edac_a10_irq_handler ,
2197
- edac );
2198
2276
2199
2277
for_each_child_of_node (pdev -> dev .of_node , child ) {
2200
2278
if (!of_device_is_available (child ))
@@ -2211,7 +2289,8 @@ static int altr_edac_a10_probe(struct platform_device *pdev)
2211
2289
2212
2290
altr_edac_a10_device_add (edac , child );
2213
2291
2214
- else if (of_device_is_compatible (child , "altr,sdram-edac-a10" ))
2292
+ else if ((of_device_is_compatible (child , "altr,sdram-edac-a10" )) ||
2293
+ (of_device_is_compatible (child , "altr,sdram-edac-s10" )))
2215
2294
of_platform_populate (pdev -> dev .of_node ,
2216
2295
altr_sdram_ctrl_of_match ,
2217
2296
NULL , & pdev -> dev );
@@ -2222,6 +2301,7 @@ static int altr_edac_a10_probe(struct platform_device *pdev)
2222
2301
2223
2302
static const struct of_device_id altr_edac_a10_of_match [] = {
2224
2303
{ .compatible = "altr,socfpga-a10-ecc-manager" },
2304
+ { .compatible = "altr,socfpga-s10-ecc-manager" },
2225
2305
{},
2226
2306
};
2227
2307
MODULE_DEVICE_TABLE (of , altr_edac_a10_of_match );
@@ -2235,171 +2315,6 @@ static struct platform_driver altr_edac_a10_driver = {
2235
2315
};
2236
2316
module_platform_driver (altr_edac_a10_driver );
2237
2317
2238
- /************** Stratix 10 EDAC Device Controller Functions> ************/
2239
-
2240
- #define to_s10edac (p , m ) container_of(p, struct altr_stratix10_edac, m)
2241
-
2242
- /*
2243
- * The double bit error is handled through SError which is fatal. This is
2244
- * called as a panic notifier to printout ECC error info as part of the panic.
2245
- */
2246
- static int s10_edac_dberr_handler (struct notifier_block * this ,
2247
- unsigned long event , void * ptr )
2248
- {
2249
- struct altr_stratix10_edac * edac = to_s10edac (this , panic_notifier );
2250
- int err_addr , dberror ;
2251
-
2252
- s10_protected_reg_read (edac , S10_SYSMGR_ECC_INTSTAT_DERR_OFST ,
2253
- & dberror );
2254
- /* Remember the UE Errors for a reboot */
2255
- s10_protected_reg_write (edac , S10_SYSMGR_UE_VAL_OFST , dberror );
2256
- if (dberror & S10_DDR0_IRQ_MASK ) {
2257
- s10_protected_reg_read (edac , S10_DERRADDR_OFST , & err_addr );
2258
- /* Remember the UE Error address */
2259
- s10_protected_reg_write (edac , S10_SYSMGR_UE_ADDR_OFST ,
2260
- err_addr );
2261
- edac_printk (KERN_ERR , EDAC_MC ,
2262
- "EDAC: [Uncorrectable errors @ 0x%08X]\n\n" ,
2263
- err_addr );
2264
- }
2265
-
2266
- return NOTIFY_DONE ;
2267
- }
2268
-
2269
- static void altr_edac_s10_irq_handler (struct irq_desc * desc )
2270
- {
2271
- struct altr_stratix10_edac * edac = irq_desc_get_handler_data (desc );
2272
- struct irq_chip * chip = irq_desc_get_chip (desc );
2273
- int irq = irq_desc_get_irq (desc );
2274
- int bit , sm_offset , irq_status ;
2275
-
2276
- sm_offset = S10_SYSMGR_ECC_INTSTAT_SERR_OFST ;
2277
-
2278
- chained_irq_enter (chip , desc );
2279
-
2280
- s10_protected_reg_read (NULL , sm_offset , & irq_status );
2281
-
2282
- for_each_set_bit (bit , (unsigned long * )& irq_status , 32 ) {
2283
- irq = irq_linear_revmap (edac -> domain , bit );
2284
- if (irq )
2285
- generic_handle_irq (irq );
2286
- }
2287
-
2288
- chained_irq_exit (chip , desc );
2289
- }
2290
-
2291
- static void s10_eccmgr_irq_mask (struct irq_data * d )
2292
- {
2293
- struct altr_stratix10_edac * edac = irq_data_get_irq_chip_data (d );
2294
-
2295
- s10_protected_reg_write (edac , S10_SYSMGR_ECC_INTMASK_SET_OFST ,
2296
- BIT (d -> hwirq ));
2297
- }
2298
-
2299
- static void s10_eccmgr_irq_unmask (struct irq_data * d )
2300
- {
2301
- struct altr_stratix10_edac * edac = irq_data_get_irq_chip_data (d );
2302
-
2303
- s10_protected_reg_write (edac , S10_SYSMGR_ECC_INTMASK_CLR_OFST ,
2304
- BIT (d -> hwirq ));
2305
- }
2306
-
2307
- static int s10_eccmgr_irqdomain_map (struct irq_domain * d , unsigned int irq ,
2308
- irq_hw_number_t hwirq )
2309
- {
2310
- struct altr_stratix10_edac * edac = d -> host_data ;
2311
-
2312
- irq_set_chip_and_handler (irq , & edac -> irq_chip , handle_simple_irq );
2313
- irq_set_chip_data (irq , edac );
2314
- irq_set_noprobe (irq );
2315
-
2316
- return 0 ;
2317
- }
2318
-
2319
- static const struct irq_domain_ops s10_eccmgr_ic_ops = {
2320
- .map = s10_eccmgr_irqdomain_map ,
2321
- .xlate = irq_domain_xlate_twocell ,
2322
- };
2323
-
2324
- static int altr_edac_s10_probe (struct platform_device * pdev )
2325
- {
2326
- struct altr_stratix10_edac * edac ;
2327
- struct device_node * child ;
2328
- int dberror , err_addr ;
2329
-
2330
- edac = devm_kzalloc (& pdev -> dev , sizeof (* edac ), GFP_KERNEL );
2331
- if (!edac )
2332
- return - ENOMEM ;
2333
-
2334
- edac -> dev = & pdev -> dev ;
2335
- platform_set_drvdata (pdev , edac );
2336
- INIT_LIST_HEAD (& edac -> s10_ecc_devices );
2337
-
2338
- edac -> irq_chip .name = pdev -> dev .of_node -> name ;
2339
- edac -> irq_chip .irq_mask = s10_eccmgr_irq_mask ;
2340
- edac -> irq_chip .irq_unmask = s10_eccmgr_irq_unmask ;
2341
- edac -> domain = irq_domain_add_linear (pdev -> dev .of_node , 64 ,
2342
- & s10_eccmgr_ic_ops , edac );
2343
- if (!edac -> domain ) {
2344
- dev_err (& pdev -> dev , "Error adding IRQ domain\n" );
2345
- return - ENOMEM ;
2346
- }
2347
-
2348
- edac -> sb_irq = platform_get_irq (pdev , 0 );
2349
- if (edac -> sb_irq < 0 ) {
2350
- dev_err (& pdev -> dev , "No SBERR IRQ resource\n" );
2351
- return edac -> sb_irq ;
2352
- }
2353
-
2354
- irq_set_chained_handler_and_data (edac -> sb_irq ,
2355
- altr_edac_s10_irq_handler ,
2356
- edac );
2357
-
2358
- edac -> panic_notifier .notifier_call = s10_edac_dberr_handler ;
2359
- atomic_notifier_chain_register (& panic_notifier_list ,
2360
- & edac -> panic_notifier );
2361
-
2362
- /* Printout a message if uncorrectable error previously. */
2363
- s10_protected_reg_read (edac , S10_SYSMGR_UE_VAL_OFST , & dberror );
2364
- if (dberror ) {
2365
- s10_protected_reg_read (edac , S10_SYSMGR_UE_ADDR_OFST ,
2366
- & err_addr );
2367
- edac_printk (KERN_ERR , EDAC_DEVICE ,
2368
- "Previous Boot UE detected[0x%X] @ 0x%X\n" ,
2369
- dberror , err_addr );
2370
- /* Reset the sticky registers */
2371
- s10_protected_reg_write (edac , S10_SYSMGR_UE_VAL_OFST , 0 );
2372
- s10_protected_reg_write (edac , S10_SYSMGR_UE_ADDR_OFST , 0 );
2373
- }
2374
-
2375
- for_each_child_of_node (pdev -> dev .of_node , child ) {
2376
- if (!of_device_is_available (child ))
2377
- continue ;
2378
-
2379
- if (of_device_is_compatible (child , "altr,sdram-edac-s10" ))
2380
- of_platform_populate (pdev -> dev .of_node ,
2381
- altr_sdram_ctrl_of_match ,
2382
- NULL , & pdev -> dev );
2383
- }
2384
-
2385
- return 0 ;
2386
- }
2387
-
2388
- static const struct of_device_id altr_edac_s10_of_match [] = {
2389
- { .compatible = "altr,socfpga-s10-ecc-manager" },
2390
- {},
2391
- };
2392
- MODULE_DEVICE_TABLE (of , altr_edac_s10_of_match );
2393
-
2394
- static struct platform_driver altr_edac_s10_driver = {
2395
- .probe = altr_edac_s10_probe ,
2396
- .driver = {
2397
- .name = "socfpga_s10_ecc_manager" ,
2398
- .of_match_table = altr_edac_s10_of_match ,
2399
- },
2400
- };
2401
- module_platform_driver (altr_edac_s10_driver );
2402
-
2403
2318
MODULE_LICENSE ("GPL v2" );
2404
2319
MODULE_AUTHOR ("Thor Thayer" );
2405
2320
MODULE_DESCRIPTION ("EDAC Driver for Altera Memories" );
0 commit comments