blob: f5283f5c07cbbeea84842549ab35f1098331f1ae [file] [log] [blame]
Dave Jianga9a753d2008-02-07 00:14:55 -08001/*
Alexander Kuleshov775c5032014-12-28 12:44:45 +06002 * Freescale MPC85xx Memory Controller kernel module
Dave Jianga9a753d2008-02-07 00:14:55 -08003 *
Chunhe Lanc92132f2013-11-25 11:28:41 +01004 * Parts Copyrighted (c) 2013 by Freescale Semiconductor, Inc.
5 *
Dave Jianga9a753d2008-02-07 00:14:55 -08006 * Author: Dave Jiang <djiang@mvista.com>
7 *
8 * 2006-2007 (c) MontaVista Software, Inc. This file is licensed under
9 * the terms of the GNU General Public License version 2. This program
10 * is licensed "as is" without any warranty of any kind, whether express
11 * or implied.
12 *
13 */
14#include <linux/module.h>
15#include <linux/init.h>
Dave Jianga9a753d2008-02-07 00:14:55 -080016#include <linux/interrupt.h>
17#include <linux/ctype.h>
18#include <linux/io.h>
19#include <linux/mod_devicetable.h>
20#include <linux/edac.h>
Andrew Kilkenny60be7552008-10-15 22:04:28 -070021#include <linux/smp.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090022#include <linux/gfp.h>
Scott Wood666db562015-12-10 13:07:12 -060023#include <linux/fsl/edac.h>
Dave Jianga9a753d2008-02-07 00:14:55 -080024
25#include <linux/of_platform.h>
26#include <linux/of_device.h>
Dave Jianga9a753d2008-02-07 00:14:55 -080027#include "edac_module.h"
28#include "edac_core.h"
29#include "mpc85xx_edac.h"
30
31static int edac_dev_idx;
Ira W. Snyder0616fb02009-10-26 16:50:10 -070032#ifdef CONFIG_PCI
Dave Jianga9a753d2008-02-07 00:14:55 -080033static int edac_pci_idx;
Ira W. Snyder0616fb02009-10-26 16:50:10 -070034#endif
Dave Jianga9a753d2008-02-07 00:14:55 -080035static int edac_mc_idx;
36
37static u32 orig_ddr_err_disable;
38static u32 orig_ddr_err_sbe;
39
40/*
41 * PCI Err defines
42 */
43#ifdef CONFIG_PCI
44static u32 orig_pci_err_cap_dr;
45static u32 orig_pci_err_en;
46#endif
47
48static u32 orig_l2_err_disable;
Christoph Eggerbd1688d2010-08-10 18:03:18 -070049#ifdef CONFIG_FSL_SOC_BOOKE
Andrew Kilkenny60be7552008-10-15 22:04:28 -070050static u32 orig_hid1[2];
Ira W. Snyderb4846252009-09-23 15:57:25 -070051#endif
Dave Jianga9a753d2008-02-07 00:14:55 -080052
Dave Jianga9a753d2008-02-07 00:14:55 -080053/************************ MC SYSFS parts ***********************************/
54
Mauro Carvalho Chehabba004232012-03-21 15:16:20 -030055#define to_mci(k) container_of(k, struct mem_ctl_info, dev)
56
57static ssize_t mpc85xx_mc_inject_data_hi_show(struct device *dev,
58 struct device_attribute *mattr,
Dave Jianga9a753d2008-02-07 00:14:55 -080059 char *data)
60{
Mauro Carvalho Chehabba004232012-03-21 15:16:20 -030061 struct mem_ctl_info *mci = to_mci(dev);
Dave Jianga9a753d2008-02-07 00:14:55 -080062 struct mpc85xx_mc_pdata *pdata = mci->pvt_info;
63 return sprintf(data, "0x%08x",
64 in_be32(pdata->mc_vbase +
65 MPC85XX_MC_DATA_ERR_INJECT_HI));
66}
67
Mauro Carvalho Chehabba004232012-03-21 15:16:20 -030068static ssize_t mpc85xx_mc_inject_data_lo_show(struct device *dev,
69 struct device_attribute *mattr,
Dave Jianga9a753d2008-02-07 00:14:55 -080070 char *data)
71{
Mauro Carvalho Chehabba004232012-03-21 15:16:20 -030072 struct mem_ctl_info *mci = to_mci(dev);
Dave Jianga9a753d2008-02-07 00:14:55 -080073 struct mpc85xx_mc_pdata *pdata = mci->pvt_info;
74 return sprintf(data, "0x%08x",
75 in_be32(pdata->mc_vbase +
76 MPC85XX_MC_DATA_ERR_INJECT_LO));
77}
78
Mauro Carvalho Chehabba004232012-03-21 15:16:20 -030079static ssize_t mpc85xx_mc_inject_ctrl_show(struct device *dev,
80 struct device_attribute *mattr,
81 char *data)
Dave Jianga9a753d2008-02-07 00:14:55 -080082{
Mauro Carvalho Chehabba004232012-03-21 15:16:20 -030083 struct mem_ctl_info *mci = to_mci(dev);
Dave Jianga9a753d2008-02-07 00:14:55 -080084 struct mpc85xx_mc_pdata *pdata = mci->pvt_info;
85 return sprintf(data, "0x%08x",
86 in_be32(pdata->mc_vbase + MPC85XX_MC_ECC_ERR_INJECT));
87}
88
Mauro Carvalho Chehabba004232012-03-21 15:16:20 -030089static ssize_t mpc85xx_mc_inject_data_hi_store(struct device *dev,
90 struct device_attribute *mattr,
Dave Jianga9a753d2008-02-07 00:14:55 -080091 const char *data, size_t count)
92{
Mauro Carvalho Chehabba004232012-03-21 15:16:20 -030093 struct mem_ctl_info *mci = to_mci(dev);
Dave Jianga9a753d2008-02-07 00:14:55 -080094 struct mpc85xx_mc_pdata *pdata = mci->pvt_info;
95 if (isdigit(*data)) {
96 out_be32(pdata->mc_vbase + MPC85XX_MC_DATA_ERR_INJECT_HI,
97 simple_strtoul(data, NULL, 0));
98 return count;
99 }
100 return 0;
101}
102
Mauro Carvalho Chehabba004232012-03-21 15:16:20 -0300103static ssize_t mpc85xx_mc_inject_data_lo_store(struct device *dev,
104 struct device_attribute *mattr,
Dave Jianga9a753d2008-02-07 00:14:55 -0800105 const char *data, size_t count)
106{
Mauro Carvalho Chehabba004232012-03-21 15:16:20 -0300107 struct mem_ctl_info *mci = to_mci(dev);
Dave Jianga9a753d2008-02-07 00:14:55 -0800108 struct mpc85xx_mc_pdata *pdata = mci->pvt_info;
109 if (isdigit(*data)) {
110 out_be32(pdata->mc_vbase + MPC85XX_MC_DATA_ERR_INJECT_LO,
111 simple_strtoul(data, NULL, 0));
112 return count;
113 }
114 return 0;
115}
116
Mauro Carvalho Chehabba004232012-03-21 15:16:20 -0300117static ssize_t mpc85xx_mc_inject_ctrl_store(struct device *dev,
118 struct device_attribute *mattr,
119 const char *data, size_t count)
Dave Jianga9a753d2008-02-07 00:14:55 -0800120{
Mauro Carvalho Chehabba004232012-03-21 15:16:20 -0300121 struct mem_ctl_info *mci = to_mci(dev);
Dave Jianga9a753d2008-02-07 00:14:55 -0800122 struct mpc85xx_mc_pdata *pdata = mci->pvt_info;
123 if (isdigit(*data)) {
124 out_be32(pdata->mc_vbase + MPC85XX_MC_ECC_ERR_INJECT,
125 simple_strtoul(data, NULL, 0));
126 return count;
127 }
128 return 0;
129}
130
Mauro Carvalho Chehabba004232012-03-21 15:16:20 -0300131DEVICE_ATTR(inject_data_hi, S_IRUGO | S_IWUSR,
132 mpc85xx_mc_inject_data_hi_show, mpc85xx_mc_inject_data_hi_store);
133DEVICE_ATTR(inject_data_lo, S_IRUGO | S_IWUSR,
134 mpc85xx_mc_inject_data_lo_show, mpc85xx_mc_inject_data_lo_store);
135DEVICE_ATTR(inject_ctrl, S_IRUGO | S_IWUSR,
136 mpc85xx_mc_inject_ctrl_show, mpc85xx_mc_inject_ctrl_store);
Dave Jianga9a753d2008-02-07 00:14:55 -0800137
Takashi Iwai917c85b2015-02-04 11:48:56 +0100138static struct attribute *mpc85xx_dev_attrs[] = {
139 &dev_attr_inject_data_hi.attr,
140 &dev_attr_inject_data_lo.attr,
141 &dev_attr_inject_ctrl.attr,
142 NULL
143};
Mauro Carvalho Chehabba004232012-03-21 15:16:20 -0300144
Takashi Iwai917c85b2015-02-04 11:48:56 +0100145ATTRIBUTE_GROUPS(mpc85xx_dev);
Dave Jianga9a753d2008-02-07 00:14:55 -0800146
147/**************************** PCI Err device ***************************/
148#ifdef CONFIG_PCI
149
150static void mpc85xx_pci_check(struct edac_pci_ctl_info *pci)
151{
152 struct mpc85xx_pci_pdata *pdata = pci->pvt_info;
153 u32 err_detect;
154
155 err_detect = in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR);
156
157 /* master aborts can happen during PCI config cycles */
158 if (!(err_detect & ~(PCI_EDE_MULTI_ERR | PCI_EDE_MST_ABRT))) {
159 out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, err_detect);
160 return;
161 }
162
163 printk(KERN_ERR "PCI error(s) detected\n");
164 printk(KERN_ERR "PCI/X ERR_DR register: %#08x\n", err_detect);
165
166 printk(KERN_ERR "PCI/X ERR_ATTRIB register: %#08x\n",
167 in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ATTRIB));
168 printk(KERN_ERR "PCI/X ERR_ADDR register: %#08x\n",
169 in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR));
170 printk(KERN_ERR "PCI/X ERR_EXT_ADDR register: %#08x\n",
171 in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EXT_ADDR));
172 printk(KERN_ERR "PCI/X ERR_DL register: %#08x\n",
173 in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DL));
174 printk(KERN_ERR "PCI/X ERR_DH register: %#08x\n",
175 in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DH));
176
177 /* clear error bits */
178 out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, err_detect);
179
180 if (err_detect & PCI_EDE_PERR_MASK)
181 edac_pci_handle_pe(pci, pci->ctl_name);
182
183 if ((err_detect & ~PCI_EDE_MULTI_ERR) & ~PCI_EDE_PERR_MASK)
184 edac_pci_handle_npe(pci, pci->ctl_name);
185}
186
Chunhe Lanc92132f2013-11-25 11:28:41 +0100187static void mpc85xx_pcie_check(struct edac_pci_ctl_info *pci)
188{
189 struct mpc85xx_pci_pdata *pdata = pci->pvt_info;
Tillmann Heidsieck6fa06b0d2016-08-15 21:08:49 +0200190 u32 err_detect, err_cap_stat;
Chunhe Lanc92132f2013-11-25 11:28:41 +0100191
192 err_detect = in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR);
Tillmann Heidsieck6fa06b0d2016-08-15 21:08:49 +0200193 err_cap_stat = in_be32(pdata->pci_vbase + MPC85XX_PCI_GAS_TIMR);
Chunhe Lanc92132f2013-11-25 11:28:41 +0100194
195 pr_err("PCIe error(s) detected\n");
196 pr_err("PCIe ERR_DR register: 0x%08x\n", err_detect);
Tillmann Heidsieck6fa06b0d2016-08-15 21:08:49 +0200197 pr_err("PCIe ERR_CAP_STAT register: 0x%08x\n", err_cap_stat);
Chunhe Lanc92132f2013-11-25 11:28:41 +0100198 pr_err("PCIe ERR_CAP_R0 register: 0x%08x\n",
199 in_be32(pdata->pci_vbase + MPC85XX_PCIE_ERR_CAP_R0));
200 pr_err("PCIe ERR_CAP_R1 register: 0x%08x\n",
201 in_be32(pdata->pci_vbase + MPC85XX_PCIE_ERR_CAP_R1));
202 pr_err("PCIe ERR_CAP_R2 register: 0x%08x\n",
203 in_be32(pdata->pci_vbase + MPC85XX_PCIE_ERR_CAP_R2));
204 pr_err("PCIe ERR_CAP_R3 register: 0x%08x\n",
205 in_be32(pdata->pci_vbase + MPC85XX_PCIE_ERR_CAP_R3));
206
207 /* clear error bits */
208 out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, err_detect);
Tillmann Heidsieck6fa06b0d2016-08-15 21:08:49 +0200209
210 /* reset error capture */
211 out_be32(pdata->pci_vbase + MPC85XX_PCI_GAS_TIMR, err_cap_stat | 0x1);
Chunhe Lanc92132f2013-11-25 11:28:41 +0100212}
213
214static int mpc85xx_pcie_find_capability(struct device_node *np)
215{
216 struct pci_controller *hose;
217
218 if (!np)
219 return -EINVAL;
220
221 hose = pci_find_hose_for_OF_device(np);
222
223 return early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP);
224}
225
Dave Jianga9a753d2008-02-07 00:14:55 -0800226static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id)
227{
228 struct edac_pci_ctl_info *pci = dev_id;
229 struct mpc85xx_pci_pdata *pdata = pci->pvt_info;
230 u32 err_detect;
231
232 err_detect = in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR);
233
234 if (!err_detect)
235 return IRQ_NONE;
236
Chunhe Lanc92132f2013-11-25 11:28:41 +0100237 if (pdata->is_pcie)
238 mpc85xx_pcie_check(pci);
239 else
240 mpc85xx_pci_check(pci);
Dave Jianga9a753d2008-02-07 00:14:55 -0800241
242 return IRQ_HANDLED;
243}
244
Scott Wood666db562015-12-10 13:07:12 -0600245static int mpc85xx_pci_err_probe(struct platform_device *op)
Dave Jianga9a753d2008-02-07 00:14:55 -0800246{
247 struct edac_pci_ctl_info *pci;
248 struct mpc85xx_pci_pdata *pdata;
Scott Wood666db562015-12-10 13:07:12 -0600249 struct mpc85xx_edac_pci_plat_data *plat_data;
250 struct device_node *of_node;
Dave Jiangf87bd332008-07-25 01:49:14 -0700251 struct resource r;
Dave Jianga9a753d2008-02-07 00:14:55 -0800252 int res = 0;
253
Dave Jiangf87bd332008-07-25 01:49:14 -0700254 if (!devres_open_group(&op->dev, mpc85xx_pci_err_probe, GFP_KERNEL))
Dave Jianga9a753d2008-02-07 00:14:55 -0800255 return -ENOMEM;
256
257 pci = edac_pci_alloc_ctl_info(sizeof(*pdata), "mpc85xx_pci_err");
258 if (!pci)
259 return -ENOMEM;
260
Jia Hongtao905e75c2012-08-28 15:44:08 +0800261 /* make sure error reporting method is sane */
262 switch (edac_op_state) {
263 case EDAC_OPSTATE_POLL:
264 case EDAC_OPSTATE_INT:
265 break;
266 default:
267 edac_op_state = EDAC_OPSTATE_INT;
268 break;
269 }
270
Dave Jianga9a753d2008-02-07 00:14:55 -0800271 pdata = pci->pvt_info;
272 pdata->name = "mpc85xx_pci_err";
273 pdata->irq = NO_IRQ;
Chunhe Lanc92132f2013-11-25 11:28:41 +0100274
Scott Wood666db562015-12-10 13:07:12 -0600275 plat_data = op->dev.platform_data;
276 if (!plat_data) {
277 dev_err(&op->dev, "no platform data");
278 res = -ENXIO;
279 goto err;
280 }
281 of_node = plat_data->of_node;
282
283 if (mpc85xx_pcie_find_capability(of_node) > 0)
Chunhe Lanc92132f2013-11-25 11:28:41 +0100284 pdata->is_pcie = true;
285
Dave Jiangf87bd332008-07-25 01:49:14 -0700286 dev_set_drvdata(&op->dev, pci);
287 pci->dev = &op->dev;
Dave Jianga9a753d2008-02-07 00:14:55 -0800288 pci->mod_name = EDAC_MOD_STR;
289 pci->ctl_name = pdata->name;
Kay Sievers031d5512009-03-24 16:38:21 -0700290 pci->dev_name = dev_name(&op->dev);
Dave Jianga9a753d2008-02-07 00:14:55 -0800291
Chunhe Lanc92132f2013-11-25 11:28:41 +0100292 if (edac_op_state == EDAC_OPSTATE_POLL) {
293 if (pdata->is_pcie)
294 pci->edac_check = mpc85xx_pcie_check;
295 else
296 pci->edac_check = mpc85xx_pci_check;
297 }
Dave Jianga9a753d2008-02-07 00:14:55 -0800298
299 pdata->edac_idx = edac_pci_idx++;
300
Scott Wood666db562015-12-10 13:07:12 -0600301 res = of_address_to_resource(of_node, 0, &r);
Dave Jiangf87bd332008-07-25 01:49:14 -0700302 if (res) {
Dave Jianga9a753d2008-02-07 00:14:55 -0800303 printk(KERN_ERR "%s: Unable to get resource for "
304 "PCI err regs\n", __func__);
305 goto err;
306 }
307
Dave Jiangf87bd332008-07-25 01:49:14 -0700308 /* we only need the error registers */
309 r.start += 0xe00;
310
H Hartley Sweeten66ed3f72010-03-10 15:23:13 -0800311 if (!devm_request_mem_region(&op->dev, r.start, resource_size(&r),
312 pdata->name)) {
Dave Jianga9a753d2008-02-07 00:14:55 -0800313 printk(KERN_ERR "%s: Error while requesting mem region\n",
314 __func__);
315 res = -EBUSY;
316 goto err;
317 }
318
H Hartley Sweeten66ed3f72010-03-10 15:23:13 -0800319 pdata->pci_vbase = devm_ioremap(&op->dev, r.start, resource_size(&r));
Dave Jianga9a753d2008-02-07 00:14:55 -0800320 if (!pdata->pci_vbase) {
321 printk(KERN_ERR "%s: Unable to setup PCI err regs\n", __func__);
322 res = -ENOMEM;
323 goto err;
324 }
325
Chunhe Lanc92132f2013-11-25 11:28:41 +0100326 if (pdata->is_pcie) {
327 orig_pci_err_cap_dr =
328 in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR);
329 out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR, ~0);
330 orig_pci_err_en =
331 in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN);
332 out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, 0);
333 } else {
334 orig_pci_err_cap_dr =
335 in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR);
Dave Jianga9a753d2008-02-07 00:14:55 -0800336
Chunhe Lanc92132f2013-11-25 11:28:41 +0100337 /* PCI master abort is expected during config cycles */
338 out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR, 0x40);
Dave Jianga9a753d2008-02-07 00:14:55 -0800339
Chunhe Lanc92132f2013-11-25 11:28:41 +0100340 orig_pci_err_en =
341 in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN);
Dave Jianga9a753d2008-02-07 00:14:55 -0800342
Chunhe Lanc92132f2013-11-25 11:28:41 +0100343 /* disable master abort reporting */
344 out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, ~0x40);
345 }
Dave Jianga9a753d2008-02-07 00:14:55 -0800346
347 /* clear error bits */
348 out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, ~0);
349
Tillmann Heidsieck6fa06b0d2016-08-15 21:08:49 +0200350 /* reset error capture */
351 out_be32(pdata->pci_vbase + MPC85XX_PCI_GAS_TIMR, 0x1);
352
Dave Jianga9a753d2008-02-07 00:14:55 -0800353 if (edac_pci_add_device(pci, pdata->edac_idx) > 0) {
Joe Perches956b9ba2012-04-29 17:08:39 -0300354 edac_dbg(3, "failed edac_pci_add_device()\n");
Dave Jianga9a753d2008-02-07 00:14:55 -0800355 goto err;
356 }
357
358 if (edac_op_state == EDAC_OPSTATE_INT) {
Scott Wood666db562015-12-10 13:07:12 -0600359 pdata->irq = irq_of_parse_and_map(of_node, 0);
Dave Jiangf87bd332008-07-25 01:49:14 -0700360 res = devm_request_irq(&op->dev, pdata->irq,
Chunhe Lanc92132f2013-11-25 11:28:41 +0100361 mpc85xx_pci_isr,
Johannes Thumshirne245e3b2014-01-21 09:42:27 +0100362 IRQF_SHARED,
Dave Jianga9a753d2008-02-07 00:14:55 -0800363 "[EDAC] PCI err", pci);
364 if (res < 0) {
365 printk(KERN_ERR
Baruch Siache7d2c212013-02-10 11:39:52 +0200366 "%s: Unable to request irq %d for "
Dave Jianga9a753d2008-02-07 00:14:55 -0800367 "MPC85xx PCI err\n", __func__, pdata->irq);
Dave Jiangf87bd332008-07-25 01:49:14 -0700368 irq_dispose_mapping(pdata->irq);
Dave Jianga9a753d2008-02-07 00:14:55 -0800369 res = -ENODEV;
370 goto err2;
371 }
372
373 printk(KERN_INFO EDAC_MOD_STR " acquired irq %d for PCI Err\n",
374 pdata->irq);
375 }
376
Chunhe Lanc92132f2013-11-25 11:28:41 +0100377 if (pdata->is_pcie) {
378 /*
379 * Enable all PCIe error interrupt & error detect except invalid
380 * PEX_CONFIG_ADDR/PEX_CONFIG_DATA access interrupt generation
381 * enable bit and invalid PEX_CONFIG_ADDR/PEX_CONFIG_DATA access
382 * detection enable bit. Because PCIe bus code to initialize and
383 * configure these PCIe devices on booting will use some invalid
384 * PEX_CONFIG_ADDR/PEX_CONFIG_DATA, edac driver prints the much
385 * notice information. So disable this detect to fix ugly print.
386 */
387 out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, ~0
388 & ~PEX_ERR_ICCAIE_EN_BIT);
389 out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR, 0
390 | PEX_ERR_ICCAD_DISR_BIT);
391 }
392
Dave Jiangf87bd332008-07-25 01:49:14 -0700393 devres_remove_group(&op->dev, mpc85xx_pci_err_probe);
Joe Perches956b9ba2012-04-29 17:08:39 -0300394 edac_dbg(3, "success\n");
Dave Jianga9a753d2008-02-07 00:14:55 -0800395 printk(KERN_INFO EDAC_MOD_STR " PCI err registered\n");
396
397 return 0;
398
399err2:
Dave Jiangf87bd332008-07-25 01:49:14 -0700400 edac_pci_del_device(&op->dev);
Dave Jianga9a753d2008-02-07 00:14:55 -0800401err:
402 edac_pci_free_ctl_info(pci);
Dave Jiangf87bd332008-07-25 01:49:14 -0700403 devres_release_group(&op->dev, mpc85xx_pci_err_probe);
Dave Jianga9a753d2008-02-07 00:14:55 -0800404 return res;
405}
406
Scott Wood666db562015-12-10 13:07:12 -0600407static const struct platform_device_id mpc85xx_pci_err_match[] = {
408 {
409 .name = "mpc85xx-pci-edac"
410 },
411 {}
412};
413
414static struct platform_driver mpc85xx_pci_err_driver = {
415 .probe = mpc85xx_pci_err_probe,
416 .id_table = mpc85xx_pci_err_match,
417 .driver = {
418 .name = "mpc85xx_pci_err",
419 .suppress_bind_attrs = true,
420 },
421};
Dave Jianga9a753d2008-02-07 00:14:55 -0800422#endif /* CONFIG_PCI */
423
424/**************************** L2 Err device ***************************/
425
426/************************ L2 SYSFS parts ***********************************/
427
428static ssize_t mpc85xx_l2_inject_data_hi_show(struct edac_device_ctl_info
429 *edac_dev, char *data)
430{
431 struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info;
432 return sprintf(data, "0x%08x",
433 in_be32(pdata->l2_vbase + MPC85XX_L2_ERRINJHI));
434}
435
436static ssize_t mpc85xx_l2_inject_data_lo_show(struct edac_device_ctl_info
437 *edac_dev, char *data)
438{
439 struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info;
440 return sprintf(data, "0x%08x",
441 in_be32(pdata->l2_vbase + MPC85XX_L2_ERRINJLO));
442}
443
444static ssize_t mpc85xx_l2_inject_ctrl_show(struct edac_device_ctl_info
445 *edac_dev, char *data)
446{
447 struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info;
448 return sprintf(data, "0x%08x",
449 in_be32(pdata->l2_vbase + MPC85XX_L2_ERRINJCTL));
450}
451
452static ssize_t mpc85xx_l2_inject_data_hi_store(struct edac_device_ctl_info
453 *edac_dev, const char *data,
454 size_t count)
455{
456 struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info;
457 if (isdigit(*data)) {
458 out_be32(pdata->l2_vbase + MPC85XX_L2_ERRINJHI,
459 simple_strtoul(data, NULL, 0));
460 return count;
461 }
462 return 0;
463}
464
465static ssize_t mpc85xx_l2_inject_data_lo_store(struct edac_device_ctl_info
466 *edac_dev, const char *data,
467 size_t count)
468{
469 struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info;
470 if (isdigit(*data)) {
471 out_be32(pdata->l2_vbase + MPC85XX_L2_ERRINJLO,
472 simple_strtoul(data, NULL, 0));
473 return count;
474 }
475 return 0;
476}
477
478static ssize_t mpc85xx_l2_inject_ctrl_store(struct edac_device_ctl_info
479 *edac_dev, const char *data,
480 size_t count)
481{
482 struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info;
483 if (isdigit(*data)) {
484 out_be32(pdata->l2_vbase + MPC85XX_L2_ERRINJCTL,
485 simple_strtoul(data, NULL, 0));
486 return count;
487 }
488 return 0;
489}
490
491static struct edac_dev_sysfs_attribute mpc85xx_l2_sysfs_attributes[] = {
492 {
493 .attr = {
494 .name = "inject_data_hi",
495 .mode = (S_IRUGO | S_IWUSR)
496 },
497 .show = mpc85xx_l2_inject_data_hi_show,
498 .store = mpc85xx_l2_inject_data_hi_store},
499 {
500 .attr = {
501 .name = "inject_data_lo",
502 .mode = (S_IRUGO | S_IWUSR)
503 },
504 .show = mpc85xx_l2_inject_data_lo_show,
505 .store = mpc85xx_l2_inject_data_lo_store},
506 {
507 .attr = {
508 .name = "inject_ctrl",
509 .mode = (S_IRUGO | S_IWUSR)
510 },
511 .show = mpc85xx_l2_inject_ctrl_show,
512 .store = mpc85xx_l2_inject_ctrl_store},
513
514 /* End of list */
515 {
516 .attr = {.name = NULL}
517 }
518};
519
520static void mpc85xx_set_l2_sysfs_attributes(struct edac_device_ctl_info
521 *edac_dev)
522{
523 edac_dev->sysfs_attributes = mpc85xx_l2_sysfs_attributes;
524}
525
526/***************************** L2 ops ***********************************/
527
528static void mpc85xx_l2_check(struct edac_device_ctl_info *edac_dev)
529{
530 struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info;
531 u32 err_detect;
532
533 err_detect = in_be32(pdata->l2_vbase + MPC85XX_L2_ERRDET);
534
535 if (!(err_detect & L2_EDE_MASK))
536 return;
537
538 printk(KERN_ERR "ECC Error in CPU L2 cache\n");
539 printk(KERN_ERR "L2 Error Detect Register: 0x%08x\n", err_detect);
540 printk(KERN_ERR "L2 Error Capture Data High Register: 0x%08x\n",
541 in_be32(pdata->l2_vbase + MPC85XX_L2_CAPTDATAHI));
542 printk(KERN_ERR "L2 Error Capture Data Lo Register: 0x%08x\n",
543 in_be32(pdata->l2_vbase + MPC85XX_L2_CAPTDATALO));
544 printk(KERN_ERR "L2 Error Syndrome Register: 0x%08x\n",
545 in_be32(pdata->l2_vbase + MPC85XX_L2_CAPTECC));
546 printk(KERN_ERR "L2 Error Attributes Capture Register: 0x%08x\n",
547 in_be32(pdata->l2_vbase + MPC85XX_L2_ERRATTR));
548 printk(KERN_ERR "L2 Error Address Capture Register: 0x%08x\n",
549 in_be32(pdata->l2_vbase + MPC85XX_L2_ERRADDR));
550
551 /* clear error detect register */
552 out_be32(pdata->l2_vbase + MPC85XX_L2_ERRDET, err_detect);
553
554 if (err_detect & L2_EDE_CE_MASK)
555 edac_device_handle_ce(edac_dev, 0, 0, edac_dev->ctl_name);
556
557 if (err_detect & L2_EDE_UE_MASK)
558 edac_device_handle_ue(edac_dev, 0, 0, edac_dev->ctl_name);
559}
560
561static irqreturn_t mpc85xx_l2_isr(int irq, void *dev_id)
562{
563 struct edac_device_ctl_info *edac_dev = dev_id;
564 struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info;
565 u32 err_detect;
566
567 err_detect = in_be32(pdata->l2_vbase + MPC85XX_L2_ERRDET);
568
569 if (!(err_detect & L2_EDE_MASK))
570 return IRQ_NONE;
571
572 mpc85xx_l2_check(edac_dev);
573
574 return IRQ_HANDLED;
575}
576
Greg Kroah-Hartman9b3c6e82012-12-21 13:23:51 -0800577static int mpc85xx_l2_err_probe(struct platform_device *op)
Dave Jianga9a753d2008-02-07 00:14:55 -0800578{
579 struct edac_device_ctl_info *edac_dev;
580 struct mpc85xx_l2_pdata *pdata;
581 struct resource r;
582 int res;
583
584 if (!devres_open_group(&op->dev, mpc85xx_l2_err_probe, GFP_KERNEL))
585 return -ENOMEM;
586
587 edac_dev = edac_device_alloc_ctl_info(sizeof(*pdata),
588 "cpu", 1, "L", 1, 2, NULL, 0,
589 edac_dev_idx);
590 if (!edac_dev) {
591 devres_release_group(&op->dev, mpc85xx_l2_err_probe);
592 return -ENOMEM;
593 }
594
595 pdata = edac_dev->pvt_info;
596 pdata->name = "mpc85xx_l2_err";
597 pdata->irq = NO_IRQ;
598 edac_dev->dev = &op->dev;
599 dev_set_drvdata(edac_dev->dev, edac_dev);
600 edac_dev->ctl_name = pdata->name;
601 edac_dev->dev_name = pdata->name;
602
Anatolij Gustschina26f95f2010-06-03 03:17:42 +0200603 res = of_address_to_resource(op->dev.of_node, 0, &r);
Dave Jianga9a753d2008-02-07 00:14:55 -0800604 if (res) {
605 printk(KERN_ERR "%s: Unable to get resource for "
606 "L2 err regs\n", __func__);
607 goto err;
608 }
609
610 /* we only need the error registers */
611 r.start += 0xe00;
612
Joe Perches28f65c112011-06-09 09:13:32 -0700613 if (!devm_request_mem_region(&op->dev, r.start, resource_size(&r),
614 pdata->name)) {
Dave Jianga9a753d2008-02-07 00:14:55 -0800615 printk(KERN_ERR "%s: Error while requesting mem region\n",
616 __func__);
617 res = -EBUSY;
618 goto err;
619 }
620
Joe Perches28f65c112011-06-09 09:13:32 -0700621 pdata->l2_vbase = devm_ioremap(&op->dev, r.start, resource_size(&r));
Dave Jianga9a753d2008-02-07 00:14:55 -0800622 if (!pdata->l2_vbase) {
623 printk(KERN_ERR "%s: Unable to setup L2 err regs\n", __func__);
624 res = -ENOMEM;
625 goto err;
626 }
627
628 out_be32(pdata->l2_vbase + MPC85XX_L2_ERRDET, ~0);
629
630 orig_l2_err_disable = in_be32(pdata->l2_vbase + MPC85XX_L2_ERRDIS);
631
632 /* clear the err_dis */
633 out_be32(pdata->l2_vbase + MPC85XX_L2_ERRDIS, 0);
634
635 edac_dev->mod_name = EDAC_MOD_STR;
636
637 if (edac_op_state == EDAC_OPSTATE_POLL)
638 edac_dev->edac_check = mpc85xx_l2_check;
639
640 mpc85xx_set_l2_sysfs_attributes(edac_dev);
641
642 pdata->edac_idx = edac_dev_idx++;
643
644 if (edac_device_add_device(edac_dev) > 0) {
Joe Perches956b9ba2012-04-29 17:08:39 -0300645 edac_dbg(3, "failed edac_device_add_device()\n");
Dave Jianga9a753d2008-02-07 00:14:55 -0800646 goto err;
647 }
648
649 if (edac_op_state == EDAC_OPSTATE_INT) {
Anatolij Gustschina26f95f2010-06-03 03:17:42 +0200650 pdata->irq = irq_of_parse_and_map(op->dev.of_node, 0);
Dave Jianga9a753d2008-02-07 00:14:55 -0800651 res = devm_request_irq(&op->dev, pdata->irq,
Borislav Petkova18c3f12014-09-30 12:55:41 +0200652 mpc85xx_l2_isr, IRQF_SHARED,
Dave Jianga9a753d2008-02-07 00:14:55 -0800653 "[EDAC] L2 err", edac_dev);
654 if (res < 0) {
655 printk(KERN_ERR
Baruch Siache7d2c212013-02-10 11:39:52 +0200656 "%s: Unable to request irq %d for "
Dave Jianga9a753d2008-02-07 00:14:55 -0800657 "MPC85xx L2 err\n", __func__, pdata->irq);
658 irq_dispose_mapping(pdata->irq);
659 res = -ENODEV;
660 goto err2;
661 }
662
663 printk(KERN_INFO EDAC_MOD_STR " acquired irq %d for L2 Err\n",
664 pdata->irq);
665
666 edac_dev->op_state = OP_RUNNING_INTERRUPT;
667
668 out_be32(pdata->l2_vbase + MPC85XX_L2_ERRINTEN, L2_EIE_MASK);
669 }
670
671 devres_remove_group(&op->dev, mpc85xx_l2_err_probe);
672
Joe Perches956b9ba2012-04-29 17:08:39 -0300673 edac_dbg(3, "success\n");
Dave Jianga9a753d2008-02-07 00:14:55 -0800674 printk(KERN_INFO EDAC_MOD_STR " L2 err registered\n");
675
676 return 0;
677
678err2:
679 edac_device_del_device(&op->dev);
680err:
681 devres_release_group(&op->dev, mpc85xx_l2_err_probe);
682 edac_device_free_ctl_info(edac_dev);
683 return res;
684}
685
Grant Likely2dc11582010-08-06 09:25:50 -0600686static int mpc85xx_l2_err_remove(struct platform_device *op)
Dave Jianga9a753d2008-02-07 00:14:55 -0800687{
688 struct edac_device_ctl_info *edac_dev = dev_get_drvdata(&op->dev);
689 struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info;
690
Joe Perches956b9ba2012-04-29 17:08:39 -0300691 edac_dbg(0, "\n");
Dave Jianga9a753d2008-02-07 00:14:55 -0800692
693 if (edac_op_state == EDAC_OPSTATE_INT) {
694 out_be32(pdata->l2_vbase + MPC85XX_L2_ERRINTEN, 0);
695 irq_dispose_mapping(pdata->irq);
696 }
697
698 out_be32(pdata->l2_vbase + MPC85XX_L2_ERRDIS, orig_l2_err_disable);
699 edac_device_del_device(&op->dev);
700 edac_device_free_ctl_info(edac_dev);
701 return 0;
702}
703
Fabian Frederick1afaa052015-03-16 20:54:41 +0100704static const struct of_device_id mpc85xx_l2_err_of_match[] = {
Kumar Gala29d6cf22009-01-06 14:42:59 -0800705/* deprecate the fsl,85.. forms in the future, 2.6.30? */
706 { .compatible = "fsl,8540-l2-cache-controller", },
707 { .compatible = "fsl,8541-l2-cache-controller", },
708 { .compatible = "fsl,8544-l2-cache-controller", },
709 { .compatible = "fsl,8548-l2-cache-controller", },
710 { .compatible = "fsl,8555-l2-cache-controller", },
711 { .compatible = "fsl,8568-l2-cache-controller", },
712 { .compatible = "fsl,mpc8536-l2-cache-controller", },
713 { .compatible = "fsl,mpc8540-l2-cache-controller", },
714 { .compatible = "fsl,mpc8541-l2-cache-controller", },
715 { .compatible = "fsl,mpc8544-l2-cache-controller", },
716 { .compatible = "fsl,mpc8548-l2-cache-controller", },
717 { .compatible = "fsl,mpc8555-l2-cache-controller", },
718 { .compatible = "fsl,mpc8560-l2-cache-controller", },
719 { .compatible = "fsl,mpc8568-l2-cache-controller", },
Anton Vorontsovcd1542c2010-08-10 18:03:21 -0700720 { .compatible = "fsl,mpc8569-l2-cache-controller", },
Kumar Gala29d6cf22009-01-06 14:42:59 -0800721 { .compatible = "fsl,mpc8572-l2-cache-controller", },
Anton Vorontsovcd1542c2010-08-10 18:03:21 -0700722 { .compatible = "fsl,p1020-l2-cache-controller", },
723 { .compatible = "fsl,p1021-l2-cache-controller", },
Yang Shia0145542009-09-23 15:57:24 -0700724 { .compatible = "fsl,p2020-l2-cache-controller", },
Dave Jianga9a753d2008-02-07 00:14:55 -0800725 {},
726};
Anton Vorontsov952e1c62010-07-27 13:18:05 -0700727MODULE_DEVICE_TABLE(of, mpc85xx_l2_err_of_match);
Dave Jianga9a753d2008-02-07 00:14:55 -0800728
Grant Likely00006122011-02-22 19:59:54 -0700729static struct platform_driver mpc85xx_l2_err_driver = {
Dave Jianga9a753d2008-02-07 00:14:55 -0800730 .probe = mpc85xx_l2_err_probe,
731 .remove = mpc85xx_l2_err_remove,
732 .driver = {
Grant Likely40182942010-04-13 16:13:02 -0700733 .name = "mpc85xx_l2_err",
Grant Likely40182942010-04-13 16:13:02 -0700734 .of_match_table = mpc85xx_l2_err_of_match,
735 },
Dave Jianga9a753d2008-02-07 00:14:55 -0800736};
737
738/**************************** MC Err device ***************************/
739
Peter Tyserdcca7c32010-03-10 15:23:12 -0800740/*
741 * Taken from table 8-55 in the MPC8641 User's Manual and/or 9-61 in the
742 * MPC8572 User's Manual. Each line represents a syndrome bit column as a
743 * 64-bit value, but split into an upper and lower 32-bit chunk. The labels
744 * below correspond to Freescale's manuals.
745 */
746static unsigned int ecc_table[16] = {
747 /* MSB LSB */
748 /* [0:31] [32:63] */
749 0xf00fe11e, 0xc33c0ff7, /* Syndrome bit 7 */
750 0x00ff00ff, 0x00fff0ff,
751 0x0f0f0f0f, 0x0f0fff00,
752 0x11113333, 0x7777000f,
753 0x22224444, 0x8888222f,
754 0x44448888, 0xffff4441,
755 0x8888ffff, 0x11118882,
756 0xffff1111, 0x22221114, /* Syndrome bit 0 */
757};
758
759/*
760 * Calculate the correct ECC value for a 64-bit value specified by high:low
761 */
762static u8 calculate_ecc(u32 high, u32 low)
763{
764 u32 mask_low;
765 u32 mask_high;
766 int bit_cnt;
767 u8 ecc = 0;
768 int i;
769 int j;
770
771 for (i = 0; i < 8; i++) {
772 mask_high = ecc_table[i * 2];
773 mask_low = ecc_table[i * 2 + 1];
774 bit_cnt = 0;
775
776 for (j = 0; j < 32; j++) {
777 if ((mask_high >> j) & 1)
778 bit_cnt ^= (high >> j) & 1;
779 if ((mask_low >> j) & 1)
780 bit_cnt ^= (low >> j) & 1;
781 }
782
783 ecc |= bit_cnt << i;
784 }
785
786 return ecc;
787}
788
789/*
790 * Create the syndrome code which is generated if the data line specified by
791 * 'bit' failed. Eg generate an 8-bit codes seen in Table 8-55 in the MPC8641
792 * User's Manual and 9-61 in the MPC8572 User's Manual.
793 */
794static u8 syndrome_from_bit(unsigned int bit) {
795 int i;
796 u8 syndrome = 0;
797
798 /*
799 * Cycle through the upper or lower 32-bit portion of each value in
800 * ecc_table depending on if 'bit' is in the upper or lower half of
801 * 64-bit data.
802 */
803 for (i = bit < 32; i < 16; i += 2)
804 syndrome |= ((ecc_table[i] >> (bit % 32)) & 1) << (i / 2);
805
806 return syndrome;
807}
808
809/*
810 * Decode data and ecc syndrome to determine what went wrong
811 * Note: This can only decode single-bit errors
812 */
813static void sbe_ecc_decode(u32 cap_high, u32 cap_low, u32 cap_ecc,
814 int *bad_data_bit, int *bad_ecc_bit)
815{
816 int i;
817 u8 syndrome;
818
819 *bad_data_bit = -1;
820 *bad_ecc_bit = -1;
821
822 /*
823 * Calculate the ECC of the captured data and XOR it with the captured
824 * ECC to find an ECC syndrome value we can search for
825 */
826 syndrome = calculate_ecc(cap_high, cap_low) ^ cap_ecc;
827
828 /* Check if a data line is stuck... */
829 for (i = 0; i < 64; i++) {
830 if (syndrome == syndrome_from_bit(i)) {
831 *bad_data_bit = i;
832 return;
833 }
834 }
835
836 /* If data is correct, check ECC bits for errors... */
837 for (i = 0; i < 8; i++) {
838 if ((syndrome >> i) & 0x1) {
839 *bad_ecc_bit = i;
840 return;
841 }
842 }
843}
844
York Sun2ce39102015-05-12 18:03:42 +0800845#define make64(high, low) (((u64)(high) << 32) | (low))
846
Dave Jianga9a753d2008-02-07 00:14:55 -0800847static void mpc85xx_mc_check(struct mem_ctl_info *mci)
848{
849 struct mpc85xx_mc_pdata *pdata = mci->pvt_info;
850 struct csrow_info *csrow;
Peter Tyser21768632010-03-10 15:23:11 -0800851 u32 bus_width;
Dave Jianga9a753d2008-02-07 00:14:55 -0800852 u32 err_detect;
853 u32 syndrome;
York Sun2ce39102015-05-12 18:03:42 +0800854 u64 err_addr;
Dave Jianga9a753d2008-02-07 00:14:55 -0800855 u32 pfn;
856 int row_index;
Peter Tyserdcca7c32010-03-10 15:23:12 -0800857 u32 cap_high;
858 u32 cap_low;
859 int bad_data_bit;
860 int bad_ecc_bit;
Dave Jianga9a753d2008-02-07 00:14:55 -0800861
862 err_detect = in_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DETECT);
Dave Jiang55e57502009-04-21 12:24:56 -0700863 if (!err_detect)
Dave Jianga9a753d2008-02-07 00:14:55 -0800864 return;
865
866 mpc85xx_mc_printk(mci, KERN_ERR, "Err Detect Register: %#8.8x\n",
867 err_detect);
868
869 /* no more processing if not ECC bit errors */
870 if (!(err_detect & (DDR_EDE_SBE | DDR_EDE_MBE))) {
871 out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DETECT, err_detect);
872 return;
873 }
874
875 syndrome = in_be32(pdata->mc_vbase + MPC85XX_MC_CAPTURE_ECC);
Peter Tyser21768632010-03-10 15:23:11 -0800876
877 /* Mask off appropriate bits of syndrome based on bus width */
878 bus_width = (in_be32(pdata->mc_vbase + MPC85XX_MC_DDR_SDRAM_CFG) &
879 DSC_DBW_MASK) ? 32 : 64;
880 if (bus_width == 64)
881 syndrome &= 0xff;
882 else
883 syndrome &= 0xffff;
884
York Sun2ce39102015-05-12 18:03:42 +0800885 err_addr = make64(
886 in_be32(pdata->mc_vbase + MPC85XX_MC_CAPTURE_EXT_ADDRESS),
887 in_be32(pdata->mc_vbase + MPC85XX_MC_CAPTURE_ADDRESS));
Dave Jianga9a753d2008-02-07 00:14:55 -0800888 pfn = err_addr >> PAGE_SHIFT;
889
890 for (row_index = 0; row_index < mci->nr_csrows; row_index++) {
Mauro Carvalho Chehabde3910eb2012-04-24 15:05:43 -0300891 csrow = mci->csrows[row_index];
Dave Jianga9a753d2008-02-07 00:14:55 -0800892 if ((pfn >= csrow->first_page) && (pfn <= csrow->last_page))
893 break;
894 }
895
Peter Tyserdcca7c32010-03-10 15:23:12 -0800896 cap_high = in_be32(pdata->mc_vbase + MPC85XX_MC_CAPTURE_DATA_HI);
897 cap_low = in_be32(pdata->mc_vbase + MPC85XX_MC_CAPTURE_DATA_LO);
898
899 /*
900 * Analyze single-bit errors on 64-bit wide buses
901 * TODO: Add support for 32-bit wide buses
902 */
903 if ((err_detect & DDR_EDE_SBE) && (bus_width == 64)) {
904 sbe_ecc_decode(cap_high, cap_low, syndrome,
905 &bad_data_bit, &bad_ecc_bit);
906
907 if (bad_data_bit != -1)
908 mpc85xx_mc_printk(mci, KERN_ERR,
909 "Faulty Data bit: %d\n", bad_data_bit);
910 if (bad_ecc_bit != -1)
911 mpc85xx_mc_printk(mci, KERN_ERR,
912 "Faulty ECC bit: %d\n", bad_ecc_bit);
913
914 mpc85xx_mc_printk(mci, KERN_ERR,
915 "Expected Data / ECC:\t%#8.8x_%08x / %#2.2x\n",
916 cap_high ^ (1 << (bad_data_bit - 32)),
917 cap_low ^ (1 << bad_data_bit),
918 syndrome ^ (1 << bad_ecc_bit));
919 }
920
921 mpc85xx_mc_printk(mci, KERN_ERR,
922 "Captured Data / ECC:\t%#8.8x_%08x / %#2.2x\n",
923 cap_high, cap_low, syndrome);
York Sun2ce39102015-05-12 18:03:42 +0800924 mpc85xx_mc_printk(mci, KERN_ERR, "Err addr: %#8.8llx\n", err_addr);
Dave Jianga9a753d2008-02-07 00:14:55 -0800925 mpc85xx_mc_printk(mci, KERN_ERR, "PFN: %#8.8x\n", pfn);
926
927 /* we are out of range */
928 if (row_index == mci->nr_csrows)
929 mpc85xx_mc_printk(mci, KERN_ERR, "PFN out of range!\n");
930
931 if (err_detect & DDR_EDE_SBE)
Mauro Carvalho Chehab9eb07a72012-06-04 13:27:43 -0300932 edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
Mauro Carvalho Chehabad4d6e22012-04-16 15:11:08 -0300933 pfn, err_addr & ~PAGE_MASK, syndrome,
934 row_index, 0, -1,
Mauro Carvalho Chehab03f7eae2012-06-04 11:29:25 -0300935 mci->ctl_name, "");
Dave Jianga9a753d2008-02-07 00:14:55 -0800936
937 if (err_detect & DDR_EDE_MBE)
Mauro Carvalho Chehab9eb07a72012-06-04 13:27:43 -0300938 edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
Mauro Carvalho Chehabad4d6e22012-04-16 15:11:08 -0300939 pfn, err_addr & ~PAGE_MASK, syndrome,
940 row_index, 0, -1,
Mauro Carvalho Chehab03f7eae2012-06-04 11:29:25 -0300941 mci->ctl_name, "");
Dave Jianga9a753d2008-02-07 00:14:55 -0800942
943 out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DETECT, err_detect);
944}
945
946static irqreturn_t mpc85xx_mc_isr(int irq, void *dev_id)
947{
948 struct mem_ctl_info *mci = dev_id;
949 struct mpc85xx_mc_pdata *pdata = mci->pvt_info;
950 u32 err_detect;
951
952 err_detect = in_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DETECT);
953 if (!err_detect)
954 return IRQ_NONE;
955
956 mpc85xx_mc_check(mci);
957
958 return IRQ_HANDLED;
959}
960
Greg Kroah-Hartman9b3c6e82012-12-21 13:23:51 -0800961static void mpc85xx_init_csrows(struct mem_ctl_info *mci)
Dave Jianga9a753d2008-02-07 00:14:55 -0800962{
963 struct mpc85xx_mc_pdata *pdata = mci->pvt_info;
964 struct csrow_info *csrow;
Mauro Carvalho Chehab084a4fc2012-01-27 18:38:08 -0300965 struct dimm_info *dimm;
Dave Jianga9a753d2008-02-07 00:14:55 -0800966 u32 sdram_ctl;
967 u32 sdtype;
968 enum mem_type mtype;
969 u32 cs_bnds;
970 int index;
971
972 sdram_ctl = in_be32(pdata->mc_vbase + MPC85XX_MC_DDR_SDRAM_CFG);
973
974 sdtype = sdram_ctl & DSC_SDTYPE_MASK;
975 if (sdram_ctl & DSC_RD_EN) {
976 switch (sdtype) {
977 case DSC_SDTYPE_DDR:
978 mtype = MEM_RDDR;
979 break;
980 case DSC_SDTYPE_DDR2:
981 mtype = MEM_RDDR2;
982 break;
Yang Shib1cfebc2009-06-30 11:41:22 -0700983 case DSC_SDTYPE_DDR3:
984 mtype = MEM_RDDR3;
985 break;
Dave Jianga9a753d2008-02-07 00:14:55 -0800986 default:
987 mtype = MEM_UNKNOWN;
988 break;
989 }
990 } else {
991 switch (sdtype) {
992 case DSC_SDTYPE_DDR:
993 mtype = MEM_DDR;
994 break;
995 case DSC_SDTYPE_DDR2:
996 mtype = MEM_DDR2;
997 break;
Yang Shib1cfebc2009-06-30 11:41:22 -0700998 case DSC_SDTYPE_DDR3:
999 mtype = MEM_DDR3;
1000 break;
Dave Jianga9a753d2008-02-07 00:14:55 -08001001 default:
1002 mtype = MEM_UNKNOWN;
1003 break;
1004 }
1005 }
1006
1007 for (index = 0; index < mci->nr_csrows; index++) {
1008 u32 start;
1009 u32 end;
1010
Mauro Carvalho Chehabde3910eb2012-04-24 15:05:43 -03001011 csrow = mci->csrows[index];
1012 dimm = csrow->channels[0]->dimm;
Mauro Carvalho Chehab084a4fc2012-01-27 18:38:08 -03001013
Dave Jianga9a753d2008-02-07 00:14:55 -08001014 cs_bnds = in_be32(pdata->mc_vbase + MPC85XX_MC_CS_BNDS_0 +
1015 (index * MPC85XX_MC_CS_BNDS_OFS));
Ira W. Snyderb4846252009-09-23 15:57:25 -07001016
1017 start = (cs_bnds & 0xffff0000) >> 16;
1018 end = (cs_bnds & 0x0000ffff);
Dave Jianga9a753d2008-02-07 00:14:55 -08001019
1020 if (start == end)
1021 continue; /* not populated */
1022
Ira W. Snyderb4846252009-09-23 15:57:25 -07001023 start <<= (24 - PAGE_SHIFT);
1024 end <<= (24 - PAGE_SHIFT);
1025 end |= (1 << (24 - PAGE_SHIFT)) - 1;
1026
Peter Tysercff92792010-02-10 13:56:36 -08001027 csrow->first_page = start;
1028 csrow->last_page = end;
Mauro Carvalho Chehaba895bf82012-01-28 09:09:38 -03001029
1030 dimm->nr_pages = end + 1 - start;
Mauro Carvalho Chehab084a4fc2012-01-27 18:38:08 -03001031 dimm->grain = 8;
1032 dimm->mtype = mtype;
1033 dimm->dtype = DEV_UNKNOWN;
Dave Jianga9a753d2008-02-07 00:14:55 -08001034 if (sdram_ctl & DSC_X32_EN)
Mauro Carvalho Chehab084a4fc2012-01-27 18:38:08 -03001035 dimm->dtype = DEV_X32;
1036 dimm->edac_mode = EDAC_SECDED;
Dave Jianga9a753d2008-02-07 00:14:55 -08001037 }
1038}
1039
Greg Kroah-Hartman9b3c6e82012-12-21 13:23:51 -08001040static int mpc85xx_mc_err_probe(struct platform_device *op)
Dave Jianga9a753d2008-02-07 00:14:55 -08001041{
1042 struct mem_ctl_info *mci;
Mauro Carvalho Chehabad4d6e22012-04-16 15:11:08 -03001043 struct edac_mc_layer layers[2];
Dave Jianga9a753d2008-02-07 00:14:55 -08001044 struct mpc85xx_mc_pdata *pdata;
1045 struct resource r;
1046 u32 sdram_ctl;
1047 int res;
1048
1049 if (!devres_open_group(&op->dev, mpc85xx_mc_err_probe, GFP_KERNEL))
1050 return -ENOMEM;
1051
Mauro Carvalho Chehabad4d6e22012-04-16 15:11:08 -03001052 layers[0].type = EDAC_MC_LAYER_CHIP_SELECT;
1053 layers[0].size = 4;
1054 layers[0].is_virt_csrow = true;
1055 layers[1].type = EDAC_MC_LAYER_CHANNEL;
1056 layers[1].size = 1;
1057 layers[1].is_virt_csrow = false;
Kim Phillipsb9bc5dd2012-06-06 19:49:42 -05001058 mci = edac_mc_alloc(edac_mc_idx, ARRAY_SIZE(layers), layers,
1059 sizeof(*pdata));
Dave Jianga9a753d2008-02-07 00:14:55 -08001060 if (!mci) {
1061 devres_release_group(&op->dev, mpc85xx_mc_err_probe);
1062 return -ENOMEM;
1063 }
1064
1065 pdata = mci->pvt_info;
1066 pdata->name = "mpc85xx_mc_err";
1067 pdata->irq = NO_IRQ;
Mauro Carvalho Chehabfd687502012-03-16 07:44:18 -03001068 mci->pdev = &op->dev;
Dave Jianga9a753d2008-02-07 00:14:55 -08001069 pdata->edac_idx = edac_mc_idx++;
Mauro Carvalho Chehabfd687502012-03-16 07:44:18 -03001070 dev_set_drvdata(mci->pdev, mci);
Dave Jianga9a753d2008-02-07 00:14:55 -08001071 mci->ctl_name = pdata->name;
1072 mci->dev_name = pdata->name;
1073
Anatolij Gustschina26f95f2010-06-03 03:17:42 +02001074 res = of_address_to_resource(op->dev.of_node, 0, &r);
Dave Jianga9a753d2008-02-07 00:14:55 -08001075 if (res) {
1076 printk(KERN_ERR "%s: Unable to get resource for MC err regs\n",
1077 __func__);
1078 goto err;
1079 }
1080
Joe Perches28f65c112011-06-09 09:13:32 -07001081 if (!devm_request_mem_region(&op->dev, r.start, resource_size(&r),
1082 pdata->name)) {
Dave Jianga9a753d2008-02-07 00:14:55 -08001083 printk(KERN_ERR "%s: Error while requesting mem region\n",
1084 __func__);
1085 res = -EBUSY;
1086 goto err;
1087 }
1088
Joe Perches28f65c112011-06-09 09:13:32 -07001089 pdata->mc_vbase = devm_ioremap(&op->dev, r.start, resource_size(&r));
Dave Jianga9a753d2008-02-07 00:14:55 -08001090 if (!pdata->mc_vbase) {
1091 printk(KERN_ERR "%s: Unable to setup MC err regs\n", __func__);
1092 res = -ENOMEM;
1093 goto err;
1094 }
1095
1096 sdram_ctl = in_be32(pdata->mc_vbase + MPC85XX_MC_DDR_SDRAM_CFG);
1097 if (!(sdram_ctl & DSC_ECC_EN)) {
1098 /* no ECC */
1099 printk(KERN_WARNING "%s: No ECC DIMMs discovered\n", __func__);
1100 res = -ENODEV;
1101 goto err;
1102 }
1103
Joe Perches956b9ba2012-04-29 17:08:39 -03001104 edac_dbg(3, "init mci\n");
Dave Jianga9a753d2008-02-07 00:14:55 -08001105 mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_RDDR2 |
1106 MEM_FLAG_DDR | MEM_FLAG_DDR2;
1107 mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
1108 mci->edac_cap = EDAC_FLAG_SECDED;
1109 mci->mod_name = EDAC_MOD_STR;
1110 mci->mod_ver = MPC85XX_REVISION;
1111
1112 if (edac_op_state == EDAC_OPSTATE_POLL)
1113 mci->edac_check = mpc85xx_mc_check;
1114
1115 mci->ctl_page_to_phys = NULL;
1116
1117 mci->scrub_mode = SCRUB_SW_SRC;
1118
Dave Jianga9a753d2008-02-07 00:14:55 -08001119 mpc85xx_init_csrows(mci);
1120
Dave Jianga9a753d2008-02-07 00:14:55 -08001121 /* store the original error disable bits */
1122 orig_ddr_err_disable =
1123 in_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DISABLE);
1124 out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DISABLE, 0);
1125
1126 /* clear all error bits */
1127 out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DETECT, ~0);
1128
Takashi Iwai917c85b2015-02-04 11:48:56 +01001129 if (edac_mc_add_mc_with_groups(mci, mpc85xx_dev_groups)) {
Joe Perches956b9ba2012-04-29 17:08:39 -03001130 edac_dbg(3, "failed edac_mc_add_mc()\n");
Dave Jianga9a753d2008-02-07 00:14:55 -08001131 goto err;
1132 }
1133
1134 if (edac_op_state == EDAC_OPSTATE_INT) {
1135 out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_INT_EN,
1136 DDR_EIE_MBEE | DDR_EIE_SBEE);
1137
1138 /* store the original error management threshold */
1139 orig_ddr_err_sbe = in_be32(pdata->mc_vbase +
1140 MPC85XX_MC_ERR_SBE) & 0xff0000;
1141
1142 /* set threshold to 1 error per interrupt */
1143 out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_SBE, 0x10000);
1144
1145 /* register interrupts */
Anatolij Gustschina26f95f2010-06-03 03:17:42 +02001146 pdata->irq = irq_of_parse_and_map(op->dev.of_node, 0);
Dave Jianga9a753d2008-02-07 00:14:55 -08001147 res = devm_request_irq(&op->dev, pdata->irq,
Andrew Kilkenny60be7552008-10-15 22:04:28 -07001148 mpc85xx_mc_isr,
Johannes Thumshirne245e3b2014-01-21 09:42:27 +01001149 IRQF_SHARED,
Dave Jianga9a753d2008-02-07 00:14:55 -08001150 "[EDAC] MC err", mci);
1151 if (res < 0) {
1152 printk(KERN_ERR "%s: Unable to request irq %d for "
1153 "MPC85xx DRAM ERR\n", __func__, pdata->irq);
1154 irq_dispose_mapping(pdata->irq);
1155 res = -ENODEV;
1156 goto err2;
1157 }
1158
1159 printk(KERN_INFO EDAC_MOD_STR " acquired irq %d for MC\n",
1160 pdata->irq);
1161 }
1162
1163 devres_remove_group(&op->dev, mpc85xx_mc_err_probe);
Joe Perches956b9ba2012-04-29 17:08:39 -03001164 edac_dbg(3, "success\n");
Dave Jianga9a753d2008-02-07 00:14:55 -08001165 printk(KERN_INFO EDAC_MOD_STR " MC err registered\n");
1166
1167 return 0;
1168
1169err2:
1170 edac_mc_del_mc(&op->dev);
1171err:
1172 devres_release_group(&op->dev, mpc85xx_mc_err_probe);
1173 edac_mc_free(mci);
1174 return res;
1175}
1176
Grant Likely2dc11582010-08-06 09:25:50 -06001177static int mpc85xx_mc_err_remove(struct platform_device *op)
Dave Jianga9a753d2008-02-07 00:14:55 -08001178{
1179 struct mem_ctl_info *mci = dev_get_drvdata(&op->dev);
1180 struct mpc85xx_mc_pdata *pdata = mci->pvt_info;
1181
Joe Perches956b9ba2012-04-29 17:08:39 -03001182 edac_dbg(0, "\n");
Dave Jianga9a753d2008-02-07 00:14:55 -08001183
1184 if (edac_op_state == EDAC_OPSTATE_INT) {
1185 out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_INT_EN, 0);
1186 irq_dispose_mapping(pdata->irq);
1187 }
1188
1189 out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DISABLE,
1190 orig_ddr_err_disable);
1191 out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_SBE, orig_ddr_err_sbe);
1192
1193 edac_mc_del_mc(&op->dev);
1194 edac_mc_free(mci);
1195 return 0;
1196}
1197
Fabian Frederick1afaa052015-03-16 20:54:41 +01001198static const struct of_device_id mpc85xx_mc_err_of_match[] = {
Kumar Gala29d6cf22009-01-06 14:42:59 -08001199/* deprecate the fsl,85.. forms in the future, 2.6.30? */
1200 { .compatible = "fsl,8540-memory-controller", },
1201 { .compatible = "fsl,8541-memory-controller", },
1202 { .compatible = "fsl,8544-memory-controller", },
1203 { .compatible = "fsl,8548-memory-controller", },
1204 { .compatible = "fsl,8555-memory-controller", },
1205 { .compatible = "fsl,8568-memory-controller", },
1206 { .compatible = "fsl,mpc8536-memory-controller", },
1207 { .compatible = "fsl,mpc8540-memory-controller", },
1208 { .compatible = "fsl,mpc8541-memory-controller", },
1209 { .compatible = "fsl,mpc8544-memory-controller", },
1210 { .compatible = "fsl,mpc8548-memory-controller", },
1211 { .compatible = "fsl,mpc8555-memory-controller", },
1212 { .compatible = "fsl,mpc8560-memory-controller", },
1213 { .compatible = "fsl,mpc8568-memory-controller", },
Anton Vorontsov5528e222010-07-20 13:24:28 -07001214 { .compatible = "fsl,mpc8569-memory-controller", },
Kumar Gala29d6cf22009-01-06 14:42:59 -08001215 { .compatible = "fsl,mpc8572-memory-controller", },
Ira W. Snyderb4846252009-09-23 15:57:25 -07001216 { .compatible = "fsl,mpc8349-memory-controller", },
Anton Vorontsovcd1542c2010-08-10 18:03:21 -07001217 { .compatible = "fsl,p1020-memory-controller", },
1218 { .compatible = "fsl,p1021-memory-controller", },
Yang Shia0145542009-09-23 15:57:24 -07001219 { .compatible = "fsl,p2020-memory-controller", },
Shaohui Xie86f9a4332011-11-15 14:52:22 -08001220 { .compatible = "fsl,qoriq-memory-controller", },
Dave Jianga9a753d2008-02-07 00:14:55 -08001221 {},
1222};
Anton Vorontsov952e1c62010-07-27 13:18:05 -07001223MODULE_DEVICE_TABLE(of, mpc85xx_mc_err_of_match);
Dave Jianga9a753d2008-02-07 00:14:55 -08001224
Grant Likely00006122011-02-22 19:59:54 -07001225static struct platform_driver mpc85xx_mc_err_driver = {
Dave Jianga9a753d2008-02-07 00:14:55 -08001226 .probe = mpc85xx_mc_err_probe,
1227 .remove = mpc85xx_mc_err_remove,
1228 .driver = {
Grant Likely40182942010-04-13 16:13:02 -07001229 .name = "mpc85xx_mc_err",
Grant Likely40182942010-04-13 16:13:02 -07001230 .of_match_table = mpc85xx_mc_err_of_match,
1231 },
Dave Jianga9a753d2008-02-07 00:14:55 -08001232};
1233
Christoph Eggerbd1688d2010-08-10 18:03:18 -07001234#ifdef CONFIG_FSL_SOC_BOOKE
Andrew Kilkenny60be7552008-10-15 22:04:28 -07001235static void __init mpc85xx_mc_clear_rfxe(void *data)
1236{
1237 orig_hid1[smp_processor_id()] = mfspr(SPRN_HID1);
Kumar Galaa94d7b32011-03-31 17:11:39 -05001238 mtspr(SPRN_HID1, (orig_hid1[smp_processor_id()] & ~HID1_RFXE));
Andrew Kilkenny60be7552008-10-15 22:04:28 -07001239}
Ira W. Snyderb4846252009-09-23 15:57:25 -07001240#endif
Andrew Kilkenny60be7552008-10-15 22:04:28 -07001241
Thierry Redingd54051f2015-12-03 10:57:12 +01001242static struct platform_driver * const drivers[] = {
1243 &mpc85xx_mc_err_driver,
1244 &mpc85xx_l2_err_driver,
Scott Wood666db562015-12-10 13:07:12 -06001245#ifdef CONFIG_PCI
1246 &mpc85xx_pci_err_driver,
1247#endif
Thierry Redingd54051f2015-12-03 10:57:12 +01001248};
1249
Dave Jianga9a753d2008-02-07 00:14:55 -08001250static int __init mpc85xx_mc_init(void)
1251{
1252 int res = 0;
Sudip Mukherjeef2b59ac2016-02-02 21:09:33 +05301253 u32 __maybe_unused pvr = 0;
Dave Jianga9a753d2008-02-07 00:14:55 -08001254
1255 printk(KERN_INFO "Freescale(R) MPC85xx EDAC driver, "
1256 "(C) 2006 Montavista Software\n");
1257
1258 /* make sure error reporting method is sane */
1259 switch (edac_op_state) {
1260 case EDAC_OPSTATE_POLL:
1261 case EDAC_OPSTATE_INT:
1262 break;
1263 default:
1264 edac_op_state = EDAC_OPSTATE_INT;
1265 break;
1266 }
1267
Thierry Redingd54051f2015-12-03 10:57:12 +01001268 res = platform_register_drivers(drivers, ARRAY_SIZE(drivers));
Dave Jianga9a753d2008-02-07 00:14:55 -08001269 if (res)
Thierry Redingd54051f2015-12-03 10:57:12 +01001270 printk(KERN_WARNING EDAC_MOD_STR "drivers fail to register\n");
Dave Jianga9a753d2008-02-07 00:14:55 -08001271
Christoph Eggerbd1688d2010-08-10 18:03:18 -07001272#ifdef CONFIG_FSL_SOC_BOOKE
Kumar Galaa94d7b32011-03-31 17:11:39 -05001273 pvr = mfspr(SPRN_PVR);
1274
1275 if ((PVR_VER(pvr) == PVR_VER_E500V1) ||
1276 (PVR_VER(pvr) == PVR_VER_E500V2)) {
1277 /*
1278 * need to clear HID1[RFXE] to disable machine check int
1279 * so we can catch it
1280 */
1281 if (edac_op_state == EDAC_OPSTATE_INT)
1282 on_each_cpu(mpc85xx_mc_clear_rfxe, NULL, 0);
1283 }
Ira W. Snyderb4846252009-09-23 15:57:25 -07001284#endif
Dave Jianga9a753d2008-02-07 00:14:55 -08001285
1286 return 0;
1287}
1288
1289module_init(mpc85xx_mc_init);
1290
Christoph Eggerbd1688d2010-08-10 18:03:18 -07001291#ifdef CONFIG_FSL_SOC_BOOKE
Andrew Kilkenny60be7552008-10-15 22:04:28 -07001292static void __exit mpc85xx_mc_restore_hid1(void *data)
1293{
1294 mtspr(SPRN_HID1, orig_hid1[smp_processor_id()]);
1295}
Ira W. Snyderb4846252009-09-23 15:57:25 -07001296#endif
Andrew Kilkenny60be7552008-10-15 22:04:28 -07001297
Dave Jianga9a753d2008-02-07 00:14:55 -08001298static void __exit mpc85xx_mc_exit(void)
1299{
Christoph Eggerbd1688d2010-08-10 18:03:18 -07001300#ifdef CONFIG_FSL_SOC_BOOKE
Kumar Galaa94d7b32011-03-31 17:11:39 -05001301 u32 pvr = mfspr(SPRN_PVR);
1302
1303 if ((PVR_VER(pvr) == PVR_VER_E500V1) ||
1304 (PVR_VER(pvr) == PVR_VER_E500V2)) {
1305 on_each_cpu(mpc85xx_mc_restore_hid1, NULL, 0);
1306 }
Ira W. Snyderb4846252009-09-23 15:57:25 -07001307#endif
Thierry Redingd54051f2015-12-03 10:57:12 +01001308 platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
Dave Jianga9a753d2008-02-07 00:14:55 -08001309}
1310
1311module_exit(mpc85xx_mc_exit);
1312
1313MODULE_LICENSE("GPL");
1314MODULE_AUTHOR("Montavista Software, Inc.");
1315module_param(edac_op_state, int, 0444);
1316MODULE_PARM_DESC(edac_op_state,
1317 "EDAC Error Reporting state: 0=Poll, 2=Interrupt");