2 * Copyright 2011 Tilera Corporation. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation, version 2.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
11 * NON INFRINGEMENT. See the GNU General Public License for
13 * Tilera-specific EDAC driver.
15 * This source code is derived from the following driver:
17 * Cell MIC driver for ECC counting
19 * Copyright 2007 Benjamin Herrenschmidt, IBM Corp.
20 * <benh@kernel.crashing.org>
24 #include <linux/module.h>
25 #include <linux/init.h>
26 #include <linux/platform_device.h>
28 #include <linux/uaccess.h>
29 #include <linux/edac.h>
30 #include <hv/hypervisor.h>
31 #include <hv/drv_mshim_intf.h>
33 #include "edac_core.h"
35 #define DRV_NAME "tile-edac"
37 /* Number of cs_rows needed per memory controller on TILEPro. */
38 #define TILE_EDAC_NR_CSROWS 1
40 /* Number of channels per memory controller on TILEPro. */
41 #define TILE_EDAC_NR_CHANS 1
43 /* Granularity of reported error in bytes on TILEPro. */
44 #define TILE_EDAC_ERROR_GRAIN 8
46 /* TILE processor has multiple independent memory controllers. */
47 struct platform_device
*mshim_pdev
[TILE_MAX_MSHIMS
];
49 struct tile_edac_priv
{
50 int hv_devhdl
; /* Hypervisor device handle. */
51 int node
; /* Memory controller instance #. */
52 unsigned int ce_count
; /*
53 * Correctable-error counter
58 static void tile_edac_check(struct mem_ctl_info
*mci
)
60 struct tile_edac_priv
*priv
= mci
->pvt_info
;
61 struct mshim_mem_error mem_error
;
63 if (hv_dev_pread(priv
->hv_devhdl
, 0, (HV_VirtAddr
)&mem_error
,
64 sizeof(struct mshim_mem_error
), MSHIM_MEM_ERROR_OFF
) !=
65 sizeof(struct mshim_mem_error
)) {
66 pr_err(DRV_NAME
": MSHIM_MEM_ERROR_OFF pread failure.\n");
70 /* Check if the current error count is different from the saved one. */
71 if (mem_error
.sbe_count
!= priv
->ce_count
) {
72 dev_dbg(mci
->dev
, "ECC CE err on node %d\n", priv
->node
);
73 priv
->ce_count
= mem_error
.sbe_count
;
74 edac_mc_handle_ce(mci
, 0, 0, 0, 0, 0, mci
->ctl_name
);
79 * Initialize the 'csrows' table within the mci control structure with the
80 * addressing of memory.
82 static int __devinit
tile_edac_init_csrows(struct mem_ctl_info
*mci
)
84 struct csrow_info
*csrow
= &mci
->csrows
[0];
85 struct tile_edac_priv
*priv
= mci
->pvt_info
;
86 struct mshim_mem_info mem_info
;
88 if (hv_dev_pread(priv
->hv_devhdl
, 0, (HV_VirtAddr
)&mem_info
,
89 sizeof(struct mshim_mem_info
), MSHIM_MEM_INFO_OFF
) !=
90 sizeof(struct mshim_mem_info
)) {
91 pr_err(DRV_NAME
": MSHIM_MEM_INFO_OFF pread failure.\n");
96 csrow
->edac_mode
= EDAC_SECDED
;
98 csrow
->edac_mode
= EDAC_NONE
;
99 switch (mem_info
.mem_type
) {
101 csrow
->mtype
= MEM_DDR2
;
105 csrow
->mtype
= MEM_DDR3
;
112 csrow
->first_page
= 0;
113 csrow
->nr_pages
= mem_info
.mem_size
>> PAGE_SHIFT
;
114 csrow
->last_page
= csrow
->first_page
+ csrow
->nr_pages
- 1;
115 csrow
->grain
= TILE_EDAC_ERROR_GRAIN
;
116 csrow
->dtype
= DEV_UNKNOWN
;
121 static int __devinit
tile_edac_mc_probe(struct platform_device
*pdev
)
125 struct mem_ctl_info
*mci
;
126 struct tile_edac_priv
*priv
;
129 sprintf(hv_file
, "mshim/%d", pdev
->id
);
130 hv_devhdl
= hv_dev_open((HV_VirtAddr
)hv_file
, 0);
134 /* A TILE MC has a single channel and one chip-select row. */
135 mci
= edac_mc_alloc(sizeof(struct tile_edac_priv
),
136 TILE_EDAC_NR_CSROWS
, TILE_EDAC_NR_CHANS
, pdev
->id
);
139 priv
= mci
->pvt_info
;
140 priv
->node
= pdev
->id
;
141 priv
->hv_devhdl
= hv_devhdl
;
143 mci
->dev
= &pdev
->dev
;
144 mci
->mtype_cap
= MEM_FLAG_DDR2
;
145 mci
->edac_ctl_cap
= EDAC_FLAG_SECDED
;
147 mci
->mod_name
= DRV_NAME
;
148 mci
->ctl_name
= "TILEPro_Memory_Controller";
149 mci
->dev_name
= dev_name(&pdev
->dev
);
150 mci
->edac_check
= tile_edac_check
;
153 * Initialize the MC control structure 'csrows' table
154 * with the mapping and control information.
156 if (tile_edac_init_csrows(mci
)) {
157 /* No csrows found. */
158 mci
->edac_cap
= EDAC_FLAG_NONE
;
160 mci
->edac_cap
= EDAC_FLAG_SECDED
;
163 platform_set_drvdata(pdev
, mci
);
165 /* Register with EDAC core */
166 rc
= edac_mc_add_mc(mci
);
168 dev_err(&pdev
->dev
, "failed to register with EDAC core\n");
176 static int __devexit
tile_edac_mc_remove(struct platform_device
*pdev
)
178 struct mem_ctl_info
*mci
= platform_get_drvdata(pdev
);
180 edac_mc_del_mc(&pdev
->dev
);
186 static struct platform_driver tile_edac_mc_driver
= {
189 .owner
= THIS_MODULE
,
191 .probe
= tile_edac_mc_probe
,
192 .remove
= __devexit_p(tile_edac_mc_remove
),
196 * Driver init routine.
198 static int __init
tile_edac_init(void)
201 struct platform_device
*pdev
;
204 /* Only support POLL mode. */
205 edac_op_state
= EDAC_OPSTATE_POLL
;
207 err
= platform_driver_register(&tile_edac_mc_driver
);
211 for (i
= 0; i
< TILE_MAX_MSHIMS
; i
++) {
213 * Not all memory controllers are configured such as in the
214 * case of a simulator. So we register only those mshims
215 * that are configured by the hypervisor.
217 sprintf(hv_file
, "mshim/%d", i
);
218 if (hv_dev_open((HV_VirtAddr
)hv_file
, 0) < 0)
221 pdev
= platform_device_register_simple(DRV_NAME
, i
, NULL
, 0);
224 mshim_pdev
[i
] = pdev
;
229 platform_driver_unregister(&tile_edac_mc_driver
);
236 * Driver cleanup routine.
238 static void __exit
tile_edac_exit(void)
242 for (i
= 0; i
< TILE_MAX_MSHIMS
; i
++) {
243 struct platform_device
*pdev
= mshim_pdev
[i
];
247 platform_set_drvdata(pdev
, NULL
);
248 platform_device_unregister(pdev
);
250 platform_driver_unregister(&tile_edac_mc_driver
);
253 module_init(tile_edac_init
);
254 module_exit(tile_edac_exit
);