Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  * Marvell MV64x60 Memory Controller kernel module for PPC platforms
  3  *
  4  * Author: Dave Jiang <djiang@mvista.com>
  5  *
  6  * 2006-2007 (c) MontaVista Software, Inc. This file is licensed under
  7  * the terms of the GNU General Public License version 2. This program
  8  * is licensed "as is" without any warranty of any kind, whether express
  9  * or implied.
 10  *
 11  */
 12 
 13 #include <linux/module.h>
 14 #include <linux/init.h>
 15 #include <linux/slab.h>
 16 #include <linux/interrupt.h>
 17 #include <linux/io.h>
 18 #include <linux/edac.h>
 19 
 20 #include "edac_core.h"
 21 #include "edac_module.h"
 22 #include "mv64x60_edac.h"
 23 
 24 static const char *mv64x60_ctl_name = "MV64x60";
 25 static int edac_dev_idx;
 26 static int edac_pci_idx;
 27 static int edac_mc_idx;
 28 
 29 /*********************** PCI err device **********************************/
 30 #ifdef CONFIG_PCI
 31 static void mv64x60_pci_check(struct edac_pci_ctl_info *pci)
 32 {
 33         struct mv64x60_pci_pdata *pdata = pci->pvt_info;
 34         u32 cause;
 35 
 36         cause = in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE);
 37         if (!cause)
 38                 return;
 39 
 40         printk(KERN_ERR "Error in PCI %d Interface\n", pdata->pci_hose);
 41         printk(KERN_ERR "Cause register: 0x%08x\n", cause);
 42         printk(KERN_ERR "Address Low: 0x%08x\n",
 43                in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_ADDR_LO));
 44         printk(KERN_ERR "Address High: 0x%08x\n",
 45                in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_ADDR_HI));
 46         printk(KERN_ERR "Attribute: 0x%08x\n",
 47                in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_ATTR));
 48         printk(KERN_ERR "Command: 0x%08x\n",
 49                in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CMD));
 50         out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE, ~cause);
 51 
 52         if (cause & MV64X60_PCI_PE_MASK)
 53                 edac_pci_handle_pe(pci, pci->ctl_name);
 54 
 55         if (!(cause & MV64X60_PCI_PE_MASK))
 56                 edac_pci_handle_npe(pci, pci->ctl_name);
 57 }
 58 
 59 static irqreturn_t mv64x60_pci_isr(int irq, void *dev_id)
 60 {
 61         struct edac_pci_ctl_info *pci = dev_id;
 62         struct mv64x60_pci_pdata *pdata = pci->pvt_info;
 63         u32 val;
 64 
 65         val = in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE);
 66         if (!val)
 67                 return IRQ_NONE;
 68 
 69         mv64x60_pci_check(pci);
 70 
 71         return IRQ_HANDLED;
 72 }
 73 
 74 static int __devinit mv64x60_pci_err_probe(struct platform_device *pdev)
 75 {
 76         struct edac_pci_ctl_info *pci;
 77         struct mv64x60_pci_pdata *pdata;
 78         struct resource *r;
 79         int res = 0;
 80 
 81         if (!devres_open_group(&pdev->dev, mv64x60_pci_err_probe, GFP_KERNEL))
 82                 return -ENOMEM;
 83 
 84         pci = edac_pci_alloc_ctl_info(sizeof(*pdata), "mv64x60_pci_err");
 85         if (!pci)
 86                 return -ENOMEM;
 87 
 88         pdata = pci->pvt_info;
 89 
 90         pdata->pci_hose = pdev->id;
 91         pdata->name = "mpc85xx_pci_err";
 92         pdata->irq = NO_IRQ;
 93         platform_set_drvdata(pdev, pci);
 94         pci->dev = &pdev->dev;
 95         pci->dev_name = pdev->dev.bus_id;
 96         pci->mod_name = EDAC_MOD_STR;
 97         pci->ctl_name = pdata->name;
 98 
 99         if (edac_op_state == EDAC_OPSTATE_POLL)
100                 pci->edac_check = mv64x60_pci_check;
101 
102         pdata->edac_idx = edac_pci_idx++;
103 
104         r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
105         if (!r) {
106                 printk(KERN_ERR "%s: Unable to get resource for "
107                        "PCI err regs\n", __func__);
108                 res = -ENOENT;
109                 goto err;
110         }
111 
112         if (!devm_request_mem_region(&pdev->dev,
113                                      r->start,
114                                      r->end - r->start + 1,
115                                      pdata->name)) {
116                 printk(KERN_ERR "%s: Error while requesting mem region\n",
117                        __func__);
118                 res = -EBUSY;
119                 goto err;
120         }
121 
122         pdata->pci_vbase = devm_ioremap(&pdev->dev,
123                                         r->start,
124                                         r->end - r->start + 1);
125         if (!pdata->pci_vbase) {
126                 printk(KERN_ERR "%s: Unable to setup PCI err regs\n", __func__);
127                 res = -ENOMEM;
128                 goto err;
129         }
130 
131         out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE, 0);
132         out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_MASK, 0);
133         out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_MASK,
134                  MV64X60_PCIx_ERR_MASK_VAL);
135 
136         if (edac_pci_add_device(pci, pdata->edac_idx) > 0) {
137                 debugf3("%s(): failed edac_pci_add_device()\n", __func__);
138                 goto err;
139         }
140 
141         if (edac_op_state == EDAC_OPSTATE_INT) {
142                 pdata->irq = platform_get_irq(pdev, 0);
143                 res = devm_request_irq(&pdev->dev,
144                                        pdata->irq,
145                                        mv64x60_pci_isr,
146                                        IRQF_DISABLED,
147                                        "[EDAC] PCI err",
148                                        pci);
149                 if (res < 0) {
150                         printk(KERN_ERR "%s: Unable to request irq %d for "
151                                "MV64x60 PCI ERR\n", __func__, pdata->irq);
152                         res = -ENODEV;
153                         goto err2;
154                 }
155                 printk(KERN_INFO EDAC_MOD_STR " acquired irq %d for PCI Err\n",
156                        pdata->irq);
157         }
158 
159         devres_remove_group(&pdev->dev, mv64x60_pci_err_probe);
160 
161         /* get this far and it's successful */
162         debugf3("%s(): success\n", __func__);
163 
164         return 0;
165 
166 err2:
167         edac_pci_del_device(&pdev->dev);
168 err:
169         edac_pci_free_ctl_info(pci);
170         devres_release_group(&pdev->dev, mv64x60_pci_err_probe);
171         return res;
172 }
173 
174 static int mv64x60_pci_err_remove(struct platform_device *pdev)
175 {
176         struct edac_pci_ctl_info *pci = platform_get_drvdata(pdev);
177 
178         debugf0("%s()\n", __func__);
179 
180         edac_pci_del_device(&pdev->dev);
181 
182         edac_pci_free_ctl_info(pci);
183 
184         return 0;
185 }
186 
187 static struct platform_driver mv64x60_pci_err_driver = {
188         .probe = mv64x60_pci_err_probe,
189         .remove = __devexit_p(mv64x60_pci_err_remove),
190         .driver = {
191                    .name = "mv64x60_pci_err",
192         }
193 };
194 
195 #endif /* CONFIG_PCI */
196 
197 /*********************** SRAM err device **********************************/
198 static void mv64x60_sram_check(struct edac_device_ctl_info *edac_dev)
199 {
200         struct mv64x60_sram_pdata *pdata = edac_dev->pvt_info;
201         u32 cause;
202 
203         cause = in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE);
204         if (!cause)
205                 return;
206 
207         printk(KERN_ERR "Error in internal SRAM\n");
208         printk(KERN_ERR "Cause register: 0x%08x\n", cause);
209         printk(KERN_ERR "Address Low: 0x%08x\n",
210                in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_ADDR_LO));
211         printk(KERN_ERR "Address High: 0x%08x\n",
212                in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_ADDR_HI));
213         printk(KERN_ERR "Data Low: 0x%08x\n",
214                in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_DATA_LO));
215         printk(KERN_ERR "Data High: 0x%08x\n",
216                in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_DATA_HI));
217         printk(KERN_ERR "Parity: 0x%08x\n",
218                in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_PARITY));
219         out_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE, 0);
220 
221         edac_device_handle_ue(edac_dev, 0, 0, edac_dev->ctl_name);
222 }
223 
224 static irqreturn_t mv64x60_sram_isr(int irq, void *dev_id)
225 {
226         struct edac_device_ctl_info *edac_dev = dev_id;
227         struct mv64x60_sram_pdata *pdata = edac_dev->pvt_info;
228         u32 cause;
229 
230         cause = in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE);
231         if (!cause)
232                 return IRQ_NONE;
233 
234         mv64x60_sram_check(edac_dev);
235 
236         return IRQ_HANDLED;
237 }
238 
239 static int __devinit mv64x60_sram_err_probe(struct platform_device *pdev)
240 {
241         struct edac_device_ctl_info *edac_dev;
242         struct mv64x60_sram_pdata *pdata;
243         struct resource *r;
244         int res = 0;
245 
246         if (!devres_open_group(&pdev->dev, mv64x60_sram_err_probe, GFP_KERNEL))
247                 return -ENOMEM;
248 
249         edac_dev = edac_device_alloc_ctl_info(sizeof(*pdata),
250                                               "sram", 1, NULL, 0, 0, NULL, 0,
251                                               edac_dev_idx);
252         if (!edac_dev) {
253                 devres_release_group(&pdev->dev, mv64x60_sram_err_probe);
254                 return -ENOMEM;
255         }
256 
257         pdata = edac_dev->pvt_info;
258         pdata->name = "mv64x60_sram_err";
259         pdata->irq = NO_IRQ;
260         edac_dev->dev = &pdev->dev;
261         platform_set_drvdata(pdev, edac_dev);
262         edac_dev->dev_name = pdev->dev.bus_id;
263 
264         r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
265         if (!r) {
266                 printk(KERN_ERR "%s: Unable to get resource for "
267                        "SRAM err regs\n", __func__);
268                 res = -ENOENT;
269                 goto err;
270         }
271 
272         if (!devm_request_mem_region(&pdev->dev,
273                                      r->start,
274                                      r->end - r->start + 1,
275                                      pdata->name)) {
276                 printk(KERN_ERR "%s: Error while request mem region\n",
277                        __func__);
278                 res = -EBUSY;
279                 goto err;
280         }
281 
282         pdata->sram_vbase = devm_ioremap(&pdev->dev,
283                                          r->start,
284                                          r->end - r->start + 1);
285         if (!pdata->sram_vbase) {
286                 printk(KERN_ERR "%s: Unable to setup SRAM err regs\n",
287                        __func__);
288                 res = -ENOMEM;
289                 goto err;
290         }
291 
292         /* setup SRAM err registers */
293         out_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE, 0);
294 
295         edac_dev->mod_name = EDAC_MOD_STR;
296         edac_dev->ctl_name = pdata->name;
297 
298         if (edac_op_state == EDAC_OPSTATE_POLL)
299                 edac_dev->edac_check = mv64x60_sram_check;
300 
301         pdata->edac_idx = edac_dev_idx++;
302 
303         if (edac_device_add_device(edac_dev) > 0) {
304                 debugf3("%s(): failed edac_device_add_device()\n", __func__);
305                 goto err;
306         }
307 
308         if (edac_op_state == EDAC_OPSTATE_INT) {
309                 pdata->irq = platform_get_irq(pdev, 0);
310                 res = devm_request_irq(&pdev->dev,
311                                        pdata->irq,
312                                        mv64x60_sram_isr,
313                                        IRQF_DISABLED,
314                                        "[EDAC] SRAM err",
315                                        edac_dev);
316                 if (res < 0) {
317                         printk(KERN_ERR
318                                "%s: Unable to request irq %d for "
319                                "MV64x60 SRAM ERR\n", __func__, pdata->irq);
320                         res = -ENODEV;
321                         goto err2;
322                 }
323 
324                 printk(KERN_INFO EDAC_MOD_STR " acquired irq %d for SRAM Err\n",
325                        pdata->irq);
326         }
327 
328         devres_remove_group(&pdev->dev, mv64x60_sram_err_probe);
329 
330         /* get this far and it's successful */
331         debugf3("%s(): success\n", __func__);
332 
333         return 0;
334 
335 err2:
336         edac_device_del_device(&pdev->dev);
337 err:
338         devres_release_group(&pdev->dev, mv64x60_sram_err_probe);
339         edac_device_free_ctl_info(edac_dev);
340         return res;
341 }
342 
343 static int mv64x60_sram_err_remove(struct platform_device *pdev)
344 {
345         struct edac_device_ctl_info *edac_dev = platform_get_drvdata(pdev);
346 
347         debugf0("%s()\n", __func__);
348 
349         edac_device_del_device(&pdev->dev);
350         edac_device_free_ctl_info(edac_dev);
351 
352         return 0;
353 }
354 
355 static struct platform_driver mv64x60_sram_err_driver = {
356         .probe = mv64x60_sram_err_probe,
357         .remove = mv64x60_sram_err_remove,
358         .driver = {
359                    .name = "mv64x60_sram_err",
360         }
361 };
362 
363 /*********************** CPU err device **********************************/
364 static void mv64x60_cpu_check(struct edac_device_ctl_info *edac_dev)
365 {
366         struct mv64x60_cpu_pdata *pdata = edac_dev->pvt_info;
367         u32 cause;
368 
369         cause = in_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE) &
370             MV64x60_CPU_CAUSE_MASK;
371         if (!cause)
372                 return;
373 
374         printk(KERN_ERR "Error on CPU interface\n");
375         printk(KERN_ERR "Cause register: 0x%08x\n", cause);
376         printk(KERN_ERR "Address Low: 0x%08x\n",
377                in_le32(pdata->cpu_vbase[0] + MV64x60_CPU_ERR_ADDR_LO));
378         printk(KERN_ERR "Address High: 0x%08x\n",
379                in_le32(pdata->cpu_vbase[0] + MV64x60_CPU_ERR_ADDR_HI));
380         printk(KERN_ERR "Data Low: 0x%08x\n",
381                in_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_DATA_LO));
382         printk(KERN_ERR "Data High: 0x%08x\n",
383                in_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_DATA_HI));
384         printk(KERN_ERR "Parity: 0x%08x\n",
385                in_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_PARITY));
386         out_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE, 0);
387 
388         edac_device_handle_ue(edac_dev, 0, 0, edac_dev->ctl_name);
389 }
390 
391 static irqreturn_t mv64x60_cpu_isr(int irq, void *dev_id)
392 {
393         struct edac_device_ctl_info *edac_dev = dev_id;
394         struct mv64x60_cpu_pdata *pdata = edac_dev->pvt_info;
395         u32 cause;
396 
397         cause = in_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE) &
398             MV64x60_CPU_CAUSE_MASK;
399         if (!cause)
400                 return IRQ_NONE;
401 
402         mv64x60_cpu_check(edac_dev);
403 
404         return IRQ_HANDLED;
405 }
406 
407 static int __devinit mv64x60_cpu_err_probe(struct platform_device *pdev)
408 {
409         struct edac_device_ctl_info *edac_dev;
410         struct resource *r;
411         struct mv64x60_cpu_pdata *pdata;
412         int res = 0;
413 
414         if (!devres_open_group(&pdev->dev, mv64x60_cpu_err_probe, GFP_KERNEL))
415                 return -ENOMEM;
416 
417         edac_dev = edac_device_alloc_ctl_info(sizeof(*pdata),
418                                               "cpu", 1, NULL, 0, 0, NULL, 0,
419                                               edac_dev_idx);
420         if (!edac_dev) {
421                 devres_release_group(&pdev->dev, mv64x60_cpu_err_probe);
422                 return -ENOMEM;
423         }
424 
425         pdata = edac_dev->pvt_info;
426         pdata->name = "mv64x60_cpu_err";
427         pdata->irq = NO_IRQ;
428         edac_dev->dev = &pdev->dev;
429         platform_set_drvdata(pdev, edac_dev);
430         edac_dev->dev_name = pdev->dev.bus_id;
431 
432         r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
433         if (!r) {
434                 printk(KERN_ERR "%s: Unable to get resource for "
435                        "CPU err regs\n", __func__);
436                 res = -ENOENT;
437                 goto err;
438         }
439 
440         if (!devm_request_mem_region(&pdev->dev,
441                                      r->start,
442                                      r->end - r->start + 1,
443                                      pdata->name)) {
444                 printk(KERN_ERR "%s: Error while requesting mem region\n",
445                        __func__);
446                 res = -EBUSY;
447                 goto err;
448         }
449 
450         pdata->cpu_vbase[0] = devm_ioremap(&pdev->dev,
451                                            r->start,
452                                            r->end - r->start + 1);
453         if (!pdata->cpu_vbase[0]) {
454                 printk(KERN_ERR "%s: Unable to setup CPU err regs\n", __func__);
455                 res = -ENOMEM;
456                 goto err;
457         }
458 
459         r = platform_get_resource(pdev, IORESOURCE_MEM, 1);
460         if (!r) {
461                 printk(KERN_ERR "%s: Unable to get resource for "
462                        "CPU err regs\n", __func__);
463                 res = -ENOENT;
464                 goto err;
465         }
466 
467         if (!devm_request_mem_region(&pdev->dev,
468                                      r->start,
469                                      r->end - r->start + 1,
470                                      pdata->name)) {
471                 printk(KERN_ERR "%s: Error while requesting mem region\n",
472                        __func__);
473                 res = -EBUSY;
474                 goto err;
475         }
476 
477         pdata->cpu_vbase[1] = devm_ioremap(&pdev->dev,
478                                            r->start,
479                                            r->end - r->start + 1);
480         if (!pdata->cpu_vbase[1]) {
481                 printk(KERN_ERR "%s: Unable to setup CPU err regs\n", __func__);
482                 res = -ENOMEM;
483                 goto err;
484         }
485 
486         /* setup CPU err registers */
487         out_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE, 0);
488         out_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_MASK, 0);
489         out_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_MASK, 0x000000ff);
490 
491         edac_dev->mod_name = EDAC_MOD_STR;
492         edac_dev->ctl_name = pdata->name;
493         if (edac_op_state == EDAC_OPSTATE_POLL)
494                 edac_dev->edac_check = mv64x60_cpu_check;
495 
496         pdata->edac_idx = edac_dev_idx++;
497 
498         if (edac_device_add_device(edac_dev) > 0) {
499                 debugf3("%s(): failed edac_device_add_device()\n", __func__);
500                 goto err;
501         }
502 
503         if (edac_op_state == EDAC_OPSTATE_INT) {
504                 pdata->irq = platform_get_irq(pdev, 0);
505                 res = devm_request_irq(&pdev->dev,
506                                        pdata->irq,
507                                        mv64x60_cpu_isr,
508                                        IRQF_DISABLED,
509                                        "[EDAC] CPU err",
510                                        edac_dev);
511                 if (res < 0) {
512                         printk(KERN_ERR
513                                "%s: Unable to request irq %d for MV64x60 "
514                                "CPU ERR\n", __func__, pdata->irq);
515                         res = -ENODEV;
516                         goto err2;
517                 }
518 
519                 printk(KERN_INFO EDAC_MOD_STR
520                        " acquired irq %d for CPU Err\n", pdata->irq);
521         }
522 
523         devres_remove_group(&pdev->dev, mv64x60_cpu_err_probe);
524 
525         /* get this far and it's successful */
526         debugf3("%s(): success\n", __func__);
527 
528         return 0;
529 
530 err2:
531         edac_device_del_device(&pdev->dev);
532 err:
533         devres_release_group(&pdev->dev, mv64x60_cpu_err_probe);
534         edac_device_free_ctl_info(edac_dev);
535         return res;
536 }
537 
538 static int mv64x60_cpu_err_remove(struct platform_device *pdev)
539 {
540         struct edac_device_ctl_info *edac_dev = platform_get_drvdata(pdev);
541 
542         debugf0("%s()\n", __func__);
543 
544         edac_device_del_device(&pdev->dev);
545         edac_device_free_ctl_info(edac_dev);
546         return 0;
547 }
548 
549 static struct platform_driver mv64x60_cpu_err_driver = {
550         .probe = mv64x60_cpu_err_probe,
551         .remove = mv64x60_cpu_err_remove,
552         .driver = {
553                    .name = "mv64x60_cpu_err",
554         }
555 };
556 
557 /*********************** DRAM err device **********************************/
558 
559 static void mv64x60_mc_check(struct mem_ctl_info *mci)
560 {
561         struct mv64x60_mc_pdata *pdata = mci->pvt_info;
562         u32 reg;
563         u32 err_addr;
564         u32 sdram_ecc;
565         u32 comp_ecc;
566         u32 syndrome;
567 
568         reg = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR);
569         if (!reg)
570                 return;
571 
572         err_addr = reg & ~0x3;
573         sdram_ecc = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_RCVD);
574         comp_ecc = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CALC);
575         syndrome = sdram_ecc ^ comp_ecc;
576 
577         /* first bit clear in ECC Err Reg, 1 bit error, correctable by HW */
578         if (!(reg & 0x1))
579                 edac_mc_handle_ce(mci, err_addr >> PAGE_SHIFT,
580                                   err_addr & PAGE_MASK, syndrome, 0, 0,
581                                   mci->ctl_name);
582         else    /* 2 bit error, UE */
583                 edac_mc_handle_ue(mci, err_addr >> PAGE_SHIFT,
584                                   err_addr & PAGE_MASK, 0, mci->ctl_name);
585 
586         /* clear the error */
587         out_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR, 0);
588 }
589 
590 static irqreturn_t mv64x60_mc_isr(int irq, void *dev_id)
591 {
592         struct mem_ctl_info *mci = dev_id;
593         struct mv64x60_mc_pdata *pdata = mci->pvt_info;
594         u32 reg;
595 
596         reg = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR);
597         if (!reg)
598                 return IRQ_NONE;
599 
600         /* writing 0's to the ECC err addr in check function clears irq */
601         mv64x60_mc_check(mci);
602 
603         return IRQ_HANDLED;
604 }
605 
606 static void get_total_mem(struct mv64x60_mc_pdata *pdata)
607 {
608         struct device_node *np = NULL;
609         const unsigned int *reg;
610 
611         np = of_find_node_by_type(NULL, "memory");
612         if (!np)
613                 return;
614 
615         reg = get_property(np, "reg", NULL);
616 
617         pdata->total_mem = reg[1];
618 }
619 
620 static void mv64x60_init_csrows(struct mem_ctl_info *mci,
621                                 struct mv64x60_mc_pdata *pdata)
622 {
623         struct csrow_info *csrow;
624         u32 devtype;
625         u32 ctl;
626 
627         get_total_mem(pdata);
628 
629         ctl = in_le32(pdata->mc_vbase + MV64X60_SDRAM_CONFIG);
630 
631         csrow = &mci->csrows[0];
632         csrow->first_page = 0;
633         csrow->nr_pages = pdata->total_mem >> PAGE_SHIFT;
634         csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
635         csrow->grain = 8;
636 
637         csrow->mtype = (ctl & MV64X60_SDRAM_REGISTERED) ? MEM_RDDR : MEM_DDR;
638 
639         devtype = (ctl >> 20) & 0x3;
640         switch (devtype) {
641         case 0x0:
642                 csrow->dtype = DEV_X32;
643                 break;
644         case 0x2:               /* could be X8 too, but no way to tell */
645                 csrow->dtype = DEV_X16;
646                 break;
647         case 0x3:
648                 csrow->dtype = DEV_X4;
649                 break;
650         default:
651                 csrow->dtype = DEV_UNKNOWN;
652                 break;
653         }
654 
655         csrow->edac_mode = EDAC_SECDED;
656 }
657 
658 static int __devinit mv64x60_mc_err_probe(struct platform_device *pdev)
659 {
660         struct mem_ctl_info *mci;
661         struct mv64x60_mc_pdata *pdata;
662         struct resource *r;
663         u32 ctl;
664         int res = 0;
665 
666         if (!devres_open_group(&pdev->dev, mv64x60_mc_err_probe, GFP_KERNEL))
667                 return -ENOMEM;
668 
669         mci = edac_mc_alloc(sizeof(struct mv64x60_mc_pdata), 1, 1, edac_mc_idx);
670         if (!mci) {
671                 printk(KERN_ERR "%s: No memory for CPU err\n", __func__);
672                 devres_release_group(&pdev->dev, mv64x60_mc_err_probe);
673                 return -ENOMEM;
674         }
675 
676         pdata = mci->pvt_info;
677         mci->dev = &pdev->dev;
678         platform_set_drvdata(pdev, mci);
679         pdata->name = "mv64x60_mc_err";
680         pdata->irq = NO_IRQ;
681         mci->dev_name = pdev->dev.bus_id;
682         pdata->edac_idx = edac_mc_idx++;
683 
684         r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
685         if (!r) {
686                 printk(KERN_ERR "%s: Unable to get resource for "
687                        "MC err regs\n", __func__);
688                 res = -ENOENT;
689                 goto err;
690         }
691 
692         if (!devm_request_mem_region(&pdev->dev,
693                                      r->start,
694                                      r->end - r->start + 1,
695                                      pdata->name)) {
696                 printk(KERN_ERR "%s: Error while requesting mem region\n",
697                        __func__);
698                 res = -EBUSY;
699                 goto err;
700         }
701 
702         pdata->mc_vbase = devm_ioremap(&pdev->dev,
703                                        r->start,
704                                        r->end - r->start + 1);
705         if (!pdata->mc_vbase) {
706                 printk(KERN_ERR "%s: Unable to setup MC err regs\n", __func__);
707                 res = -ENOMEM;
708                 goto err;
709         }
710 
711         ctl = in_le32(pdata->mc_vbase + MV64X60_SDRAM_CONFIG);
712         if (!(ctl & MV64X60_SDRAM_ECC)) {
713                 /* Non-ECC RAM? */
714                 printk(KERN_WARNING "%s: No ECC DIMMs discovered\n", __func__);
715                 res = -ENODEV;
716                 goto err2;
717         }
718 
719         debugf3("%s(): init mci\n", __func__);
720         mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_DDR;
721         mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
722         mci->edac_cap = EDAC_FLAG_SECDED;
723         mci->mod_name = EDAC_MOD_STR;
724         mci->mod_ver = MV64x60_REVISION;
725         mci->ctl_name = mv64x60_ctl_name;
726 
727         if (edac_op_state == EDAC_OPSTATE_POLL)
728                 mci->edac_check = mv64x60_mc_check;
729 
730         mci->ctl_page_to_phys = NULL;
731 
732         mci->scrub_mode = SCRUB_SW_SRC;
733 
734         mv64x60_init_csrows(mci, pdata);
735 
736         /* setup MC registers */
737         out_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR, 0);
738         ctl = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CNTL);
739         ctl = (ctl & 0xff00ffff) | 0x10000;
740         out_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CNTL, ctl);
741 
742         if (edac_mc_add_mc(mci)) {
743                 debugf3("%s(): failed edac_mc_add_mc()\n", __func__);
744                 goto err;
745         }
746 
747         if (edac_op_state == EDAC_OPSTATE_INT) {
748                 /* acquire interrupt that reports errors */
749                 pdata->irq = platform_get_irq(pdev, 0);
750                 res = devm_request_irq(&pdev->dev,
751                                        pdata->irq,
752                                        mv64x60_mc_isr,
753                                        IRQF_DISABLED,
754                                        "[EDAC] MC err",
755                                        mci);
756                 if (res < 0) {
757                         printk(KERN_ERR "%s: Unable to request irq %d for "
758                                "MV64x60 DRAM ERR\n", __func__, pdata->irq);
759                         res = -ENODEV;
760                         goto err2;
761                 }
762 
763                 printk(KERN_INFO EDAC_MOD_STR " acquired irq %d for MC Err\n",
764                        pdata->irq);
765         }
766 
767         /* get this far and it's successful */
768         debugf3("%s(): success\n", __func__);
769 
770         return 0;
771 
772 err2:
773         edac_mc_del_mc(&pdev->dev);
774 err:
775         devres_release_group(&pdev->dev, mv64x60_mc_err_probe);
776         edac_mc_free(mci);
777         return res;
778 }
779 
780 static int mv64x60_mc_err_remove(struct platform_device *pdev)
781 {
782         struct mem_ctl_info *mci = platform_get_drvdata(pdev);
783 
784         debugf0("%s()\n", __func__);
785 
786         edac_mc_del_mc(&pdev->dev);
787         edac_mc_free(mci);
788         return 0;
789 }
790 
791 static struct platform_driver mv64x60_mc_err_driver = {
792         .probe = mv64x60_mc_err_probe,
793         .remove = mv64x60_mc_err_remove,
794         .driver = {
795                    .name = "mv64x60_mc_err",
796         }
797 };
798 
799 static int __init mv64x60_edac_init(void)
800 {
801         int ret = 0;
802 
803         printk(KERN_INFO "Marvell MV64x60 EDAC driver " MV64x60_REVISION "\n");
804         printk(KERN_INFO "\t(C) 2006-2007 MontaVista Software\n");
805         /* make sure error reporting method is sane */
806         switch (edac_op_state) {
807         case EDAC_OPSTATE_POLL:
808         case EDAC_OPSTATE_INT:
809                 break;
810         default:
811                 edac_op_state = EDAC_OPSTATE_INT;
812                 break;
813         }
814 
815         ret = platform_driver_register(&mv64x60_mc_err_driver);
816         if (ret)
817                 printk(KERN_WARNING EDAC_MOD_STR "MC err failed to register\n");
818 
819         ret = platform_driver_register(&mv64x60_cpu_err_driver);
820         if (ret)
821                 printk(KERN_WARNING EDAC_MOD_STR
822                         "CPU err failed to register\n");
823 
824         ret = platform_driver_register(&mv64x60_sram_err_driver);
825         if (ret)
826                 printk(KERN_WARNING EDAC_MOD_STR
827                         "SRAM err failed to register\n");
828 
829 #ifdef CONFIG_PCI
830         ret = platform_driver_register(&mv64x60_pci_err_driver);
831         if (ret)
832                 printk(KERN_WARNING EDAC_MOD_STR
833                         "PCI err failed to register\n");
834 #endif
835 
836         return ret;
837 }
838 module_init(mv64x60_edac_init);
839 
840 static void __exit mv64x60_edac_exit(void)
841 {
842 #ifdef CONFIG_PCI
843         platform_driver_unregister(&mv64x60_pci_err_driver);
844 #endif
845         platform_driver_unregister(&mv64x60_sram_err_driver);
846         platform_driver_unregister(&mv64x60_cpu_err_driver);
847         platform_driver_unregister(&mv64x60_mc_err_driver);
848 }
849 module_exit(mv64x60_edac_exit);
850 
851 MODULE_LICENSE("GPL");
852 MODULE_AUTHOR("Montavista Software, Inc.");
853 module_param(edac_op_state, int, 0444);
854 MODULE_PARM_DESC(edac_op_state,
855                  "EDAC Error Reporting state: 0=Poll, 2=Interrupt");
856 
  This page was automatically generated by the LXR engine.