diff options
author | Thor Thayer <tthayer@opensource.altera.com> | 2015-06-04 10:28:46 -0400 |
---|---|---|
committer | Borislav Petkov <bp@suse.de> | 2015-06-24 12:16:08 -0400 |
commit | 143f4a5ac5af82a4055100c8f40b26187d5c20ba (patch) | |
tree | ac65223b91db64f2823deefd7552f23e1d9ba116 | |
parent | f9ae487e04370e229a96c83a8c86510299712192 (diff) |
EDAC, altera: Refactor for Altera CycloneV SoC
The Arria10 SoC uses a completely different SDRAM controller from the
earlier CycloneV and ArriaV SoCs. This patch abstracts the SDRAM bits
for the CycloneV/ArriaV SoCs in preparation for the Arria10 support.
Signed-off-by: Thor Thayer <tthayer@opensource.altera.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: devicetree@vger.kernel.org
Cc: dinguyen@opensource.altera.com
Cc: galak@codeaurora.org
Cc: grant.likely@linaro.org
Cc: ijc+devicetree@hellion.org.uk
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-edac <linux-edac@vger.kernel.org>
Cc: m.chehab@samsung.com
Cc: mark.rutland@arm.com
Cc: pawel.moll@arm.com
Cc: robh+dt@kernel.org
Cc: tthayer.linux@gmail.com
Link: http://lkml.kernel.org/r/1433428128-7292-3-git-send-email-tthayer@opensource.altera.com
Signed-off-by: Borislav Petkov <bp@suse.de>
-rw-r--r-- | drivers/edac/altera_edac.c | 194 | ||||
-rw-r--r-- | drivers/edac/altera_edac.h | 116 |
2 files changed, 206 insertions, 104 deletions
diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c index 1d55c5b98024..4ac4e6c11ece 100644 --- a/drivers/edac/altera_edac.c +++ b/drivers/edac/altera_edac.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright Altera Corporation (C) 2014. All rights reserved. | 2 | * Copyright Altera Corporation (C) 2014-2015. All rights reserved. |
3 | * Copyright 2011-2012 Calxeda, Inc. | 3 | * Copyright 2011-2012 Calxeda, Inc. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
@@ -28,111 +28,64 @@ | |||
28 | #include <linux/types.h> | 28 | #include <linux/types.h> |
29 | #include <linux/uaccess.h> | 29 | #include <linux/uaccess.h> |
30 | 30 | ||
31 | #include "altera_edac.h" | ||
31 | #include "edac_core.h" | 32 | #include "edac_core.h" |
32 | #include "edac_module.h" | 33 | #include "edac_module.h" |
33 | 34 | ||
34 | #define EDAC_MOD_STR "altera_edac" | 35 | #define EDAC_MOD_STR "altera_edac" |
35 | #define EDAC_VERSION "1" | 36 | #define EDAC_VERSION "1" |
36 | 37 | ||
37 | /* SDRAM Controller CtrlCfg Register */ | 38 | static const struct altr_sdram_prv_data c5_data = { |
38 | #define CTLCFG_OFST 0x00 | 39 | .ecc_ctrl_offset = CV_CTLCFG_OFST, |
39 | 40 | .ecc_ctl_en_mask = CV_CTLCFG_ECC_AUTO_EN, | |
40 | /* SDRAM Controller CtrlCfg Register Bit Masks */ | 41 | .ecc_stat_offset = CV_DRAMSTS_OFST, |
41 | #define CTLCFG_ECC_EN 0x400 | 42 | .ecc_stat_ce_mask = CV_DRAMSTS_SBEERR, |
42 | #define CTLCFG_ECC_CORR_EN 0x800 | 43 | .ecc_stat_ue_mask = CV_DRAMSTS_DBEERR, |
43 | #define CTLCFG_GEN_SB_ERR 0x2000 | 44 | .ecc_saddr_offset = CV_ERRADDR_OFST, |
44 | #define CTLCFG_GEN_DB_ERR 0x4000 | 45 | .ecc_cecnt_offset = CV_SBECOUNT_OFST, |
45 | 46 | .ecc_uecnt_offset = CV_DBECOUNT_OFST, | |
46 | #define CTLCFG_ECC_AUTO_EN (CTLCFG_ECC_EN | \ | 47 | .ecc_irq_en_offset = CV_DRAMINTR_OFST, |
47 | CTLCFG_ECC_CORR_EN) | 48 | .ecc_irq_en_mask = CV_DRAMINTR_INTREN, |
48 | 49 | .ecc_irq_clr_offset = CV_DRAMINTR_OFST, | |
49 | /* SDRAM Controller Address Width Register */ | 50 | .ecc_irq_clr_mask = (CV_DRAMINTR_INTRCLR | CV_DRAMINTR_INTREN), |
50 | #define DRAMADDRW_OFST 0x2C | 51 | .ecc_cnt_rst_offset = CV_DRAMINTR_OFST, |
51 | 52 | .ecc_cnt_rst_mask = CV_DRAMINTR_INTRCLR, | |
52 | /* SDRAM Controller Address Widths Field Register */ | 53 | #ifdef CONFIG_EDAC_DEBUG |
53 | #define DRAMADDRW_COLBIT_MASK 0x001F | 54 | .ce_ue_trgr_offset = CV_CTLCFG_OFST, |
54 | #define DRAMADDRW_COLBIT_SHIFT 0 | 55 | .ce_set_mask = CV_CTLCFG_GEN_SB_ERR, |
55 | #define DRAMADDRW_ROWBIT_MASK 0x03E0 | 56 | .ue_set_mask = CV_CTLCFG_GEN_DB_ERR, |
56 | #define DRAMADDRW_ROWBIT_SHIFT 5 | 57 | #endif |
57 | #define DRAMADDRW_BANKBIT_MASK 0x1C00 | ||
58 | #define DRAMADDRW_BANKBIT_SHIFT 10 | ||
59 | #define DRAMADDRW_CSBIT_MASK 0xE000 | ||
60 | #define DRAMADDRW_CSBIT_SHIFT 13 | ||
61 | |||
62 | /* SDRAM Controller Interface Data Width Register */ | ||
63 | #define DRAMIFWIDTH_OFST 0x30 | ||
64 | |||
65 | /* SDRAM Controller Interface Data Width Defines */ | ||
66 | #define DRAMIFWIDTH_16B_ECC 24 | ||
67 | #define DRAMIFWIDTH_32B_ECC 40 | ||
68 | |||
69 | /* SDRAM Controller DRAM Status Register */ | ||
70 | #define DRAMSTS_OFST 0x38 | ||
71 | |||
72 | /* SDRAM Controller DRAM Status Register Bit Masks */ | ||
73 | #define DRAMSTS_SBEERR 0x04 | ||
74 | #define DRAMSTS_DBEERR 0x08 | ||
75 | #define DRAMSTS_CORR_DROP 0x10 | ||
76 | |||
77 | /* SDRAM Controller DRAM IRQ Register */ | ||
78 | #define DRAMINTR_OFST 0x3C | ||
79 | |||
80 | /* SDRAM Controller DRAM IRQ Register Bit Masks */ | ||
81 | #define DRAMINTR_INTREN 0x01 | ||
82 | #define DRAMINTR_SBEMASK 0x02 | ||
83 | #define DRAMINTR_DBEMASK 0x04 | ||
84 | #define DRAMINTR_CORRDROPMASK 0x08 | ||
85 | #define DRAMINTR_INTRCLR 0x10 | ||
86 | |||
87 | /* SDRAM Controller Single Bit Error Count Register */ | ||
88 | #define SBECOUNT_OFST 0x40 | ||
89 | |||
90 | /* SDRAM Controller Single Bit Error Count Register Bit Masks */ | ||
91 | #define SBECOUNT_MASK 0x0F | ||
92 | |||
93 | /* SDRAM Controller Double Bit Error Count Register */ | ||
94 | #define DBECOUNT_OFST 0x44 | ||
95 | |||
96 | /* SDRAM Controller Double Bit Error Count Register Bit Masks */ | ||
97 | #define DBECOUNT_MASK 0x0F | ||
98 | |||
99 | /* SDRAM Controller ECC Error Address Register */ | ||
100 | #define ERRADDR_OFST 0x48 | ||
101 | |||
102 | /* SDRAM Controller ECC Error Address Register Bit Masks */ | ||
103 | #define ERRADDR_MASK 0xFFFFFFFF | ||
104 | |||
105 | /* Altera SDRAM Memory Controller data */ | ||
106 | struct altr_sdram_mc_data { | ||
107 | struct regmap *mc_vbase; | ||
108 | }; | 58 | }; |
109 | 59 | ||
110 | static irqreturn_t altr_sdram_mc_err_handler(int irq, void *dev_id) | 60 | static irqreturn_t altr_sdram_mc_err_handler(int irq, void *dev_id) |
111 | { | 61 | { |
112 | struct mem_ctl_info *mci = dev_id; | 62 | struct mem_ctl_info *mci = dev_id; |
113 | struct altr_sdram_mc_data *drvdata = mci->pvt_info; | 63 | struct altr_sdram_mc_data *drvdata = mci->pvt_info; |
64 | const struct altr_sdram_prv_data *priv = drvdata->data; | ||
114 | u32 status, err_count, err_addr; | 65 | u32 status, err_count, err_addr; |
115 | 66 | ||
116 | /* Error Address is shared by both SBE & DBE */ | 67 | /* Error Address is shared by both SBE & DBE */ |
117 | regmap_read(drvdata->mc_vbase, ERRADDR_OFST, &err_addr); | 68 | regmap_read(drvdata->mc_vbase, priv->ecc_saddr_offset, &err_addr); |
118 | 69 | ||
119 | regmap_read(drvdata->mc_vbase, DRAMSTS_OFST, &status); | 70 | regmap_read(drvdata->mc_vbase, priv->ecc_stat_offset, &status); |
120 | 71 | ||
121 | if (status & DRAMSTS_DBEERR) { | 72 | if (status & priv->ecc_stat_ue_mask) { |
122 | regmap_read(drvdata->mc_vbase, DBECOUNT_OFST, &err_count); | 73 | regmap_read(drvdata->mc_vbase, priv->ecc_uecnt_offset, |
74 | &err_count); | ||
123 | panic("\nEDAC: [%d Uncorrectable errors @ 0x%08X]\n", | 75 | panic("\nEDAC: [%d Uncorrectable errors @ 0x%08X]\n", |
124 | err_count, err_addr); | 76 | err_count, err_addr); |
125 | } | 77 | } |
126 | if (status & DRAMSTS_SBEERR) { | 78 | if (status & priv->ecc_stat_ce_mask) { |
127 | regmap_read(drvdata->mc_vbase, SBECOUNT_OFST, &err_count); | 79 | regmap_read(drvdata->mc_vbase, priv->ecc_cecnt_offset, |
80 | &err_count); | ||
128 | edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, err_count, | 81 | edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, err_count, |
129 | err_addr >> PAGE_SHIFT, | 82 | err_addr >> PAGE_SHIFT, |
130 | err_addr & ~PAGE_MASK, 0, | 83 | err_addr & ~PAGE_MASK, 0, |
131 | 0, 0, -1, mci->ctl_name, ""); | 84 | 0, 0, -1, mci->ctl_name, ""); |
132 | } | 85 | } |
133 | 86 | ||
134 | regmap_write(drvdata->mc_vbase, DRAMINTR_OFST, | 87 | regmap_write(drvdata->mc_vbase, priv->ecc_irq_clr_offset, |
135 | (DRAMINTR_INTRCLR | DRAMINTR_INTREN)); | 88 | priv->ecc_irq_clr_mask); |
136 | 89 | ||
137 | return IRQ_HANDLED; | 90 | return IRQ_HANDLED; |
138 | } | 91 | } |
@@ -144,6 +97,7 @@ static ssize_t altr_sdr_mc_err_inject_write(struct file *file, | |||
144 | { | 97 | { |
145 | struct mem_ctl_info *mci = file->private_data; | 98 | struct mem_ctl_info *mci = file->private_data; |
146 | struct altr_sdram_mc_data *drvdata = mci->pvt_info; | 99 | struct altr_sdram_mc_data *drvdata = mci->pvt_info; |
100 | const struct altr_sdram_prv_data *priv = drvdata->data; | ||
147 | u32 *ptemp; | 101 | u32 *ptemp; |
148 | dma_addr_t dma_handle; | 102 | dma_addr_t dma_handle; |
149 | u32 reg, read_reg; | 103 | u32 reg, read_reg; |
@@ -156,8 +110,9 @@ static ssize_t altr_sdr_mc_err_inject_write(struct file *file, | |||
156 | return -ENOMEM; | 110 | return -ENOMEM; |
157 | } | 111 | } |
158 | 112 | ||
159 | regmap_read(drvdata->mc_vbase, CTLCFG_OFST, &read_reg); | 113 | regmap_read(drvdata->mc_vbase, priv->ce_ue_trgr_offset, |
160 | read_reg &= ~(CTLCFG_GEN_SB_ERR | CTLCFG_GEN_DB_ERR); | 114 | &read_reg); |
115 | read_reg &= ~(priv->ce_set_mask | priv->ue_set_mask); | ||
161 | 116 | ||
162 | /* Error are injected by writing a word while the SBE or DBE | 117 | /* Error are injected by writing a word while the SBE or DBE |
163 | * bit in the CTLCFG register is set. Reading the word will | 118 | * bit in the CTLCFG register is set. Reading the word will |
@@ -166,20 +121,20 @@ static ssize_t altr_sdr_mc_err_inject_write(struct file *file, | |||
166 | if (count == 3) { | 121 | if (count == 3) { |
167 | edac_printk(KERN_ALERT, EDAC_MC, | 122 | edac_printk(KERN_ALERT, EDAC_MC, |
168 | "Inject Double bit error\n"); | 123 | "Inject Double bit error\n"); |
169 | regmap_write(drvdata->mc_vbase, CTLCFG_OFST, | 124 | regmap_write(drvdata->mc_vbase, priv->ce_ue_trgr_offset, |
170 | (read_reg | CTLCFG_GEN_DB_ERR)); | 125 | (read_reg | priv->ue_set_mask)); |
171 | } else { | 126 | } else { |
172 | edac_printk(KERN_ALERT, EDAC_MC, | 127 | edac_printk(KERN_ALERT, EDAC_MC, |
173 | "Inject Single bit error\n"); | 128 | "Inject Single bit error\n"); |
174 | regmap_write(drvdata->mc_vbase, CTLCFG_OFST, | 129 | regmap_write(drvdata->mc_vbase, priv->ce_ue_trgr_offset, |
175 | (read_reg | CTLCFG_GEN_SB_ERR)); | 130 | (read_reg | priv->ce_set_mask)); |
176 | } | 131 | } |
177 | 132 | ||
178 | ptemp[0] = 0x5A5A5A5A; | 133 | ptemp[0] = 0x5A5A5A5A; |
179 | ptemp[1] = 0xA5A5A5A5; | 134 | ptemp[1] = 0xA5A5A5A5; |
180 | 135 | ||
181 | /* Clear the error injection bits */ | 136 | /* Clear the error injection bits */ |
182 | regmap_write(drvdata->mc_vbase, CTLCFG_OFST, read_reg); | 137 | regmap_write(drvdata->mc_vbase, priv->ce_ue_trgr_offset, read_reg); |
183 | /* Ensure it has been written out */ | 138 | /* Ensure it has been written out */ |
184 | wmb(); | 139 | wmb(); |
185 | 140 | ||
@@ -246,18 +201,29 @@ static unsigned long get_total_mem(void) | |||
246 | return total_mem; | 201 | return total_mem; |
247 | } | 202 | } |
248 | 203 | ||
204 | static const struct of_device_id altr_sdram_ctrl_of_match[] = { | ||
205 | { .compatible = "altr,sdram-edac", .data = (void *)&c5_data}, | ||
206 | {}, | ||
207 | }; | ||
208 | MODULE_DEVICE_TABLE(of, altr_sdram_ctrl_of_match); | ||
209 | |||
249 | static int altr_sdram_probe(struct platform_device *pdev) | 210 | static int altr_sdram_probe(struct platform_device *pdev) |
250 | { | 211 | { |
212 | const struct of_device_id *id; | ||
251 | struct edac_mc_layer layers[2]; | 213 | struct edac_mc_layer layers[2]; |
252 | struct mem_ctl_info *mci; | 214 | struct mem_ctl_info *mci; |
253 | struct altr_sdram_mc_data *drvdata; | 215 | struct altr_sdram_mc_data *drvdata; |
216 | const struct altr_sdram_prv_data *priv; | ||
254 | struct regmap *mc_vbase; | 217 | struct regmap *mc_vbase; |
255 | struct dimm_info *dimm; | 218 | struct dimm_info *dimm; |
256 | u32 read_reg, mem_size; | 219 | u32 read_reg; |
257 | int irq; | 220 | int irq, res = 0; |
258 | int res = 0; | 221 | unsigned long mem_size; |
222 | |||
223 | id = of_match_device(altr_sdram_ctrl_of_match, &pdev->dev); | ||
224 | if (!id) | ||
225 | return -ENODEV; | ||
259 | 226 | ||
260 | /* Validate the SDRAM controller has ECC enabled */ | ||
261 | /* Grab the register range from the sdr controller in device tree */ | 227 | /* Grab the register range from the sdr controller in device tree */ |
262 | mc_vbase = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, | 228 | mc_vbase = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, |
263 | "altr,sdr-syscon"); | 229 | "altr,sdr-syscon"); |
@@ -267,8 +233,13 @@ static int altr_sdram_probe(struct platform_device *pdev) | |||
267 | return -ENODEV; | 233 | return -ENODEV; |
268 | } | 234 | } |
269 | 235 | ||
270 | if (regmap_read(mc_vbase, CTLCFG_OFST, &read_reg) || | 236 | /* Check specific dependencies for the module */ |
271 | ((read_reg & CTLCFG_ECC_AUTO_EN) != CTLCFG_ECC_AUTO_EN)) { | 237 | priv = of_match_node(altr_sdram_ctrl_of_match, |
238 | pdev->dev.of_node)->data; | ||
239 | |||
240 | /* Validate the SDRAM controller has ECC enabled */ | ||
241 | if (regmap_read(mc_vbase, priv->ecc_ctrl_offset, &read_reg) || | ||
242 | ((read_reg & priv->ecc_ctl_en_mask) != priv->ecc_ctl_en_mask)) { | ||
272 | edac_printk(KERN_ERR, EDAC_MC, | 243 | edac_printk(KERN_ERR, EDAC_MC, |
273 | "No ECC/ECC disabled [0x%08X]\n", read_reg); | 244 | "No ECC/ECC disabled [0x%08X]\n", read_reg); |
274 | return -ENODEV; | 245 | return -ENODEV; |
@@ -281,10 +252,27 @@ static int altr_sdram_probe(struct platform_device *pdev) | |||
281 | return -ENODEV; | 252 | return -ENODEV; |
282 | } | 253 | } |
283 | 254 | ||
284 | /* Ensure the SDRAM Interrupt is disabled and cleared */ | 255 | /* Ensure the SDRAM Interrupt is disabled */ |
285 | if (regmap_write(mc_vbase, DRAMINTR_OFST, DRAMINTR_INTRCLR)) { | 256 | if (regmap_update_bits(mc_vbase, priv->ecc_irq_en_offset, |
257 | priv->ecc_irq_en_mask, 0)) { | ||
258 | edac_printk(KERN_ERR, EDAC_MC, | ||
259 | "Error disabling SDRAM ECC IRQ\n"); | ||
260 | return -ENODEV; | ||
261 | } | ||
262 | |||
263 | /* Toggle to clear the SDRAM Error count */ | ||
264 | if (regmap_update_bits(mc_vbase, priv->ecc_cnt_rst_offset, | ||
265 | priv->ecc_cnt_rst_mask, | ||
266 | priv->ecc_cnt_rst_mask)) { | ||
267 | edac_printk(KERN_ERR, EDAC_MC, | ||
268 | "Error clearing SDRAM ECC count\n"); | ||
269 | return -ENODEV; | ||
270 | } | ||
271 | |||
272 | if (regmap_update_bits(mc_vbase, priv->ecc_cnt_rst_offset, | ||
273 | priv->ecc_cnt_rst_mask, 0)) { | ||
286 | edac_printk(KERN_ERR, EDAC_MC, | 274 | edac_printk(KERN_ERR, EDAC_MC, |
287 | "Error clearing SDRAM ECC IRQ\n"); | 275 | "Error clearing SDRAM ECC count\n"); |
288 | return -ENODEV; | 276 | return -ENODEV; |
289 | } | 277 | } |
290 | 278 | ||
@@ -309,9 +297,12 @@ static int altr_sdram_probe(struct platform_device *pdev) | |||
309 | mci->pdev = &pdev->dev; | 297 | mci->pdev = &pdev->dev; |
310 | drvdata = mci->pvt_info; | 298 | drvdata = mci->pvt_info; |
311 | drvdata->mc_vbase = mc_vbase; | 299 | drvdata->mc_vbase = mc_vbase; |
300 | drvdata->data = priv; | ||
312 | platform_set_drvdata(pdev, mci); | 301 | platform_set_drvdata(pdev, mci); |
313 | 302 | ||
314 | if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL)) { | 303 | if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL)) { |
304 | edac_printk(KERN_ERR, EDAC_MC, | ||
305 | "Unable to get managed device resource\n"); | ||
315 | res = -ENOMEM; | 306 | res = -ENOMEM; |
316 | goto free; | 307 | goto free; |
317 | } | 308 | } |
@@ -345,8 +336,9 @@ static int altr_sdram_probe(struct platform_device *pdev) | |||
345 | goto err2; | 336 | goto err2; |
346 | } | 337 | } |
347 | 338 | ||
348 | if (regmap_write(drvdata->mc_vbase, DRAMINTR_OFST, | 339 | /* Infrastructure ready - enable the IRQ */ |
349 | (DRAMINTR_INTRCLR | DRAMINTR_INTREN))) { | 340 | if (regmap_update_bits(drvdata->mc_vbase, priv->ecc_irq_en_offset, |
341 | priv->ecc_irq_en_mask, priv->ecc_irq_en_mask)) { | ||
350 | edac_mc_printk(mci, KERN_ERR, | 342 | edac_mc_printk(mci, KERN_ERR, |
351 | "Error enabling SDRAM ECC IRQ\n"); | 343 | "Error enabling SDRAM ECC IRQ\n"); |
352 | res = -ENODEV; | 344 | res = -ENODEV; |
@@ -382,12 +374,6 @@ static int altr_sdram_remove(struct platform_device *pdev) | |||
382 | return 0; | 374 | return 0; |
383 | } | 375 | } |
384 | 376 | ||
385 | static const struct of_device_id altr_sdram_ctrl_of_match[] = { | ||
386 | { .compatible = "altr,sdram-edac", }, | ||
387 | {}, | ||
388 | }; | ||
389 | MODULE_DEVICE_TABLE(of, altr_sdram_ctrl_of_match); | ||
390 | |||
391 | static struct platform_driver altr_sdram_edac_driver = { | 377 | static struct platform_driver altr_sdram_edac_driver = { |
392 | .probe = altr_sdram_probe, | 378 | .probe = altr_sdram_probe, |
393 | .remove = altr_sdram_remove, | 379 | .remove = altr_sdram_remove, |
diff --git a/drivers/edac/altera_edac.h b/drivers/edac/altera_edac.h new file mode 100644 index 000000000000..b744d914d976 --- /dev/null +++ b/drivers/edac/altera_edac.h | |||
@@ -0,0 +1,116 @@ | |||
1 | /* | ||
2 | * | ||
3 | * Copyright (C) 2015 Altera Corporation | ||
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 | |||
18 | #ifndef _ALTERA_EDAC_H | ||
19 | #define _ALTERA_EDAC_H | ||
20 | |||
21 | #include <linux/edac.h> | ||
22 | #include <linux/types.h> | ||
23 | |||
24 | /* SDRAM Controller CtrlCfg Register */ | ||
25 | #define CV_CTLCFG_OFST 0x00 | ||
26 | |||
27 | /* SDRAM Controller CtrlCfg Register Bit Masks */ | ||
28 | #define CV_CTLCFG_ECC_EN 0x400 | ||
29 | #define CV_CTLCFG_ECC_CORR_EN 0x800 | ||
30 | #define CV_CTLCFG_GEN_SB_ERR 0x2000 | ||
31 | #define CV_CTLCFG_GEN_DB_ERR 0x4000 | ||
32 | |||
33 | #define CV_CTLCFG_ECC_AUTO_EN (CV_CTLCFG_ECC_EN | \ | ||
34 | CV_CTLCFG_ECC_CORR_EN) | ||
35 | |||
36 | /* SDRAM Controller Address Width Register */ | ||
37 | #define CV_DRAMADDRW_OFST 0x2C | ||
38 | |||
39 | /* SDRAM Controller Address Widths Field Register */ | ||
40 | #define DRAMADDRW_COLBIT_MASK 0x001F | ||
41 | #define DRAMADDRW_COLBIT_SHIFT 0 | ||
42 | #define DRAMADDRW_ROWBIT_MASK 0x03E0 | ||
43 | #define DRAMADDRW_ROWBIT_SHIFT 5 | ||
44 | #define CV_DRAMADDRW_BANKBIT_MASK 0x1C00 | ||
45 | #define CV_DRAMADDRW_BANKBIT_SHIFT 10 | ||
46 | #define CV_DRAMADDRW_CSBIT_MASK 0xE000 | ||
47 | #define CV_DRAMADDRW_CSBIT_SHIFT 13 | ||
48 | |||
49 | /* SDRAM Controller Interface Data Width Register */ | ||
50 | #define CV_DRAMIFWIDTH_OFST 0x30 | ||
51 | |||
52 | /* SDRAM Controller Interface Data Width Defines */ | ||
53 | #define CV_DRAMIFWIDTH_16B_ECC 24 | ||
54 | #define CV_DRAMIFWIDTH_32B_ECC 40 | ||
55 | |||
56 | /* SDRAM Controller DRAM Status Register */ | ||
57 | #define CV_DRAMSTS_OFST 0x38 | ||
58 | |||
59 | /* SDRAM Controller DRAM Status Register Bit Masks */ | ||
60 | #define CV_DRAMSTS_SBEERR 0x04 | ||
61 | #define CV_DRAMSTS_DBEERR 0x08 | ||
62 | #define CV_DRAMSTS_CORR_DROP 0x10 | ||
63 | |||
64 | /* SDRAM Controller DRAM IRQ Register */ | ||
65 | #define CV_DRAMINTR_OFST 0x3C | ||
66 | |||
67 | /* SDRAM Controller DRAM IRQ Register Bit Masks */ | ||
68 | #define CV_DRAMINTR_INTREN 0x01 | ||
69 | #define CV_DRAMINTR_SBEMASK 0x02 | ||
70 | #define CV_DRAMINTR_DBEMASK 0x04 | ||
71 | #define CV_DRAMINTR_CORRDROPMASK 0x08 | ||
72 | #define CV_DRAMINTR_INTRCLR 0x10 | ||
73 | |||
74 | /* SDRAM Controller Single Bit Error Count Register */ | ||
75 | #define CV_SBECOUNT_OFST 0x40 | ||
76 | |||
77 | /* SDRAM Controller Double Bit Error Count Register */ | ||
78 | #define CV_DBECOUNT_OFST 0x44 | ||
79 | |||
80 | /* SDRAM Controller ECC Error Address Register */ | ||
81 | #define CV_ERRADDR_OFST 0x48 | ||
82 | |||
83 | struct altr_sdram_prv_data { | ||
84 | int ecc_ctrl_offset; | ||
85 | int ecc_ctl_en_mask; | ||
86 | int ecc_cecnt_offset; | ||
87 | int ecc_uecnt_offset; | ||
88 | int ecc_stat_offset; | ||
89 | int ecc_stat_ce_mask; | ||
90 | int ecc_stat_ue_mask; | ||
91 | int ecc_saddr_offset; | ||
92 | int ecc_daddr_offset; | ||
93 | int ecc_irq_en_offset; | ||
94 | int ecc_irq_en_mask; | ||
95 | int ecc_irq_clr_offset; | ||
96 | int ecc_irq_clr_mask; | ||
97 | int ecc_cnt_rst_offset; | ||
98 | int ecc_cnt_rst_mask; | ||
99 | #ifdef CONFIG_EDAC_DEBUG | ||
100 | struct edac_dev_sysfs_attribute *eccmgr_sysfs_attr; | ||
101 | int ecc_enable_mask; | ||
102 | int ce_set_mask; | ||
103 | int ue_set_mask; | ||
104 | int ce_ue_trgr_offset; | ||
105 | #endif | ||
106 | }; | ||
107 | |||
108 | /* Altera SDRAM Memory Controller data */ | ||
109 | struct altr_sdram_mc_data { | ||
110 | struct regmap *mc_vbase; | ||
111 | int sb_irq; | ||
112 | int db_irq; | ||
113 | const struct altr_sdram_prv_data *data; | ||
114 | }; | ||
115 | |||
116 | #endif /* #ifndef _ALTERA_EDAC_H */ | ||