mv64x60_edac.c 22 KB

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