blob: dcedc4a8cd12c2b19f9455541e90877ee3abfefd [file] [log] [blame]
Thor Thayer71bcada2014-09-03 10:27:54 -05001/*
Thor Thayerc3eea192016-02-10 13:26:21 -06002 * Copyright Altera Corporation (C) 2014-2016. All rights reserved.
Thor Thayer71bcada2014-09-03 10:27:54 -05003 * 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 */
19
Thor Thayerc3eea192016-02-10 13:26:21 -060020#include <asm/cacheflush.h>
Thor Thayer71bcada2014-09-03 10:27:54 -050021#include <linux/ctype.h>
22#include <linux/edac.h>
Thor Thayerc3eea192016-02-10 13:26:21 -060023#include <linux/genalloc.h>
Thor Thayer71bcada2014-09-03 10:27:54 -050024#include <linux/interrupt.h>
Thor Thayer13ab8442016-06-07 15:35:57 -050025#include <linux/irqchip/chained_irq.h>
Thor Thayer71bcada2014-09-03 10:27:54 -050026#include <linux/kernel.h>
27#include <linux/mfd/syscon.h>
Thor Thayer588cb032016-03-21 11:01:44 -050028#include <linux/of_address.h>
Thor Thayer13ab8442016-06-07 15:35:57 -050029#include <linux/of_irq.h>
Thor Thayer71bcada2014-09-03 10:27:54 -050030#include <linux/of_platform.h>
31#include <linux/platform_device.h>
32#include <linux/regmap.h>
33#include <linux/types.h>
34#include <linux/uaccess.h>
35
Thor Thayer143f4a52015-06-04 09:28:46 -050036#include "altera_edac.h"
Thor Thayer71bcada2014-09-03 10:27:54 -050037#include "edac_core.h"
38#include "edac_module.h"
39
40#define EDAC_MOD_STR "altera_edac"
41#define EDAC_VERSION "1"
Thor Thayerc3eea192016-02-10 13:26:21 -060042#define EDAC_DEVICE "Altera"
Thor Thayer71bcada2014-09-03 10:27:54 -050043
Thor Thayer143f4a52015-06-04 09:28:46 -050044static const struct altr_sdram_prv_data c5_data = {
45 .ecc_ctrl_offset = CV_CTLCFG_OFST,
46 .ecc_ctl_en_mask = CV_CTLCFG_ECC_AUTO_EN,
47 .ecc_stat_offset = CV_DRAMSTS_OFST,
48 .ecc_stat_ce_mask = CV_DRAMSTS_SBEERR,
49 .ecc_stat_ue_mask = CV_DRAMSTS_DBEERR,
50 .ecc_saddr_offset = CV_ERRADDR_OFST,
Thor Thayer73bcc942015-06-04 09:28:47 -050051 .ecc_daddr_offset = CV_ERRADDR_OFST,
Thor Thayer143f4a52015-06-04 09:28:46 -050052 .ecc_cecnt_offset = CV_SBECOUNT_OFST,
53 .ecc_uecnt_offset = CV_DBECOUNT_OFST,
54 .ecc_irq_en_offset = CV_DRAMINTR_OFST,
55 .ecc_irq_en_mask = CV_DRAMINTR_INTREN,
56 .ecc_irq_clr_offset = CV_DRAMINTR_OFST,
57 .ecc_irq_clr_mask = (CV_DRAMINTR_INTRCLR | CV_DRAMINTR_INTREN),
58 .ecc_cnt_rst_offset = CV_DRAMINTR_OFST,
59 .ecc_cnt_rst_mask = CV_DRAMINTR_INTRCLR,
Thor Thayer143f4a52015-06-04 09:28:46 -050060 .ce_ue_trgr_offset = CV_CTLCFG_OFST,
61 .ce_set_mask = CV_CTLCFG_GEN_SB_ERR,
62 .ue_set_mask = CV_CTLCFG_GEN_DB_ERR,
Thor Thayer71bcada2014-09-03 10:27:54 -050063};
64
Thor Thayer73bcc942015-06-04 09:28:47 -050065static const struct altr_sdram_prv_data a10_data = {
66 .ecc_ctrl_offset = A10_ECCCTRL1_OFST,
67 .ecc_ctl_en_mask = A10_ECCCTRL1_ECC_EN,
68 .ecc_stat_offset = A10_INTSTAT_OFST,
69 .ecc_stat_ce_mask = A10_INTSTAT_SBEERR,
70 .ecc_stat_ue_mask = A10_INTSTAT_DBEERR,
71 .ecc_saddr_offset = A10_SERRADDR_OFST,
72 .ecc_daddr_offset = A10_DERRADDR_OFST,
73 .ecc_irq_en_offset = A10_ERRINTEN_OFST,
74 .ecc_irq_en_mask = A10_ECC_IRQ_EN_MASK,
75 .ecc_irq_clr_offset = A10_INTSTAT_OFST,
76 .ecc_irq_clr_mask = (A10_INTSTAT_SBEERR | A10_INTSTAT_DBEERR),
77 .ecc_cnt_rst_offset = A10_ECCCTRL1_OFST,
78 .ecc_cnt_rst_mask = A10_ECC_CNT_RESET_MASK,
Thor Thayer73bcc942015-06-04 09:28:47 -050079 .ce_ue_trgr_offset = A10_DIAGINTTEST_OFST,
80 .ce_set_mask = A10_DIAGINT_TSERRA_MASK,
81 .ue_set_mask = A10_DIAGINT_TDERRA_MASK,
Thor Thayer73bcc942015-06-04 09:28:47 -050082};
83
Thor Thayerc3eea192016-02-10 13:26:21 -060084/*********************** EDAC Memory Controller Functions ****************/
85
86/* The SDRAM controller uses the EDAC Memory Controller framework. */
87
Thor Thayer71bcada2014-09-03 10:27:54 -050088static irqreturn_t altr_sdram_mc_err_handler(int irq, void *dev_id)
89{
90 struct mem_ctl_info *mci = dev_id;
91 struct altr_sdram_mc_data *drvdata = mci->pvt_info;
Thor Thayer143f4a52015-06-04 09:28:46 -050092 const struct altr_sdram_prv_data *priv = drvdata->data;
Thor Thayer73bcc942015-06-04 09:28:47 -050093 u32 status, err_count = 1, err_addr;
Thor Thayer71bcada2014-09-03 10:27:54 -050094
Thor Thayer143f4a52015-06-04 09:28:46 -050095 regmap_read(drvdata->mc_vbase, priv->ecc_stat_offset, &status);
Thor Thayer71bcada2014-09-03 10:27:54 -050096
Thor Thayer143f4a52015-06-04 09:28:46 -050097 if (status & priv->ecc_stat_ue_mask) {
Thor Thayer73bcc942015-06-04 09:28:47 -050098 regmap_read(drvdata->mc_vbase, priv->ecc_daddr_offset,
99 &err_addr);
100 if (priv->ecc_uecnt_offset)
101 regmap_read(drvdata->mc_vbase, priv->ecc_uecnt_offset,
102 &err_count);
Thor Thayer71bcada2014-09-03 10:27:54 -0500103 panic("\nEDAC: [%d Uncorrectable errors @ 0x%08X]\n",
104 err_count, err_addr);
105 }
Thor Thayer143f4a52015-06-04 09:28:46 -0500106 if (status & priv->ecc_stat_ce_mask) {
Thor Thayer73bcc942015-06-04 09:28:47 -0500107 regmap_read(drvdata->mc_vbase, priv->ecc_saddr_offset,
108 &err_addr);
109 if (priv->ecc_uecnt_offset)
110 regmap_read(drvdata->mc_vbase, priv->ecc_cecnt_offset,
111 &err_count);
Thor Thayer71bcada2014-09-03 10:27:54 -0500112 edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, err_count,
113 err_addr >> PAGE_SHIFT,
114 err_addr & ~PAGE_MASK, 0,
115 0, 0, -1, mci->ctl_name, "");
Thor Thayer73bcc942015-06-04 09:28:47 -0500116 /* Clear IRQ to resume */
117 regmap_write(drvdata->mc_vbase, priv->ecc_irq_clr_offset,
118 priv->ecc_irq_clr_mask);
119
120 return IRQ_HANDLED;
Thor Thayer71bcada2014-09-03 10:27:54 -0500121 }
Thor Thayer73bcc942015-06-04 09:28:47 -0500122 return IRQ_NONE;
Thor Thayer71bcada2014-09-03 10:27:54 -0500123}
124
Thor Thayer71bcada2014-09-03 10:27:54 -0500125static ssize_t altr_sdr_mc_err_inject_write(struct file *file,
126 const char __user *data,
127 size_t count, loff_t *ppos)
128{
129 struct mem_ctl_info *mci = file->private_data;
130 struct altr_sdram_mc_data *drvdata = mci->pvt_info;
Thor Thayer143f4a52015-06-04 09:28:46 -0500131 const struct altr_sdram_prv_data *priv = drvdata->data;
Thor Thayer71bcada2014-09-03 10:27:54 -0500132 u32 *ptemp;
133 dma_addr_t dma_handle;
134 u32 reg, read_reg;
135
136 ptemp = dma_alloc_coherent(mci->pdev, 16, &dma_handle, GFP_KERNEL);
137 if (!ptemp) {
138 dma_free_coherent(mci->pdev, 16, ptemp, dma_handle);
139 edac_printk(KERN_ERR, EDAC_MC,
140 "Inject: Buffer Allocation error\n");
141 return -ENOMEM;
142 }
143
Thor Thayer143f4a52015-06-04 09:28:46 -0500144 regmap_read(drvdata->mc_vbase, priv->ce_ue_trgr_offset,
145 &read_reg);
146 read_reg &= ~(priv->ce_set_mask | priv->ue_set_mask);
Thor Thayer71bcada2014-09-03 10:27:54 -0500147
148 /* Error are injected by writing a word while the SBE or DBE
149 * bit in the CTLCFG register is set. Reading the word will
150 * trigger the SBE or DBE error and the corresponding IRQ.
151 */
152 if (count == 3) {
153 edac_printk(KERN_ALERT, EDAC_MC,
154 "Inject Double bit error\n");
Thor Thayer143f4a52015-06-04 09:28:46 -0500155 regmap_write(drvdata->mc_vbase, priv->ce_ue_trgr_offset,
156 (read_reg | priv->ue_set_mask));
Thor Thayer71bcada2014-09-03 10:27:54 -0500157 } else {
158 edac_printk(KERN_ALERT, EDAC_MC,
159 "Inject Single bit error\n");
Thor Thayer143f4a52015-06-04 09:28:46 -0500160 regmap_write(drvdata->mc_vbase, priv->ce_ue_trgr_offset,
161 (read_reg | priv->ce_set_mask));
Thor Thayer71bcada2014-09-03 10:27:54 -0500162 }
163
164 ptemp[0] = 0x5A5A5A5A;
165 ptemp[1] = 0xA5A5A5A5;
166
167 /* Clear the error injection bits */
Thor Thayer143f4a52015-06-04 09:28:46 -0500168 regmap_write(drvdata->mc_vbase, priv->ce_ue_trgr_offset, read_reg);
Thor Thayer71bcada2014-09-03 10:27:54 -0500169 /* Ensure it has been written out */
170 wmb();
171
172 /*
173 * To trigger the error, we need to read the data back
174 * (the data was written with errors above).
175 * The ACCESS_ONCE macros and printk are used to prevent the
176 * the compiler optimizing these reads out.
177 */
178 reg = ACCESS_ONCE(ptemp[0]);
179 read_reg = ACCESS_ONCE(ptemp[1]);
180 /* Force Read */
181 rmb();
182
183 edac_printk(KERN_ALERT, EDAC_MC, "Read Data [0x%X, 0x%X]\n",
184 reg, read_reg);
185
186 dma_free_coherent(mci->pdev, 16, ptemp, dma_handle);
187
188 return count;
189}
190
191static const struct file_operations altr_sdr_mc_debug_inject_fops = {
192 .open = simple_open,
193 .write = altr_sdr_mc_err_inject_write,
194 .llseek = generic_file_llseek,
195};
196
197static void altr_sdr_mc_create_debugfs_nodes(struct mem_ctl_info *mci)
198{
Borislav Petkovbba3b312015-09-22 12:27:29 +0200199 if (!IS_ENABLED(CONFIG_EDAC_DEBUG))
200 return;
201
202 if (!mci->debugfs)
203 return;
204
205 edac_debugfs_create_file("inject_ctrl", S_IWUSR, mci->debugfs, mci,
206 &altr_sdr_mc_debug_inject_fops);
Thor Thayer71bcada2014-09-03 10:27:54 -0500207}
Thor Thayer71bcada2014-09-03 10:27:54 -0500208
Thor Thayerf9ae4872015-06-04 09:28:45 -0500209/* Get total memory size from Open Firmware DTB */
210static unsigned long get_total_mem(void)
Thor Thayer71bcada2014-09-03 10:27:54 -0500211{
Thor Thayerf9ae4872015-06-04 09:28:45 -0500212 struct device_node *np = NULL;
213 const unsigned int *reg, *reg_end;
214 int len, sw, aw;
215 unsigned long start, size, total_mem = 0;
Thor Thayer71bcada2014-09-03 10:27:54 -0500216
Thor Thayerf9ae4872015-06-04 09:28:45 -0500217 for_each_node_by_type(np, "memory") {
218 aw = of_n_addr_cells(np);
219 sw = of_n_size_cells(np);
220 reg = (const unsigned int *)of_get_property(np, "reg", &len);
221 reg_end = reg + (len / sizeof(u32));
Thor Thayer71bcada2014-09-03 10:27:54 -0500222
Thor Thayerf9ae4872015-06-04 09:28:45 -0500223 total_mem = 0;
224 do {
225 start = of_read_number(reg, aw);
226 reg += aw;
227 size = of_read_number(reg, sw);
228 reg += sw;
229 total_mem += size;
230 } while (reg < reg_end);
231 }
232 edac_dbg(0, "total_mem 0x%lx\n", total_mem);
233 return total_mem;
Thor Thayer71bcada2014-09-03 10:27:54 -0500234}
235
Thor Thayer143f4a52015-06-04 09:28:46 -0500236static const struct of_device_id altr_sdram_ctrl_of_match[] = {
Arnd Bergmann2c911f62016-04-16 22:13:55 +0200237 { .compatible = "altr,sdram-edac", .data = &c5_data},
238 { .compatible = "altr,sdram-edac-a10", .data = &a10_data},
Thor Thayer143f4a52015-06-04 09:28:46 -0500239 {},
240};
241MODULE_DEVICE_TABLE(of, altr_sdram_ctrl_of_match);
242
Thor Thayer73bcc942015-06-04 09:28:47 -0500243static int a10_init(struct regmap *mc_vbase)
244{
245 if (regmap_update_bits(mc_vbase, A10_INTMODE_OFST,
246 A10_INTMODE_SB_INT, A10_INTMODE_SB_INT)) {
247 edac_printk(KERN_ERR, EDAC_MC,
248 "Error setting SB IRQ mode\n");
249 return -ENODEV;
250 }
251
252 if (regmap_write(mc_vbase, A10_SERRCNTREG_OFST, 1)) {
253 edac_printk(KERN_ERR, EDAC_MC,
254 "Error setting trigger count\n");
255 return -ENODEV;
256 }
257
258 return 0;
259}
260
261static int a10_unmask_irq(struct platform_device *pdev, u32 mask)
262{
263 void __iomem *sm_base;
264 int ret = 0;
265
266 if (!request_mem_region(A10_SYMAN_INTMASK_CLR, sizeof(u32),
267 dev_name(&pdev->dev))) {
268 edac_printk(KERN_ERR, EDAC_MC,
269 "Unable to request mem region\n");
270 return -EBUSY;
271 }
272
273 sm_base = ioremap(A10_SYMAN_INTMASK_CLR, sizeof(u32));
274 if (!sm_base) {
275 edac_printk(KERN_ERR, EDAC_MC,
276 "Unable to ioremap device\n");
277
278 ret = -ENOMEM;
279 goto release;
280 }
281
282 iowrite32(mask, sm_base);
283
284 iounmap(sm_base);
285
286release:
287 release_mem_region(A10_SYMAN_INTMASK_CLR, sizeof(u32));
288
289 return ret;
290}
291
Thor Thayer71bcada2014-09-03 10:27:54 -0500292static int altr_sdram_probe(struct platform_device *pdev)
293{
Thor Thayer143f4a52015-06-04 09:28:46 -0500294 const struct of_device_id *id;
Thor Thayer71bcada2014-09-03 10:27:54 -0500295 struct edac_mc_layer layers[2];
296 struct mem_ctl_info *mci;
297 struct altr_sdram_mc_data *drvdata;
Thor Thayer143f4a52015-06-04 09:28:46 -0500298 const struct altr_sdram_prv_data *priv;
Thor Thayer71bcada2014-09-03 10:27:54 -0500299 struct regmap *mc_vbase;
300 struct dimm_info *dimm;
Thor Thayer143f4a52015-06-04 09:28:46 -0500301 u32 read_reg;
Thor Thayer73bcc942015-06-04 09:28:47 -0500302 int irq, irq2, res = 0;
303 unsigned long mem_size, irqflags = 0;
Thor Thayer71bcada2014-09-03 10:27:54 -0500304
Thor Thayer143f4a52015-06-04 09:28:46 -0500305 id = of_match_device(altr_sdram_ctrl_of_match, &pdev->dev);
306 if (!id)
307 return -ENODEV;
308
Thor Thayer71bcada2014-09-03 10:27:54 -0500309 /* Grab the register range from the sdr controller in device tree */
310 mc_vbase = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
311 "altr,sdr-syscon");
312 if (IS_ERR(mc_vbase)) {
313 edac_printk(KERN_ERR, EDAC_MC,
314 "regmap for altr,sdr-syscon lookup failed.\n");
315 return -ENODEV;
316 }
317
Thor Thayer143f4a52015-06-04 09:28:46 -0500318 /* Check specific dependencies for the module */
319 priv = of_match_node(altr_sdram_ctrl_of_match,
320 pdev->dev.of_node)->data;
321
322 /* Validate the SDRAM controller has ECC enabled */
323 if (regmap_read(mc_vbase, priv->ecc_ctrl_offset, &read_reg) ||
324 ((read_reg & priv->ecc_ctl_en_mask) != priv->ecc_ctl_en_mask)) {
Thor Thayer71bcada2014-09-03 10:27:54 -0500325 edac_printk(KERN_ERR, EDAC_MC,
326 "No ECC/ECC disabled [0x%08X]\n", read_reg);
327 return -ENODEV;
328 }
329
330 /* Grab memory size from device tree. */
Thor Thayerf9ae4872015-06-04 09:28:45 -0500331 mem_size = get_total_mem();
Thor Thayer71bcada2014-09-03 10:27:54 -0500332 if (!mem_size) {
Thor Thayerf9ae4872015-06-04 09:28:45 -0500333 edac_printk(KERN_ERR, EDAC_MC, "Unable to calculate memory size\n");
Thor Thayer71bcada2014-09-03 10:27:54 -0500334 return -ENODEV;
335 }
336
Thor Thayer143f4a52015-06-04 09:28:46 -0500337 /* Ensure the SDRAM Interrupt is disabled */
338 if (regmap_update_bits(mc_vbase, priv->ecc_irq_en_offset,
339 priv->ecc_irq_en_mask, 0)) {
Thor Thayer71bcada2014-09-03 10:27:54 -0500340 edac_printk(KERN_ERR, EDAC_MC,
Thor Thayer143f4a52015-06-04 09:28:46 -0500341 "Error disabling SDRAM ECC IRQ\n");
342 return -ENODEV;
343 }
344
345 /* Toggle to clear the SDRAM Error count */
346 if (regmap_update_bits(mc_vbase, priv->ecc_cnt_rst_offset,
347 priv->ecc_cnt_rst_mask,
348 priv->ecc_cnt_rst_mask)) {
349 edac_printk(KERN_ERR, EDAC_MC,
350 "Error clearing SDRAM ECC count\n");
351 return -ENODEV;
352 }
353
354 if (regmap_update_bits(mc_vbase, priv->ecc_cnt_rst_offset,
355 priv->ecc_cnt_rst_mask, 0)) {
356 edac_printk(KERN_ERR, EDAC_MC,
357 "Error clearing SDRAM ECC count\n");
Thor Thayer71bcada2014-09-03 10:27:54 -0500358 return -ENODEV;
359 }
360
361 irq = platform_get_irq(pdev, 0);
362 if (irq < 0) {
363 edac_printk(KERN_ERR, EDAC_MC,
364 "No irq %d in DT\n", irq);
365 return -ENODEV;
366 }
367
Thor Thayer73bcc942015-06-04 09:28:47 -0500368 /* Arria10 has a 2nd IRQ */
369 irq2 = platform_get_irq(pdev, 1);
370
Thor Thayer71bcada2014-09-03 10:27:54 -0500371 layers[0].type = EDAC_MC_LAYER_CHIP_SELECT;
372 layers[0].size = 1;
373 layers[0].is_virt_csrow = true;
374 layers[1].type = EDAC_MC_LAYER_CHANNEL;
375 layers[1].size = 1;
376 layers[1].is_virt_csrow = false;
377 mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers,
378 sizeof(struct altr_sdram_mc_data));
379 if (!mci)
380 return -ENOMEM;
381
382 mci->pdev = &pdev->dev;
383 drvdata = mci->pvt_info;
384 drvdata->mc_vbase = mc_vbase;
Thor Thayer143f4a52015-06-04 09:28:46 -0500385 drvdata->data = priv;
Thor Thayer71bcada2014-09-03 10:27:54 -0500386 platform_set_drvdata(pdev, mci);
387
388 if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL)) {
Thor Thayer143f4a52015-06-04 09:28:46 -0500389 edac_printk(KERN_ERR, EDAC_MC,
390 "Unable to get managed device resource\n");
Thor Thayer71bcada2014-09-03 10:27:54 -0500391 res = -ENOMEM;
392 goto free;
393 }
394
395 mci->mtype_cap = MEM_FLAG_DDR3;
396 mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
397 mci->edac_cap = EDAC_FLAG_SECDED;
398 mci->mod_name = EDAC_MOD_STR;
399 mci->mod_ver = EDAC_VERSION;
400 mci->ctl_name = dev_name(&pdev->dev);
401 mci->scrub_mode = SCRUB_SW_SRC;
402 mci->dev_name = dev_name(&pdev->dev);
403
404 dimm = *mci->dimms;
405 dimm->nr_pages = ((mem_size - 1) >> PAGE_SHIFT) + 1;
406 dimm->grain = 8;
407 dimm->dtype = DEV_X8;
408 dimm->mtype = MEM_DDR3;
409 dimm->edac_mode = EDAC_SECDED;
410
411 res = edac_mc_add_mc(mci);
412 if (res < 0)
413 goto err;
414
Thor Thayer73bcc942015-06-04 09:28:47 -0500415 /* Only the Arria10 has separate IRQs */
416 if (irq2 > 0) {
417 /* Arria10 specific initialization */
418 res = a10_init(mc_vbase);
419 if (res < 0)
420 goto err2;
421
422 res = devm_request_irq(&pdev->dev, irq2,
423 altr_sdram_mc_err_handler,
424 IRQF_SHARED, dev_name(&pdev->dev), mci);
425 if (res < 0) {
426 edac_mc_printk(mci, KERN_ERR,
427 "Unable to request irq %d\n", irq2);
428 res = -ENODEV;
429 goto err2;
430 }
431
432 res = a10_unmask_irq(pdev, A10_DDR0_IRQ_MASK);
433 if (res < 0)
434 goto err2;
435
436 irqflags = IRQF_SHARED;
437 }
438
Thor Thayer71bcada2014-09-03 10:27:54 -0500439 res = devm_request_irq(&pdev->dev, irq, altr_sdram_mc_err_handler,
Thor Thayer73bcc942015-06-04 09:28:47 -0500440 irqflags, dev_name(&pdev->dev), mci);
Thor Thayer71bcada2014-09-03 10:27:54 -0500441 if (res < 0) {
442 edac_mc_printk(mci, KERN_ERR,
443 "Unable to request irq %d\n", irq);
444 res = -ENODEV;
445 goto err2;
446 }
447
Thor Thayer143f4a52015-06-04 09:28:46 -0500448 /* Infrastructure ready - enable the IRQ */
449 if (regmap_update_bits(drvdata->mc_vbase, priv->ecc_irq_en_offset,
450 priv->ecc_irq_en_mask, priv->ecc_irq_en_mask)) {
Thor Thayer71bcada2014-09-03 10:27:54 -0500451 edac_mc_printk(mci, KERN_ERR,
452 "Error enabling SDRAM ECC IRQ\n");
453 res = -ENODEV;
454 goto err2;
455 }
456
457 altr_sdr_mc_create_debugfs_nodes(mci);
458
459 devres_close_group(&pdev->dev, NULL);
460
461 return 0;
462
463err2:
464 edac_mc_del_mc(&pdev->dev);
465err:
466 devres_release_group(&pdev->dev, NULL);
467free:
468 edac_mc_free(mci);
469 edac_printk(KERN_ERR, EDAC_MC,
470 "EDAC Probe Failed; Error %d\n", res);
471
472 return res;
473}
474
475static int altr_sdram_remove(struct platform_device *pdev)
476{
477 struct mem_ctl_info *mci = platform_get_drvdata(pdev);
478
479 edac_mc_del_mc(&pdev->dev);
480 edac_mc_free(mci);
481 platform_set_drvdata(pdev, NULL);
482
483 return 0;
484}
485
Alan Tull6f2b6422015-06-05 08:49:15 -0500486/*
487 * If you want to suspend, need to disable EDAC by removing it
488 * from the device tree or defconfig.
489 */
490#ifdef CONFIG_PM
491static int altr_sdram_prepare(struct device *dev)
492{
493 pr_err("Suspend not allowed when EDAC is enabled.\n");
494
495 return -EPERM;
496}
497
498static const struct dev_pm_ops altr_sdram_pm_ops = {
499 .prepare = altr_sdram_prepare,
500};
501#endif
502
Thor Thayer71bcada2014-09-03 10:27:54 -0500503static struct platform_driver altr_sdram_edac_driver = {
504 .probe = altr_sdram_probe,
505 .remove = altr_sdram_remove,
506 .driver = {
507 .name = "altr_sdram_edac",
Alan Tull6f2b6422015-06-05 08:49:15 -0500508#ifdef CONFIG_PM
509 .pm = &altr_sdram_pm_ops,
510#endif
Thor Thayer71bcada2014-09-03 10:27:54 -0500511 .of_match_table = altr_sdram_ctrl_of_match,
512 },
513};
514
515module_platform_driver(altr_sdram_edac_driver);
516
Thor Thayerc3eea192016-02-10 13:26:21 -0600517/************************* EDAC Parent Probe *************************/
518
519static const struct of_device_id altr_edac_device_of_match[];
520
521static const struct of_device_id altr_edac_of_match[] = {
522 { .compatible = "altr,socfpga-ecc-manager" },
523 {},
524};
525MODULE_DEVICE_TABLE(of, altr_edac_of_match);
526
527static int altr_edac_probe(struct platform_device *pdev)
528{
529 of_platform_populate(pdev->dev.of_node, altr_edac_device_of_match,
530 NULL, &pdev->dev);
531 return 0;
532}
533
534static struct platform_driver altr_edac_driver = {
535 .probe = altr_edac_probe,
536 .driver = {
537 .name = "socfpga_ecc_manager",
538 .of_match_table = altr_edac_of_match,
539 },
540};
541module_platform_driver(altr_edac_driver);
542
543/************************* EDAC Device Functions *************************/
544
545/*
546 * EDAC Device Functions (shared between various IPs).
547 * The discrete memories use the EDAC Device framework. The probe
548 * and error handling functions are very similar between memories
549 * so they are shared. The memory allocation and freeing for EDAC
550 * trigger testing are different for each memory.
551 */
552
Thor Thayer1cf70372016-06-22 08:58:54 -0500553static const struct edac_device_prv_data ocramecc_data;
554static const struct edac_device_prv_data l2ecc_data;
555static const struct edac_device_prv_data a10_ocramecc_data;
556static const struct edac_device_prv_data a10_l2ecc_data;
Thor Thayerc3eea192016-02-10 13:26:21 -0600557
Thor Thayerc3eea192016-02-10 13:26:21 -0600558static irqreturn_t altr_edac_device_handler(int irq, void *dev_id)
559{
560 irqreturn_t ret_value = IRQ_NONE;
561 struct edac_device_ctl_info *dci = dev_id;
562 struct altr_edac_device_dev *drvdata = dci->pvt_info;
563 const struct edac_device_prv_data *priv = drvdata->data;
564
565 if (irq == drvdata->sb_irq) {
566 if (priv->ce_clear_mask)
567 writel(priv->ce_clear_mask, drvdata->base);
568 edac_device_handle_ce(dci, 0, 0, drvdata->edac_dev_name);
569 ret_value = IRQ_HANDLED;
570 } else if (irq == drvdata->db_irq) {
571 if (priv->ue_clear_mask)
572 writel(priv->ue_clear_mask, drvdata->base);
573 edac_device_handle_ue(dci, 0, 0, drvdata->edac_dev_name);
574 panic("\nEDAC:ECC_DEVICE[Uncorrectable errors]\n");
575 ret_value = IRQ_HANDLED;
576 } else {
577 WARN_ON(1);
578 }
579
580 return ret_value;
581}
582
583static ssize_t altr_edac_device_trig(struct file *file,
584 const char __user *user_buf,
585 size_t count, loff_t *ppos)
586
587{
588 u32 *ptemp, i, error_mask;
589 int result = 0;
590 u8 trig_type;
591 unsigned long flags;
592 struct edac_device_ctl_info *edac_dci = file->private_data;
593 struct altr_edac_device_dev *drvdata = edac_dci->pvt_info;
594 const struct edac_device_prv_data *priv = drvdata->data;
595 void *generic_ptr = edac_dci->dev;
596
597 if (!user_buf || get_user(trig_type, user_buf))
598 return -EFAULT;
599
600 if (!priv->alloc_mem)
601 return -ENOMEM;
602
603 /*
604 * Note that generic_ptr is initialized to the device * but in
605 * some alloc_functions, this is overridden and returns data.
606 */
607 ptemp = priv->alloc_mem(priv->trig_alloc_sz, &generic_ptr);
608 if (!ptemp) {
609 edac_printk(KERN_ERR, EDAC_DEVICE,
610 "Inject: Buffer Allocation error\n");
611 return -ENOMEM;
612 }
613
614 if (trig_type == ALTR_UE_TRIGGER_CHAR)
615 error_mask = priv->ue_set_mask;
616 else
617 error_mask = priv->ce_set_mask;
618
619 edac_printk(KERN_ALERT, EDAC_DEVICE,
620 "Trigger Error Mask (0x%X)\n", error_mask);
621
622 local_irq_save(flags);
623 /* write ECC corrupted data out. */
624 for (i = 0; i < (priv->trig_alloc_sz / sizeof(*ptemp)); i++) {
625 /* Read data so we're in the correct state */
626 rmb();
627 if (ACCESS_ONCE(ptemp[i]))
628 result = -1;
629 /* Toggle Error bit (it is latched), leave ECC enabled */
Thor Thayer811fce42016-03-21 11:01:42 -0500630 writel(error_mask, (drvdata->base + priv->set_err_ofst));
631 writel(priv->ecc_enable_mask, (drvdata->base +
632 priv->set_err_ofst));
Thor Thayerc3eea192016-02-10 13:26:21 -0600633 ptemp[i] = i;
634 }
635 /* Ensure it has been written out */
636 wmb();
637 local_irq_restore(flags);
638
639 if (result)
640 edac_printk(KERN_ERR, EDAC_DEVICE, "Mem Not Cleared\n");
641
642 /* Read out written data. ECC error caused here */
643 for (i = 0; i < ALTR_TRIGGER_READ_WRD_CNT; i++)
644 if (ACCESS_ONCE(ptemp[i]) != i)
645 edac_printk(KERN_ERR, EDAC_DEVICE,
646 "Read doesn't match written data\n");
647
648 if (priv->free_mem)
649 priv->free_mem(ptemp, priv->trig_alloc_sz, generic_ptr);
650
651 return count;
652}
653
654static const struct file_operations altr_edac_device_inject_fops = {
655 .open = simple_open,
656 .write = altr_edac_device_trig,
657 .llseek = generic_file_llseek,
658};
659
Thor Thayerc7b4be82016-04-06 20:22:54 -0500660static ssize_t altr_edac_a10_device_trig(struct file *file,
661 const char __user *user_buf,
662 size_t count, loff_t *ppos);
663
664static const struct file_operations altr_edac_a10_device_inject_fops = {
665 .open = simple_open,
666 .write = altr_edac_a10_device_trig,
667 .llseek = generic_file_llseek,
668};
669
Thor Thayerc3eea192016-02-10 13:26:21 -0600670static void altr_create_edacdev_dbgfs(struct edac_device_ctl_info *edac_dci,
671 const struct edac_device_prv_data *priv)
672{
673 struct altr_edac_device_dev *drvdata = edac_dci->pvt_info;
674
675 if (!IS_ENABLED(CONFIG_EDAC_DEBUG))
676 return;
677
678 drvdata->debugfs_dir = edac_debugfs_create_dir(drvdata->edac_dev_name);
679 if (!drvdata->debugfs_dir)
680 return;
681
682 if (!edac_debugfs_create_file(priv->dbgfs_name, S_IWUSR,
683 drvdata->debugfs_dir, edac_dci,
Thor Thayere17ced22016-03-31 13:48:01 -0500684 priv->inject_fops))
Thor Thayerc3eea192016-02-10 13:26:21 -0600685 debugfs_remove_recursive(drvdata->debugfs_dir);
686}
687
688static const struct of_device_id altr_edac_device_of_match[] = {
689#ifdef CONFIG_EDAC_ALTERA_L2C
Arnd Bergmann2c911f62016-04-16 22:13:55 +0200690 { .compatible = "altr,socfpga-l2-ecc", .data = &l2ecc_data },
Thor Thayerc3eea192016-02-10 13:26:21 -0600691#endif
692#ifdef CONFIG_EDAC_ALTERA_OCRAM
Arnd Bergmann2c911f62016-04-16 22:13:55 +0200693 { .compatible = "altr,socfpga-ocram-ecc", .data = &ocramecc_data },
Thor Thayerc3eea192016-02-10 13:26:21 -0600694#endif
695 {},
696};
697MODULE_DEVICE_TABLE(of, altr_edac_device_of_match);
698
699/*
700 * altr_edac_device_probe()
701 * This is a generic EDAC device driver that will support
702 * various Altera memory devices such as the L2 cache ECC and
703 * OCRAM ECC as well as the memories for other peripherals.
704 * Module specific initialization is done by passing the
705 * function index in the device tree.
706 */
707static int altr_edac_device_probe(struct platform_device *pdev)
708{
709 struct edac_device_ctl_info *dci;
710 struct altr_edac_device_dev *drvdata;
711 struct resource *r;
712 int res = 0;
713 struct device_node *np = pdev->dev.of_node;
714 char *ecc_name = (char *)np->name;
715 static int dev_instance;
716
717 if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL)) {
718 edac_printk(KERN_ERR, EDAC_DEVICE,
719 "Unable to open devm\n");
720 return -ENOMEM;
721 }
722
723 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
724 if (!r) {
725 edac_printk(KERN_ERR, EDAC_DEVICE,
726 "Unable to get mem resource\n");
727 res = -ENODEV;
728 goto fail;
729 }
730
731 if (!devm_request_mem_region(&pdev->dev, r->start, resource_size(r),
732 dev_name(&pdev->dev))) {
733 edac_printk(KERN_ERR, EDAC_DEVICE,
734 "%s:Error requesting mem region\n", ecc_name);
735 res = -EBUSY;
736 goto fail;
737 }
738
739 dci = edac_device_alloc_ctl_info(sizeof(*drvdata), ecc_name,
740 1, ecc_name, 1, 0, NULL, 0,
741 dev_instance++);
742
743 if (!dci) {
744 edac_printk(KERN_ERR, EDAC_DEVICE,
745 "%s: Unable to allocate EDAC device\n", ecc_name);
746 res = -ENOMEM;
747 goto fail;
748 }
749
750 drvdata = dci->pvt_info;
751 dci->dev = &pdev->dev;
752 platform_set_drvdata(pdev, dci);
753 drvdata->edac_dev_name = ecc_name;
754
755 drvdata->base = devm_ioremap(&pdev->dev, r->start, resource_size(r));
756 if (!drvdata->base)
757 goto fail1;
758
759 /* Get driver specific data for this EDAC device */
760 drvdata->data = of_match_node(altr_edac_device_of_match, np)->data;
761
762 /* Check specific dependencies for the module */
763 if (drvdata->data->setup) {
Thor Thayer328ca7a2016-03-21 11:01:40 -0500764 res = drvdata->data->setup(drvdata);
Thor Thayerc3eea192016-02-10 13:26:21 -0600765 if (res)
766 goto fail1;
767 }
768
769 drvdata->sb_irq = platform_get_irq(pdev, 0);
770 res = devm_request_irq(&pdev->dev, drvdata->sb_irq,
771 altr_edac_device_handler,
772 0, dev_name(&pdev->dev), dci);
773 if (res)
774 goto fail1;
775
776 drvdata->db_irq = platform_get_irq(pdev, 1);
777 res = devm_request_irq(&pdev->dev, drvdata->db_irq,
778 altr_edac_device_handler,
779 0, dev_name(&pdev->dev), dci);
780 if (res)
781 goto fail1;
782
783 dci->mod_name = "Altera ECC Manager";
784 dci->dev_name = drvdata->edac_dev_name;
785
786 res = edac_device_add_device(dci);
787 if (res)
788 goto fail1;
789
790 altr_create_edacdev_dbgfs(dci, drvdata->data);
791
792 devres_close_group(&pdev->dev, NULL);
793
794 return 0;
795
796fail1:
797 edac_device_free_ctl_info(dci);
798fail:
799 devres_release_group(&pdev->dev, NULL);
800 edac_printk(KERN_ERR, EDAC_DEVICE,
801 "%s:Error setting up EDAC device: %d\n", ecc_name, res);
802
803 return res;
804}
805
806static int altr_edac_device_remove(struct platform_device *pdev)
807{
808 struct edac_device_ctl_info *dci = platform_get_drvdata(pdev);
809 struct altr_edac_device_dev *drvdata = dci->pvt_info;
810
811 debugfs_remove_recursive(drvdata->debugfs_dir);
812 edac_device_del_device(&pdev->dev);
813 edac_device_free_ctl_info(dci);
814
815 return 0;
816}
817
818static struct platform_driver altr_edac_device_driver = {
819 .probe = altr_edac_device_probe,
820 .remove = altr_edac_device_remove,
821 .driver = {
822 .name = "altr_edac_device",
823 .of_match_table = altr_edac_device_of_match,
824 },
825};
826module_platform_driver(altr_edac_device_driver);
827
828/*********************** OCRAM EDAC Device Functions *********************/
829
830#ifdef CONFIG_EDAC_ALTERA_OCRAM
Arnd Bergmann1aa6eb52016-04-16 22:13:56 +0200831/*
832 * Test for memory's ECC dependencies upon entry because platform specific
833 * startup should have initialized the memory and enabled the ECC.
834 * Can't turn on ECC here because accessing un-initialized memory will
835 * cause CE/UE errors possibly causing an ABORT.
836 */
837static int altr_check_ecc_deps(struct altr_edac_device_dev *device)
838{
839 void __iomem *base = device->base;
840 const struct edac_device_prv_data *prv = device->data;
841
842 if (readl(base + prv->ecc_en_ofst) & prv->ecc_enable_mask)
843 return 0;
844
845 edac_printk(KERN_ERR, EDAC_DEVICE,
846 "%s: No ECC present or ECC disabled.\n",
847 device->edac_dev_name);
848 return -ENODEV;
849}
Thor Thayerc3eea192016-02-10 13:26:21 -0600850
851static void *ocram_alloc_mem(size_t size, void **other)
852{
853 struct device_node *np;
854 struct gen_pool *gp;
855 void *sram_addr;
856
857 np = of_find_compatible_node(NULL, NULL, "altr,socfpga-ocram-ecc");
858 if (!np)
859 return NULL;
860
861 gp = of_gen_pool_get(np, "iram", 0);
862 of_node_put(np);
863 if (!gp)
864 return NULL;
865
866 sram_addr = (void *)gen_pool_alloc(gp, size);
867 if (!sram_addr)
868 return NULL;
869
870 memset(sram_addr, 0, size);
871 /* Ensure data is written out */
872 wmb();
873
874 /* Remember this handle for freeing later */
875 *other = gp;
876
877 return sram_addr;
878}
879
880static void ocram_free_mem(void *p, size_t size, void *other)
881{
882 gen_pool_free((struct gen_pool *)other, (u32)p, size);
883}
884
Thor Thayer13ab8442016-06-07 15:35:57 -0500885static irqreturn_t altr_edac_a10_ecc_irq(int irq, void *dev_id)
Arnd Bergmann1aa6eb52016-04-16 22:13:56 +0200886{
Thor Thayer13ab8442016-06-07 15:35:57 -0500887 struct altr_edac_device_dev *dci = dev_id;
Arnd Bergmann1aa6eb52016-04-16 22:13:56 +0200888 void __iomem *base = dci->base;
889
Thor Thayer13ab8442016-06-07 15:35:57 -0500890 if (irq == dci->sb_irq) {
Arnd Bergmann1aa6eb52016-04-16 22:13:56 +0200891 writel(ALTR_A10_ECC_SERRPENA,
892 base + ALTR_A10_ECC_INTSTAT_OFST);
893 edac_device_handle_ce(dci->edac_dev, 0, 0, dci->edac_dev_name);
Thor Thayer13ab8442016-06-07 15:35:57 -0500894
895 return IRQ_HANDLED;
896 } else if (irq == dci->db_irq) {
Arnd Bergmann1aa6eb52016-04-16 22:13:56 +0200897 writel(ALTR_A10_ECC_DERRPENA,
898 base + ALTR_A10_ECC_INTSTAT_OFST);
899 edac_device_handle_ue(dci->edac_dev, 0, 0, dci->edac_dev_name);
Thor Thayer2b083d62016-06-22 08:58:53 -0500900 if (dci->data->panic)
901 panic("\nEDAC:ECC_DEVICE[Uncorrectable errors]\n");
Thor Thayer13ab8442016-06-07 15:35:57 -0500902
903 return IRQ_HANDLED;
Arnd Bergmann1aa6eb52016-04-16 22:13:56 +0200904 }
Thor Thayer13ab8442016-06-07 15:35:57 -0500905
906 WARN_ON(1);
907
908 return IRQ_NONE;
Arnd Bergmann1aa6eb52016-04-16 22:13:56 +0200909}
910
Thor Thayer1cf70372016-06-22 08:58:54 -0500911static const struct edac_device_prv_data ocramecc_data = {
Thor Thayeraa1f06d2016-03-31 13:48:03 -0500912 .setup = altr_check_ecc_deps,
Thor Thayerc3eea192016-02-10 13:26:21 -0600913 .ce_clear_mask = (ALTR_OCR_ECC_EN | ALTR_OCR_ECC_SERR),
914 .ue_clear_mask = (ALTR_OCR_ECC_EN | ALTR_OCR_ECC_DERR),
915 .dbgfs_name = "altr_ocram_trigger",
916 .alloc_mem = ocram_alloc_mem,
917 .free_mem = ocram_free_mem,
918 .ecc_enable_mask = ALTR_OCR_ECC_EN,
Thor Thayer943ad912016-03-31 13:48:02 -0500919 .ecc_en_ofst = ALTR_OCR_ECC_REG_OFFSET,
Thor Thayerc3eea192016-02-10 13:26:21 -0600920 .ce_set_mask = (ALTR_OCR_ECC_EN | ALTR_OCR_ECC_INJS),
921 .ue_set_mask = (ALTR_OCR_ECC_EN | ALTR_OCR_ECC_INJD),
Thor Thayer811fce42016-03-21 11:01:42 -0500922 .set_err_ofst = ALTR_OCR_ECC_REG_OFFSET,
Thor Thayerc3eea192016-02-10 13:26:21 -0600923 .trig_alloc_sz = ALTR_TRIG_OCRAM_BYTE_SIZE,
Thor Thayere17ced22016-03-31 13:48:01 -0500924 .inject_fops = &altr_edac_device_inject_fops,
Thor Thayerc3eea192016-02-10 13:26:21 -0600925};
926
Thor Thayer1cf70372016-06-22 08:58:54 -0500927static const struct edac_device_prv_data a10_ocramecc_data = {
Thor Thayerc7b4be82016-04-06 20:22:54 -0500928 .setup = altr_check_ecc_deps,
929 .ce_clear_mask = ALTR_A10_ECC_SERRPENA,
930 .ue_clear_mask = ALTR_A10_ECC_DERRPENA,
931 .irq_status_mask = A10_SYSMGR_ECC_INTSTAT_OCRAM,
932 .dbgfs_name = "altr_ocram_trigger",
933 .ecc_enable_mask = ALTR_A10_OCRAM_ECC_EN_CTL,
934 .ecc_en_ofst = ALTR_A10_ECC_CTRL_OFST,
935 .ce_set_mask = ALTR_A10_ECC_TSERRA,
936 .ue_set_mask = ALTR_A10_ECC_TDERRA,
937 .set_err_ofst = ALTR_A10_ECC_INTTEST_OFST,
938 .ecc_irq_handler = altr_edac_a10_ecc_irq,
939 .inject_fops = &altr_edac_a10_device_inject_fops,
Thor Thayer2b083d62016-06-22 08:58:53 -0500940 /*
941 * OCRAM panic on uncorrectable error because sleep/resume
942 * functions and FPGA contents are stored in OCRAM. Prefer
943 * a kernel panic over executing/loading corrupted data.
944 */
945 .panic = true,
Thor Thayerc7b4be82016-04-06 20:22:54 -0500946};
947
Thor Thayerc3eea192016-02-10 13:26:21 -0600948#endif /* CONFIG_EDAC_ALTERA_OCRAM */
949
950/********************* L2 Cache EDAC Device Functions ********************/
951
952#ifdef CONFIG_EDAC_ALTERA_L2C
953
954static void *l2_alloc_mem(size_t size, void **other)
955{
956 struct device *dev = *other;
957 void *ptemp = devm_kzalloc(dev, size, GFP_KERNEL);
958
959 if (!ptemp)
960 return NULL;
961
962 /* Make sure everything is written out */
963 wmb();
964
965 /*
966 * Clean all cache levels up to LoC (includes L2)
967 * This ensures the corrupted data is written into
968 * L2 cache for readback test (which causes ECC error).
969 */
970 flush_cache_all();
971
972 return ptemp;
973}
974
975static void l2_free_mem(void *p, size_t size, void *other)
976{
977 struct device *dev = other;
978
979 if (dev && p)
980 devm_kfree(dev, p);
981}
982
983/*
984 * altr_l2_check_deps()
985 * Test for L2 cache ECC dependencies upon entry because
986 * platform specific startup should have initialized the L2
987 * memory and enabled the ECC.
988 * Bail if ECC is not enabled.
989 * Note that L2 Cache Enable is forced at build time.
990 */
Thor Thayer328ca7a2016-03-21 11:01:40 -0500991static int altr_l2_check_deps(struct altr_edac_device_dev *device)
Thor Thayerc3eea192016-02-10 13:26:21 -0600992{
Thor Thayer328ca7a2016-03-21 11:01:40 -0500993 void __iomem *base = device->base;
Thor Thayer27439a12016-03-21 11:01:41 -0500994 const struct edac_device_prv_data *prv = device->data;
995
996 if ((readl(base) & prv->ecc_enable_mask) ==
997 prv->ecc_enable_mask)
Thor Thayerc3eea192016-02-10 13:26:21 -0600998 return 0;
999
1000 edac_printk(KERN_ERR, EDAC_DEVICE,
1001 "L2: No ECC present, or ECC disabled\n");
1002 return -ENODEV;
1003}
1004
Thor Thayer13ab8442016-06-07 15:35:57 -05001005static irqreturn_t altr_edac_a10_l2_irq(int irq, void *dev_id)
Thor Thayer588cb032016-03-21 11:01:44 -05001006{
Thor Thayer13ab8442016-06-07 15:35:57 -05001007 struct altr_edac_device_dev *dci = dev_id;
1008
1009 if (irq == dci->sb_irq) {
Thor Thayer588cb032016-03-21 11:01:44 -05001010 regmap_write(dci->edac->ecc_mgr_map,
1011 A10_SYSGMR_MPU_CLEAR_L2_ECC_OFST,
1012 A10_SYSGMR_MPU_CLEAR_L2_ECC_SB);
1013 edac_device_handle_ce(dci->edac_dev, 0, 0, dci->edac_dev_name);
Thor Thayer13ab8442016-06-07 15:35:57 -05001014
1015 return IRQ_HANDLED;
1016 } else if (irq == dci->db_irq) {
Thor Thayer588cb032016-03-21 11:01:44 -05001017 regmap_write(dci->edac->ecc_mgr_map,
1018 A10_SYSGMR_MPU_CLEAR_L2_ECC_OFST,
1019 A10_SYSGMR_MPU_CLEAR_L2_ECC_MB);
1020 edac_device_handle_ue(dci->edac_dev, 0, 0, dci->edac_dev_name);
1021 panic("\nEDAC:ECC_DEVICE[Uncorrectable errors]\n");
Thor Thayer13ab8442016-06-07 15:35:57 -05001022
1023 return IRQ_HANDLED;
Thor Thayer588cb032016-03-21 11:01:44 -05001024 }
Thor Thayer13ab8442016-06-07 15:35:57 -05001025
1026 WARN_ON(1);
1027
1028 return IRQ_NONE;
Thor Thayer588cb032016-03-21 11:01:44 -05001029}
1030
Thor Thayer1cf70372016-06-22 08:58:54 -05001031static const struct edac_device_prv_data l2ecc_data = {
Thor Thayerc3eea192016-02-10 13:26:21 -06001032 .setup = altr_l2_check_deps,
1033 .ce_clear_mask = 0,
1034 .ue_clear_mask = 0,
1035 .dbgfs_name = "altr_l2_trigger",
1036 .alloc_mem = l2_alloc_mem,
1037 .free_mem = l2_free_mem,
1038 .ecc_enable_mask = ALTR_L2_ECC_EN,
1039 .ce_set_mask = (ALTR_L2_ECC_EN | ALTR_L2_ECC_INJS),
1040 .ue_set_mask = (ALTR_L2_ECC_EN | ALTR_L2_ECC_INJD),
Thor Thayer811fce42016-03-21 11:01:42 -05001041 .set_err_ofst = ALTR_L2_ECC_REG_OFFSET,
Thor Thayerc3eea192016-02-10 13:26:21 -06001042 .trig_alloc_sz = ALTR_TRIG_L2C_BYTE_SIZE,
Thor Thayere17ced22016-03-31 13:48:01 -05001043 .inject_fops = &altr_edac_device_inject_fops,
Thor Thayerc3eea192016-02-10 13:26:21 -06001044};
1045
Thor Thayer1cf70372016-06-22 08:58:54 -05001046static const struct edac_device_prv_data a10_l2ecc_data = {
Thor Thayer588cb032016-03-21 11:01:44 -05001047 .setup = altr_l2_check_deps,
1048 .ce_clear_mask = ALTR_A10_L2_ECC_SERR_CLR,
1049 .ue_clear_mask = ALTR_A10_L2_ECC_MERR_CLR,
1050 .irq_status_mask = A10_SYSMGR_ECC_INTSTAT_L2,
1051 .dbgfs_name = "altr_l2_trigger",
1052 .alloc_mem = l2_alloc_mem,
1053 .free_mem = l2_free_mem,
1054 .ecc_enable_mask = ALTR_A10_L2_ECC_EN_CTL,
1055 .ce_set_mask = ALTR_A10_L2_ECC_CE_INJ_MASK,
1056 .ue_set_mask = ALTR_A10_L2_ECC_UE_INJ_MASK,
1057 .set_err_ofst = ALTR_A10_L2_ECC_INJ_OFST,
1058 .ecc_irq_handler = altr_edac_a10_l2_irq,
1059 .trig_alloc_sz = ALTR_TRIG_L2C_BYTE_SIZE,
Thor Thayere17ced22016-03-31 13:48:01 -05001060 .inject_fops = &altr_edac_device_inject_fops,
Thor Thayer588cb032016-03-21 11:01:44 -05001061};
1062
Thor Thayerc3eea192016-02-10 13:26:21 -06001063#endif /* CONFIG_EDAC_ALTERA_L2C */
1064
Thor Thayer588cb032016-03-21 11:01:44 -05001065/********************* Arria10 EDAC Device Functions *************************/
Thor Thayerab564cb2016-05-25 11:29:41 -05001066static const struct of_device_id altr_edac_a10_device_of_match[] = {
1067#ifdef CONFIG_EDAC_ALTERA_L2C
1068 { .compatible = "altr,socfpga-a10-l2-ecc", .data = &a10_l2ecc_data },
1069#endif
1070#ifdef CONFIG_EDAC_ALTERA_OCRAM
1071 { .compatible = "altr,socfpga-a10-ocram-ecc",
1072 .data = &a10_ocramecc_data },
1073#endif
1074 {},
1075};
1076MODULE_DEVICE_TABLE(of, altr_edac_a10_device_of_match);
Thor Thayer588cb032016-03-21 11:01:44 -05001077
1078/*
1079 * The Arria10 EDAC Device Functions differ from the Cyclone5/Arria5
1080 * because 2 IRQs are shared among the all ECC peripherals. The ECC
1081 * manager manages the IRQs and the children.
1082 * Based on xgene_edac.c peripheral code.
1083 */
1084
Thor Thayerc7b4be82016-04-06 20:22:54 -05001085static ssize_t altr_edac_a10_device_trig(struct file *file,
1086 const char __user *user_buf,
1087 size_t count, loff_t *ppos)
1088{
1089 struct edac_device_ctl_info *edac_dci = file->private_data;
1090 struct altr_edac_device_dev *drvdata = edac_dci->pvt_info;
1091 const struct edac_device_prv_data *priv = drvdata->data;
1092 void __iomem *set_addr = (drvdata->base + priv->set_err_ofst);
1093 unsigned long flags;
1094 u8 trig_type;
1095
1096 if (!user_buf || get_user(trig_type, user_buf))
1097 return -EFAULT;
1098
1099 local_irq_save(flags);
1100 if (trig_type == ALTR_UE_TRIGGER_CHAR)
1101 writel(priv->ue_set_mask, set_addr);
1102 else
1103 writel(priv->ce_set_mask, set_addr);
1104 /* Ensure the interrupt test bits are set */
1105 wmb();
1106 local_irq_restore(flags);
1107
1108 return count;
1109}
1110
Thor Thayer13ab8442016-06-07 15:35:57 -05001111static void altr_edac_a10_irq_handler(struct irq_desc *desc)
Thor Thayer588cb032016-03-21 11:01:44 -05001112{
Thor Thayer13ab8442016-06-07 15:35:57 -05001113 int dberr, bit, sm_offset, irq_status;
1114 struct altr_arria10_edac *edac = irq_desc_get_handler_data(desc);
1115 struct irq_chip *chip = irq_desc_get_chip(desc);
1116 int irq = irq_desc_get_irq(desc);
1117
1118 dberr = (irq == edac->db_irq) ? 1 : 0;
1119 sm_offset = dberr ? A10_SYSMGR_ECC_INTSTAT_DERR_OFST :
1120 A10_SYSMGR_ECC_INTSTAT_SERR_OFST;
1121
1122 chained_irq_enter(chip, desc);
Thor Thayer588cb032016-03-21 11:01:44 -05001123
1124 regmap_read(edac->ecc_mgr_map, sm_offset, &irq_status);
1125
Thor Thayer13ab8442016-06-07 15:35:57 -05001126 for_each_set_bit(bit, (unsigned long *)&irq_status, 32) {
1127 irq = irq_linear_revmap(edac->domain, dberr * 32 + bit);
1128 if (irq)
1129 generic_handle_irq(irq);
Thor Thayer588cb032016-03-21 11:01:44 -05001130 }
1131
Thor Thayer13ab8442016-06-07 15:35:57 -05001132 chained_irq_exit(chip, desc);
Thor Thayer588cb032016-03-21 11:01:44 -05001133}
1134
Thor Thayer44ec9b32016-06-22 08:58:52 -05001135static int validate_parent_available(struct device_node *np)
1136{
1137 struct device_node *parent;
1138 int ret = 0;
1139
1140 /* Ensure parent device is enabled if parent node exists */
1141 parent = of_parse_phandle(np, "altr,ecc-parent", 0);
1142 if (parent && !of_device_is_available(parent))
1143 ret = -ENODEV;
1144
1145 of_node_put(parent);
1146 return ret;
1147}
1148
Thor Thayer588cb032016-03-21 11:01:44 -05001149static int altr_edac_a10_device_add(struct altr_arria10_edac *edac,
1150 struct device_node *np)
1151{
1152 struct edac_device_ctl_info *dci;
1153 struct altr_edac_device_dev *altdev;
1154 char *ecc_name = (char *)np->name;
1155 struct resource res;
1156 int edac_idx;
1157 int rc = 0;
1158 const struct edac_device_prv_data *prv;
1159 /* Get matching node and check for valid result */
1160 const struct of_device_id *pdev_id =
Thor Thayerab564cb2016-05-25 11:29:41 -05001161 of_match_node(altr_edac_a10_device_of_match, np);
Thor Thayer588cb032016-03-21 11:01:44 -05001162 if (IS_ERR_OR_NULL(pdev_id))
1163 return -ENODEV;
1164
1165 /* Get driver specific data for this EDAC device */
1166 prv = pdev_id->data;
1167 if (IS_ERR_OR_NULL(prv))
1168 return -ENODEV;
1169
Thor Thayer44ec9b32016-06-22 08:58:52 -05001170 if (validate_parent_available(np))
1171 return -ENODEV;
1172
Thor Thayer588cb032016-03-21 11:01:44 -05001173 if (!devres_open_group(edac->dev, altr_edac_a10_device_add, GFP_KERNEL))
1174 return -ENOMEM;
1175
1176 rc = of_address_to_resource(np, 0, &res);
1177 if (rc < 0) {
1178 edac_printk(KERN_ERR, EDAC_DEVICE,
1179 "%s: no resource address\n", ecc_name);
1180 goto err_release_group;
1181 }
1182
1183 edac_idx = edac_device_alloc_index();
1184 dci = edac_device_alloc_ctl_info(sizeof(*altdev), ecc_name,
1185 1, ecc_name, 1, 0, NULL, 0,
1186 edac_idx);
1187
1188 if (!dci) {
1189 edac_printk(KERN_ERR, EDAC_DEVICE,
1190 "%s: Unable to allocate EDAC device\n", ecc_name);
1191 rc = -ENOMEM;
1192 goto err_release_group;
1193 }
1194
1195 altdev = dci->pvt_info;
1196 dci->dev = edac->dev;
1197 altdev->edac_dev_name = ecc_name;
1198 altdev->edac_idx = edac_idx;
1199 altdev->edac = edac;
1200 altdev->edac_dev = dci;
1201 altdev->data = prv;
1202 altdev->ddev = *edac->dev;
1203 dci->dev = &altdev->ddev;
1204 dci->ctl_name = "Altera ECC Manager";
1205 dci->mod_name = ecc_name;
1206 dci->dev_name = ecc_name;
1207
1208 altdev->base = devm_ioremap_resource(edac->dev, &res);
1209 if (IS_ERR(altdev->base)) {
1210 rc = PTR_ERR(altdev->base);
1211 goto err_release_group1;
1212 }
1213
1214 /* Check specific dependencies for the module */
1215 if (altdev->data->setup) {
1216 rc = altdev->data->setup(altdev);
1217 if (rc)
1218 goto err_release_group1;
1219 }
1220
Thor Thayer13ab8442016-06-07 15:35:57 -05001221 altdev->sb_irq = irq_of_parse_and_map(np, 0);
1222 if (!altdev->sb_irq) {
1223 edac_printk(KERN_ERR, EDAC_DEVICE, "Error allocating SBIRQ\n");
1224 rc = -ENODEV;
1225 goto err_release_group1;
1226 }
1227 rc = devm_request_irq(edac->dev, altdev->sb_irq,
1228 prv->ecc_irq_handler,
1229 IRQF_SHARED, ecc_name, altdev);
1230 if (rc) {
1231 edac_printk(KERN_ERR, EDAC_DEVICE, "No DBERR IRQ resource\n");
1232 goto err_release_group1;
1233 }
1234
1235 altdev->db_irq = irq_of_parse_and_map(np, 1);
1236 if (!altdev->db_irq) {
1237 edac_printk(KERN_ERR, EDAC_DEVICE, "Error allocating DBIRQ\n");
1238 rc = -ENODEV;
1239 goto err_release_group1;
1240 }
1241 rc = devm_request_irq(edac->dev, altdev->db_irq,
1242 prv->ecc_irq_handler,
1243 IRQF_SHARED, ecc_name, altdev);
1244 if (rc) {
1245 edac_printk(KERN_ERR, EDAC_DEVICE, "No DBERR IRQ resource\n");
1246 goto err_release_group1;
1247 }
1248
Thor Thayer588cb032016-03-21 11:01:44 -05001249 rc = edac_device_add_device(dci);
1250 if (rc) {
1251 dev_err(edac->dev, "edac_device_add_device failed\n");
1252 rc = -ENOMEM;
1253 goto err_release_group1;
1254 }
1255
1256 altr_create_edacdev_dbgfs(dci, prv);
1257
1258 list_add(&altdev->next, &edac->a10_ecc_devices);
1259
1260 devres_remove_group(edac->dev, altr_edac_a10_device_add);
1261
1262 return 0;
1263
1264err_release_group1:
1265 edac_device_free_ctl_info(dci);
1266err_release_group:
Thor Thayer588cb032016-03-21 11:01:44 -05001267 devres_release_group(edac->dev, NULL);
1268 edac_printk(KERN_ERR, EDAC_DEVICE,
1269 "%s:Error setting up EDAC device: %d\n", ecc_name, rc);
1270
1271 return rc;
1272}
1273
Thor Thayer13ab8442016-06-07 15:35:57 -05001274static void a10_eccmgr_irq_mask(struct irq_data *d)
1275{
1276 struct altr_arria10_edac *edac = irq_data_get_irq_chip_data(d);
1277
1278 regmap_write(edac->ecc_mgr_map, A10_SYSMGR_ECC_INTMASK_SET_OFST,
1279 BIT(d->hwirq));
1280}
1281
1282static void a10_eccmgr_irq_unmask(struct irq_data *d)
1283{
1284 struct altr_arria10_edac *edac = irq_data_get_irq_chip_data(d);
1285
1286 regmap_write(edac->ecc_mgr_map, A10_SYSMGR_ECC_INTMASK_CLR_OFST,
1287 BIT(d->hwirq));
1288}
1289
1290static int a10_eccmgr_irqdomain_map(struct irq_domain *d, unsigned int irq,
1291 irq_hw_number_t hwirq)
1292{
1293 struct altr_arria10_edac *edac = d->host_data;
1294
1295 irq_set_chip_and_handler(irq, &edac->irq_chip, handle_simple_irq);
1296 irq_set_chip_data(irq, edac);
1297 irq_set_noprobe(irq);
1298
1299 return 0;
1300}
1301
1302struct irq_domain_ops a10_eccmgr_ic_ops = {
1303 .map = a10_eccmgr_irqdomain_map,
1304 .xlate = irq_domain_xlate_twocell,
1305};
1306
Thor Thayer588cb032016-03-21 11:01:44 -05001307static int altr_edac_a10_probe(struct platform_device *pdev)
1308{
1309 struct altr_arria10_edac *edac;
1310 struct device_node *child;
Thor Thayer588cb032016-03-21 11:01:44 -05001311
1312 edac = devm_kzalloc(&pdev->dev, sizeof(*edac), GFP_KERNEL);
1313 if (!edac)
1314 return -ENOMEM;
1315
1316 edac->dev = &pdev->dev;
1317 platform_set_drvdata(pdev, edac);
1318 INIT_LIST_HEAD(&edac->a10_ecc_devices);
1319
1320 edac->ecc_mgr_map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
1321 "altr,sysmgr-syscon");
1322 if (IS_ERR(edac->ecc_mgr_map)) {
1323 edac_printk(KERN_ERR, EDAC_DEVICE,
1324 "Unable to get syscon altr,sysmgr-syscon\n");
1325 return PTR_ERR(edac->ecc_mgr_map);
1326 }
1327
Thor Thayer13ab8442016-06-07 15:35:57 -05001328 edac->irq_chip.name = pdev->dev.of_node->name;
1329 edac->irq_chip.irq_mask = a10_eccmgr_irq_mask;
1330 edac->irq_chip.irq_unmask = a10_eccmgr_irq_unmask;
1331 edac->domain = irq_domain_add_linear(pdev->dev.of_node, 64,
1332 &a10_eccmgr_ic_ops, edac);
1333 if (!edac->domain) {
1334 dev_err(&pdev->dev, "Error adding IRQ domain\n");
1335 return -ENOMEM;
Thor Thayer588cb032016-03-21 11:01:44 -05001336 }
1337
Thor Thayer13ab8442016-06-07 15:35:57 -05001338 edac->sb_irq = platform_get_irq(pdev, 0);
1339 if (edac->sb_irq < 0) {
1340 dev_err(&pdev->dev, "No SBERR IRQ resource\n");
1341 return edac->sb_irq;
Thor Thayer588cb032016-03-21 11:01:44 -05001342 }
1343
Thor Thayer13ab8442016-06-07 15:35:57 -05001344 irq_set_chained_handler_and_data(edac->sb_irq,
1345 altr_edac_a10_irq_handler,
1346 edac);
1347
1348 edac->db_irq = platform_get_irq(pdev, 1);
1349 if (edac->db_irq < 0) {
1350 dev_err(&pdev->dev, "No DBERR IRQ resource\n");
1351 return edac->db_irq;
1352 }
1353 irq_set_chained_handler_and_data(edac->db_irq,
1354 altr_edac_a10_irq_handler,
1355 edac);
1356
Thor Thayer588cb032016-03-21 11:01:44 -05001357 for_each_child_of_node(pdev->dev.of_node, child) {
1358 if (!of_device_is_available(child))
1359 continue;
1360 if (of_device_is_compatible(child, "altr,socfpga-a10-l2-ecc"))
1361 altr_edac_a10_device_add(edac, child);
Thor Thayerc7b4be82016-04-06 20:22:54 -05001362 else if (of_device_is_compatible(child,
1363 "altr,socfpga-a10-ocram-ecc"))
1364 altr_edac_a10_device_add(edac, child);
Thor Thayerab564cb2016-05-25 11:29:41 -05001365 else if (of_device_is_compatible(child,
1366 "altr,sdram-edac-a10"))
1367 of_platform_populate(pdev->dev.of_node,
1368 altr_sdram_ctrl_of_match,
1369 NULL, &pdev->dev);
Thor Thayer588cb032016-03-21 11:01:44 -05001370 }
1371
1372 return 0;
1373}
1374
1375static const struct of_device_id altr_edac_a10_of_match[] = {
1376 { .compatible = "altr,socfpga-a10-ecc-manager" },
1377 {},
1378};
1379MODULE_DEVICE_TABLE(of, altr_edac_a10_of_match);
1380
1381static struct platform_driver altr_edac_a10_driver = {
1382 .probe = altr_edac_a10_probe,
1383 .driver = {
1384 .name = "socfpga_a10_ecc_manager",
1385 .of_match_table = altr_edac_a10_of_match,
1386 },
1387};
1388module_platform_driver(altr_edac_a10_driver);
1389
Thor Thayer71bcada2014-09-03 10:27:54 -05001390MODULE_LICENSE("GPL v2");
1391MODULE_AUTHOR("Thor Thayer");
Thor Thayerc3eea192016-02-10 13:26:21 -06001392MODULE_DESCRIPTION("EDAC Driver for Altera Memories");