Skip to content

Commit d5fc912

Browse files
tthayer-intelsuryasaimadhu
authored andcommitted
EDAC, altera: Combine Stratix10 and Arria10 probe functions
On Stratix10, the ECC offsets are similar to the existing Arria10 functions and this can be leveraged to simplify the EDAC driver as follows: 1. Fold Stratix10 specifics into Arria10 structures and functions. 2. Implement the Stratix10 System Manager register accesses using a custom regmap to allow use with the Arria10 System Manager regmaps. 3. Stratix10 double bit errors are implemented as SError instead of interrupts so use a panic notifier. Signed-off-by: Thor Thayer <thor.thayer@linux.intel.com> Signed-off-by: Borislav Petkov <bp@suse.de> Cc: dinguyen@kernel.org Cc: robh+dt@kernel.org Cc: mark.rutland@arm.com Cc: mchehab@kernel.org Cc: devicetree@vger.kernel.org Cc: linux-edac@vger.kernel.org Link: https://lkml.kernel.org/r/1537883342-30180-3-git-send-email-thor.thayer@linux.intel.com
1 parent 3ce078f commit d5fc912

File tree

2 files changed

+90
-183
lines changed

2 files changed

+90
-183
lines changed

drivers/edac/altera_edac.c

Lines changed: 89 additions & 174 deletions
Original file line numberDiff line numberDiff line change
@@ -2146,6 +2146,35 @@ static const struct irq_domain_ops a10_eccmgr_ic_ops = {
21462146
.xlate = irq_domain_xlate_twocell,
21472147
};
21482148

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 *********************/
21492178
static int altr_edac_a10_probe(struct platform_device *pdev)
21502179
{
21512180
struct altr_arria10_edac *edac;
@@ -2159,8 +2188,33 @@ static int altr_edac_a10_probe(struct platform_device *pdev)
21592188
platform_set_drvdata(pdev, edac);
21602189
INIT_LIST_HEAD(&edac->a10_ecc_devices);
21612190

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,
21632194
"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+
21642218
if (IS_ERR(edac->ecc_mgr_map)) {
21652219
edac_printk(KERN_ERR, EDAC_DEVICE,
21662220
"Unable to get syscon altr,sysmgr-syscon\n");
@@ -2187,14 +2241,38 @@ static int altr_edac_a10_probe(struct platform_device *pdev)
21872241
altr_edac_a10_irq_handler,
21882242
edac);
21892243

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+
}
21942275
}
2195-
irq_set_chained_handler_and_data(edac->db_irq,
2196-
altr_edac_a10_irq_handler,
2197-
edac);
21982276

21992277
for_each_child_of_node(pdev->dev.of_node, child) {
22002278
if (!of_device_is_available(child))
@@ -2211,7 +2289,8 @@ static int altr_edac_a10_probe(struct platform_device *pdev)
22112289

22122290
altr_edac_a10_device_add(edac, child);
22132291

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")))
22152294
of_platform_populate(pdev->dev.of_node,
22162295
altr_sdram_ctrl_of_match,
22172296
NULL, &pdev->dev);
@@ -2222,6 +2301,7 @@ static int altr_edac_a10_probe(struct platform_device *pdev)
22222301

22232302
static const struct of_device_id altr_edac_a10_of_match[] = {
22242303
{ .compatible = "altr,socfpga-a10-ecc-manager" },
2304+
{ .compatible = "altr,socfpga-s10-ecc-manager" },
22252305
{},
22262306
};
22272307
MODULE_DEVICE_TABLE(of, altr_edac_a10_of_match);
@@ -2235,171 +2315,6 @@ static struct platform_driver altr_edac_a10_driver = {
22352315
};
22362316
module_platform_driver(altr_edac_a10_driver);
22372317

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-
24032318
MODULE_LICENSE("GPL v2");
24042319
MODULE_AUTHOR("Thor Thayer");
24052320
MODULE_DESCRIPTION("EDAC Driver for Altera Memories");

drivers/edac/altera_edac.h

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ struct altr_arria10_edac {
370370
struct irq_domain *domain;
371371
struct irq_chip irq_chip;
372372
struct list_head a10_ecc_devices;
373+
struct notifier_block panic_notifier;
373374
};
374375

375376
/*
@@ -437,13 +438,4 @@ struct altr_arria10_edac {
437438
#define INTEL_SIP_SMC_REG_WRITE \
438439
INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_REG_WRITE)
439440

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-
449441
#endif /* #ifndef _ALTERA_EDAC_H */

0 commit comments

Comments
 (0)