Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
1446f17a
K
Kernel
项目概览
openeuler
/
Kernel
1 年多 前同步成功
通知
8
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
1446f17a
编写于
11月 16, 2013
作者:
B
Borislav Petkov
浏览文件
操作
浏览文件
下载
差异文件
Merge tag 'edac_calxeda_for_3.13' into edac-for-3.13
Pull Calxeda Highbank stuff from Robert Richter.
上级
959f5854
78cfbf0b
变更
10
隐藏空白更改
内联
并排
Showing
10 changed file
with
151 addition
and
110 deletion
+151
-110
Documentation/devicetree/bindings/arm/calxeda/mem-ctrlr.txt
Documentation/devicetree/bindings/arm/calxeda/mem-ctrlr.txt
+3
-1
MAINTAINERS
MAINTAINERS
+8
-0
arch/arm/boot/dts/ecx-2000.dts
arch/arm/boot/dts/ecx-2000.dts
+6
-0
arch/arm/boot/dts/ecx-common.dtsi
arch/arm/boot/dts/ecx-common.dtsi
+0
-6
arch/arm/boot/dts/highbank.dts
arch/arm/boot/dts/highbank.dts
+6
-0
drivers/edac/edac_device.c
drivers/edac/edac_device.c
+3
-6
drivers/edac/edac_mc.c
drivers/edac/edac_mc.c
+4
-2
drivers/edac/edac_pci.c
drivers/edac/edac_pci.c
+3
-5
drivers/edac/highbank_l2_edac.c
drivers/edac/highbank_l2_edac.c
+19
-14
drivers/edac/highbank_mc_edac.c
drivers/edac/highbank_mc_edac.c
+99
-76
未找到文件。
Documentation/devicetree/bindings/arm/calxeda/mem-ctrlr.txt
浏览文件 @
1446f17a
Calxeda DDR memory controller
Properties:
- compatible : Should be "calxeda,hb-ddr-ctrl"
- compatible : Should be:
- "calxeda,hb-ddr-ctrl" for ECX-1000
- "calxeda,ecx-2000-ddr-ctrl" for ECX-2000
- reg : Address and size for DDR controller registers.
- interrupts : Interrupt for DDR controller.
...
...
MAINTAINERS
浏览文件 @
1446f17a
...
...
@@ -3047,6 +3047,14 @@ W: bluesmoke.sourceforge.net
S: Maintained
F: drivers/edac/amd64_edac*
EDAC-CALXEDA
M: Doug Thompson <dougthompson@xmission.com>
M: Robert Richter <rric@kernel.org>
L: linux-edac@vger.kernel.org
W: bluesmoke.sourceforge.net
S: Maintained
F: drivers/edac/highbank*
EDAC-CAVIUM
M: Ralf Baechle <ralf@linux-mips.org>
M: David Daney <david.daney@cavium.com>
...
...
arch/arm/boot/dts/ecx-2000.dts
浏览文件 @
1446f17a
...
...
@@ -85,6 +85,12 @@
<
1
10
0xf08
>;
};
memory
-
controller
@
fff00000
{
compatible
=
"calxeda,ecx-2000-ddr-ctrl"
;
reg
=
<
0xfff00000
0x1000
>;
interrupts
=
<
0
91
4
>;
};
intc
:
interrupt
-
controller
@
fff11000
{
compatible
=
"arm,cortex-a15-gic"
;
#
interrupt
-
cells
=
<
3
>;
...
...
arch/arm/boot/dts/ecx-common.dtsi
浏览文件 @
1446f17a
...
...
@@ -45,12 +45,6 @@
status = "disabled";
};
memory-controller@fff00000 {
compatible = "calxeda,hb-ddr-ctrl";
reg = <0xfff00000 0x1000>;
interrupts = <0 91 4>;
};
ipc@fff20000 {
compatible = "arm,pl320", "arm,primecell";
reg = <0xfff20000 0x1000>;
...
...
arch/arm/boot/dts/highbank.dts
浏览文件 @
1446f17a
...
...
@@ -86,6 +86,12 @@
soc
{
ranges
=
<
0x00000000
0x00000000
0xffffffff
>;
memory
-
controller
@
fff00000
{
compatible
=
"calxeda,hb-ddr-ctrl"
;
reg
=
<
0xfff00000
0x1000
>;
interrupts
=
<
0
91
4
>;
};
timer
@
fff10600
{
compatible
=
"arm,cortex-a9-twd-timer"
;
reg
=
<
0xfff10600
0x20
>;
...
...
drivers/edac/edac_device.c
浏览文件 @
1446f17a
...
...
@@ -530,12 +530,9 @@ int edac_device_add_device(struct edac_device_ctl_info *edac_dev)
/* Report action taken */
edac_device_printk
(
edac_dev
,
KERN_INFO
,
"Giving out device to module '%s' controller "
"'%s': DEV '%s' (%s)
\n
"
,
edac_dev
->
mod_name
,
edac_dev
->
ctl_name
,
edac_dev_name
(
edac_dev
),
edac_op_state_to_string
(
edac_dev
->
op_state
));
"Giving out device to module %s controller %s: DEV %s (%s)
\n
"
,
edac_dev
->
mod_name
,
edac_dev
->
ctl_name
,
edac_dev
->
dev_name
,
edac_op_state_to_string
(
edac_dev
->
op_state
));
mutex_unlock
(
&
device_ctls_mutex
);
return
0
;
...
...
drivers/edac/edac_mc.c
浏览文件 @
1446f17a
...
...
@@ -788,8 +788,10 @@ int edac_mc_add_mc(struct mem_ctl_info *mci)
}
/* Report action taken */
edac_mc_printk
(
mci
,
KERN_INFO
,
"Giving out device to '%s' '%s':"
" DEV %s
\n
"
,
mci
->
mod_name
,
mci
->
ctl_name
,
edac_dev_name
(
mci
));
edac_mc_printk
(
mci
,
KERN_INFO
,
"Giving out device to module %s controller %s: DEV %s (%s)
\n
"
,
mci
->
mod_name
,
mci
->
ctl_name
,
mci
->
dev_name
,
edac_op_state_to_string
(
mci
->
op_state
));
edac_mc_owner
=
mci
->
mod_name
;
...
...
drivers/edac/edac_pci.c
浏览文件 @
1446f17a
...
...
@@ -358,11 +358,9 @@ int edac_pci_add_device(struct edac_pci_ctl_info *pci, int edac_idx)
}
edac_pci_printk
(
pci
,
KERN_INFO
,
"Giving out device to module '%s' controller '%s':"
" DEV '%s' (%s)
\n
"
,
pci
->
mod_name
,
pci
->
ctl_name
,
edac_dev_name
(
pci
),
edac_op_state_to_string
(
pci
->
op_state
));
"Giving out device to module %s controller %s: DEV %s (%s)
\n
"
,
pci
->
mod_name
,
pci
->
ctl_name
,
pci
->
dev_name
,
edac_op_state_to_string
(
pci
->
op_state
));
mutex_unlock
(
&
edac_pci_ctls_mutex
);
return
0
;
...
...
drivers/edac/highbank_l2_edac.c
浏览文件 @
1446f17a
...
...
@@ -50,8 +50,15 @@ static irqreturn_t highbank_l2_err_handler(int irq, void *dev_id)
return
IRQ_HANDLED
;
}
static
const
struct
of_device_id
hb_l2_err_of_match
[]
=
{
{
.
compatible
=
"calxeda,hb-sregs-l2-ecc"
,
},
{},
};
MODULE_DEVICE_TABLE
(
of
,
hb_l2_err_of_match
);
static
int
highbank_l2_err_probe
(
struct
platform_device
*
pdev
)
{
const
struct
of_device_id
*
id
;
struct
edac_device_ctl_info
*
dci
;
struct
hb_l2_drvdata
*
drvdata
;
struct
resource
*
r
;
...
...
@@ -90,28 +97,32 @@ static int highbank_l2_err_probe(struct platform_device *pdev)
goto
err
;
}
id
=
of_match_device
(
hb_l2_err_of_match
,
&
pdev
->
dev
);
dci
->
mod_name
=
pdev
->
dev
.
driver
->
name
;
dci
->
ctl_name
=
id
?
id
->
compatible
:
"unknown"
;
dci
->
dev_name
=
dev_name
(
&
pdev
->
dev
);
if
(
edac_device_add_device
(
dci
))
goto
err
;
drvdata
->
db_irq
=
platform_get_irq
(
pdev
,
0
);
res
=
devm_request_irq
(
&
pdev
->
dev
,
drvdata
->
db_irq
,
highbank_l2_err_handler
,
0
,
dev_name
(
&
pdev
->
dev
),
dci
);
if
(
res
<
0
)
goto
err
;
goto
err
2
;
drvdata
->
sb_irq
=
platform_get_irq
(
pdev
,
1
);
res
=
devm_request_irq
(
&
pdev
->
dev
,
drvdata
->
sb_irq
,
highbank_l2_err_handler
,
0
,
dev_name
(
&
pdev
->
dev
),
dci
);
if
(
res
<
0
)
goto
err
;
dci
->
mod_name
=
dev_name
(
&
pdev
->
dev
);
dci
->
dev_name
=
dev_name
(
&
pdev
->
dev
);
if
(
edac_device_add_device
(
dci
))
goto
err
;
goto
err2
;
devres_close_group
(
&
pdev
->
dev
,
NULL
);
return
0
;
err2:
edac_device_del_device
(
&
pdev
->
dev
);
err:
devres_release_group
(
&
pdev
->
dev
,
NULL
);
edac_device_free_ctl_info
(
dci
);
...
...
@@ -127,12 +138,6 @@ static int highbank_l2_err_remove(struct platform_device *pdev)
return
0
;
}
static
const
struct
of_device_id
hb_l2_err_of_match
[]
=
{
{
.
compatible
=
"calxeda,hb-sregs-l2-ecc"
,
},
{},
};
MODULE_DEVICE_TABLE
(
of
,
hb_l2_err_of_match
);
static
struct
platform_driver
highbank_l2_edac_driver
=
{
.
probe
=
highbank_l2_err_probe
,
.
remove
=
highbank_l2_err_remove
,
...
...
drivers/edac/highbank_mc_edac.c
浏览文件 @
1446f17a
...
...
@@ -26,31 +26,40 @@
#include "edac_module.h"
/* DDR Ctrlr Error Registers */
#define HB_DDR_ECC_OPT 0x128
#define HB_DDR_ECC_U_ERR_ADDR 0x130
#define HB_DDR_ECC_U_ERR_STAT 0x134
#define HB_DDR_ECC_U_ERR_DATAL 0x138
#define HB_DDR_ECC_U_ERR_DATAH 0x13c
#define HB_DDR_ECC_C_ERR_ADDR 0x140
#define HB_DDR_ECC_C_ERR_STAT 0x144
#define HB_DDR_ECC_C_ERR_DATAL 0x148
#define HB_DDR_ECC_C_ERR_DATAH 0x14c
#define HB_DDR_ECC_INT_STATUS 0x180
#define HB_DDR_ECC_INT_ACK 0x184
#define HB_DDR_ECC_U_ERR_ID 0x424
#define HB_DDR_ECC_C_ERR_ID 0x428
#define HB_DDR_ECC_INT_STAT_CE 0x8
#define HB_DDR_ECC_INT_STAT_DOUBLE_CE 0x10
#define HB_DDR_ECC_INT_STAT_UE 0x20
#define HB_DDR_ECC_INT_STAT_DOUBLE_UE 0x40
#define HB_DDR_ECC_ERR_BASE 0x128
#define MW_DDR_ECC_ERR_BASE 0x1b4
#define HB_DDR_ECC_OPT 0x00
#define HB_DDR_ECC_U_ERR_ADDR 0x08
#define HB_DDR_ECC_U_ERR_STAT 0x0c
#define HB_DDR_ECC_U_ERR_DATAL 0x10
#define HB_DDR_ECC_U_ERR_DATAH 0x14
#define HB_DDR_ECC_C_ERR_ADDR 0x18
#define HB_DDR_ECC_C_ERR_STAT 0x1c
#define HB_DDR_ECC_C_ERR_DATAL 0x20
#define HB_DDR_ECC_C_ERR_DATAH 0x24
#define HB_DDR_ECC_OPT_MODE_MASK 0x3
#define HB_DDR_ECC_OPT_FWC 0x100
#define HB_DDR_ECC_OPT_XOR_SHIFT 16
/* DDR Ctrlr Interrupt Registers */
#define HB_DDR_ECC_INT_BASE 0x180
#define MW_DDR_ECC_INT_BASE 0x218
#define HB_DDR_ECC_INT_STATUS 0x00
#define HB_DDR_ECC_INT_ACK 0x04
#define HB_DDR_ECC_INT_STAT_CE 0x8
#define HB_DDR_ECC_INT_STAT_DOUBLE_CE 0x10
#define HB_DDR_ECC_INT_STAT_UE 0x20
#define HB_DDR_ECC_INT_STAT_DOUBLE_UE 0x40
struct
hb_mc_drvdata
{
void
__iomem
*
mc_vbase
;
void
__iomem
*
mc_err_base
;
void
__iomem
*
mc_int_base
;
};
static
irqreturn_t
highbank_mc_err_handler
(
int
irq
,
void
*
dev_id
)
...
...
@@ -60,10 +69,10 @@ static irqreturn_t highbank_mc_err_handler(int irq, void *dev_id)
u32
status
,
err_addr
;
/* Read the interrupt status register */
status
=
readl
(
drvdata
->
mc_
v
base
+
HB_DDR_ECC_INT_STATUS
);
status
=
readl
(
drvdata
->
mc_
int_
base
+
HB_DDR_ECC_INT_STATUS
);
if
(
status
&
HB_DDR_ECC_INT_STAT_UE
)
{
err_addr
=
readl
(
drvdata
->
mc_
v
base
+
HB_DDR_ECC_U_ERR_ADDR
);
err_addr
=
readl
(
drvdata
->
mc_
err_
base
+
HB_DDR_ECC_U_ERR_ADDR
);
edac_mc_handle_error
(
HW_EVENT_ERR_UNCORRECTED
,
mci
,
1
,
err_addr
>>
PAGE_SHIFT
,
err_addr
&
~
PAGE_MASK
,
0
,
...
...
@@ -71,9 +80,9 @@ static irqreturn_t highbank_mc_err_handler(int irq, void *dev_id)
mci
->
ctl_name
,
""
);
}
if
(
status
&
HB_DDR_ECC_INT_STAT_CE
)
{
u32
syndrome
=
readl
(
drvdata
->
mc_
v
base
+
HB_DDR_ECC_C_ERR_STAT
);
u32
syndrome
=
readl
(
drvdata
->
mc_
err_
base
+
HB_DDR_ECC_C_ERR_STAT
);
syndrome
=
(
syndrome
>>
8
)
&
0xff
;
err_addr
=
readl
(
drvdata
->
mc_
v
base
+
HB_DDR_ECC_C_ERR_ADDR
);
err_addr
=
readl
(
drvdata
->
mc_
err_
base
+
HB_DDR_ECC_C_ERR_ADDR
);
edac_mc_handle_error
(
HW_EVENT_ERR_CORRECTED
,
mci
,
1
,
err_addr
>>
PAGE_SHIFT
,
err_addr
&
~
PAGE_MASK
,
syndrome
,
...
...
@@ -82,66 +91,79 @@ static irqreturn_t highbank_mc_err_handler(int irq, void *dev_id)
}
/* clear the error, clears the interrupt */
writel
(
status
,
drvdata
->
mc_
v
base
+
HB_DDR_ECC_INT_ACK
);
writel
(
status
,
drvdata
->
mc_
int_
base
+
HB_DDR_ECC_INT_ACK
);
return
IRQ_HANDLED
;
}
#ifdef CONFIG_EDAC_DEBUG
static
ssize_t
highbank_mc_err_inject_write
(
struct
file
*
file
,
const
char
__user
*
data
,
size_t
count
,
loff_t
*
ppos
)
static
void
highbank_mc_err_inject
(
struct
mem_ctl_info
*
mci
,
u8
synd
)
{
struct
mem_ctl_info
*
mci
=
file
->
private_data
;
struct
hb_mc_drvdata
*
pdata
=
mci
->
pvt_info
;
char
buf
[
32
];
size_t
buf_size
;
u32
reg
;
reg
=
readl
(
pdata
->
mc_err_base
+
HB_DDR_ECC_OPT
);
reg
&=
HB_DDR_ECC_OPT_MODE_MASK
;
reg
|=
(
synd
<<
HB_DDR_ECC_OPT_XOR_SHIFT
)
|
HB_DDR_ECC_OPT_FWC
;
writel
(
reg
,
pdata
->
mc_err_base
+
HB_DDR_ECC_OPT
);
}
#define to_mci(k) container_of(k, struct mem_ctl_info, dev)
static
ssize_t
highbank_mc_inject_ctrl
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
count
)
{
struct
mem_ctl_info
*
mci
=
to_mci
(
dev
);
u8
synd
;
buf_size
=
min
(
count
,
(
sizeof
(
buf
)
-
1
));
if
(
copy_from_user
(
buf
,
data
,
buf_size
))
return
-
EFAULT
;
buf
[
buf_size
]
=
0
;
if
(
kstrtou8
(
buf
,
16
,
&
synd
))
return
-
EINVAL
;
if
(
!
kstrtou8
(
buf
,
16
,
&
synd
))
{
reg
=
readl
(
pdata
->
mc_vbase
+
HB_DDR_ECC_OPT
);
reg
&=
HB_DDR_ECC_OPT_MODE_MASK
;
reg
|=
(
synd
<<
HB_DDR_ECC_OPT_XOR_SHIFT
)
|
HB_DDR_ECC_OPT_FWC
;
writel
(
reg
,
pdata
->
mc_vbase
+
HB_DDR_ECC_OPT
);
}
highbank_mc_err_inject
(
mci
,
synd
);
return
count
;
}
static
const
struct
file_operations
highbank_mc_debug_inject_fops
=
{
.
open
=
simple_open
,
.
write
=
highbank_mc_err_inject_write
,
.
llseek
=
generic_file_llseek
,
static
DEVICE_ATTR
(
inject_ctrl
,
S_IWUSR
,
NULL
,
highbank_mc_inject_ctrl
);
struct
hb_mc_settings
{
int
err_offset
;
int
int_offset
;
};
static
void
highbank_mc_create_debugfs_nodes
(
struct
mem_ctl_info
*
mci
)
{
if
(
mci
->
debugfs
)
debugfs_create_file
(
"inject_ctrl"
,
S_IWUSR
,
mci
->
debugfs
,
mci
,
&
highbank_mc_debug_inject_fops
);
;
}
#else
static
void
highbank_mc_create_debugfs_nodes
(
struct
mem_ctl_info
*
mci
)
{}
#endif
static
struct
hb_mc_settings
hb_settings
=
{
.
err_offset
=
HB_DDR_ECC_ERR_BASE
,
.
int_offset
=
HB_DDR_ECC_INT_BASE
,
};
static
struct
hb_mc_settings
mw_settings
=
{
.
err_offset
=
MW_DDR_ECC_ERR_BASE
,
.
int_offset
=
MW_DDR_ECC_INT_BASE
,
};
static
struct
of_device_id
hb_ddr_ctrl_of_match
[]
=
{
{
.
compatible
=
"calxeda,hb-ddr-ctrl"
,
.
data
=
&
hb_settings
},
{
.
compatible
=
"calxeda,ecx-2000-ddr-ctrl"
,
.
data
=
&
mw_settings
},
{},
};
MODULE_DEVICE_TABLE
(
of
,
hb_ddr_ctrl_of_match
);
static
int
highbank_mc_probe
(
struct
platform_device
*
pdev
)
{
const
struct
of_device_id
*
id
;
const
struct
hb_mc_settings
*
settings
;
struct
edac_mc_layer
layers
[
2
];
struct
mem_ctl_info
*
mci
;
struct
hb_mc_drvdata
*
drvdata
;
struct
dimm_info
*
dimm
;
struct
resource
*
r
;
void
__iomem
*
base
;
u32
control
;
int
irq
;
int
res
=
0
;
id
=
of_match_device
(
hb_ddr_ctrl_of_match
,
&
pdev
->
dev
);
if
(
!
id
)
return
-
ENODEV
;
layers
[
0
].
type
=
EDAC_MC_LAYER_CHIP_SELECT
;
layers
[
0
].
size
=
1
;
layers
[
0
].
is_virt_csrow
=
true
;
...
...
@@ -174,35 +196,31 @@ static int highbank_mc_probe(struct platform_device *pdev)
goto
err
;
}
drvdata
->
mc_vbase
=
devm_ioremap
(
&
pdev
->
dev
,
r
->
start
,
resource_size
(
r
));
if
(
!
drvdata
->
mc_vbase
)
{
base
=
devm_ioremap
(
&
pdev
->
dev
,
r
->
start
,
resource_size
(
r
));
if
(
!
base
)
{
dev_err
(
&
pdev
->
dev
,
"Unable to map regs
\n
"
);
res
=
-
ENOMEM
;
goto
err
;
}
control
=
readl
(
drvdata
->
mc_vbase
+
HB_DDR_ECC_OPT
)
&
0x3
;
settings
=
id
->
data
;
drvdata
->
mc_err_base
=
base
+
settings
->
err_offset
;
drvdata
->
mc_int_base
=
base
+
settings
->
int_offset
;
control
=
readl
(
drvdata
->
mc_err_base
+
HB_DDR_ECC_OPT
)
&
0x3
;
if
(
!
control
||
(
control
==
0x2
))
{
dev_err
(
&
pdev
->
dev
,
"No ECC present, or ECC disabled
\n
"
);
res
=
-
ENODEV
;
goto
err
;
}
irq
=
platform_get_irq
(
pdev
,
0
);
res
=
devm_request_irq
(
&
pdev
->
dev
,
irq
,
highbank_mc_err_handler
,
0
,
dev_name
(
&
pdev
->
dev
),
mci
);
if
(
res
<
0
)
{
dev_err
(
&
pdev
->
dev
,
"Unable to request irq %d
\n
"
,
irq
);
goto
err
;
}
mci
->
mtype_cap
=
MEM_FLAG_DDR3
;
mci
->
edac_ctl_cap
=
EDAC_FLAG_NONE
|
EDAC_FLAG_SECDED
;
mci
->
edac_cap
=
EDAC_FLAG_SECDED
;
mci
->
mod_name
=
dev_name
(
&
pdev
->
dev
)
;
mci
->
mod_name
=
pdev
->
dev
.
driver
->
name
;
mci
->
mod_ver
=
"1"
;
mci
->
ctl_name
=
dev_name
(
&
pdev
->
dev
);
mci
->
ctl_name
=
id
->
compatible
;
mci
->
dev_name
=
dev_name
(
&
pdev
->
dev
);
mci
->
scrub_mode
=
SCRUB_SW_SRC
;
/* Only a single 4GB DIMM is supported */
...
...
@@ -217,10 +235,20 @@ static int highbank_mc_probe(struct platform_device *pdev)
if
(
res
<
0
)
goto
err
;
highbank_mc_create_debugfs_nodes
(
mci
);
irq
=
platform_get_irq
(
pdev
,
0
);
res
=
devm_request_irq
(
&
pdev
->
dev
,
irq
,
highbank_mc_err_handler
,
0
,
dev_name
(
&
pdev
->
dev
),
mci
);
if
(
res
<
0
)
{
dev_err
(
&
pdev
->
dev
,
"Unable to request irq %d
\n
"
,
irq
);
goto
err2
;
}
device_create_file
(
&
mci
->
dev
,
&
dev_attr_inject_ctrl
);
devres_close_group
(
&
pdev
->
dev
,
NULL
);
return
0
;
err2:
edac_mc_del_mc
(
&
pdev
->
dev
);
err:
devres_release_group
(
&
pdev
->
dev
,
NULL
);
edac_mc_free
(
mci
);
...
...
@@ -231,17 +259,12 @@ static int highbank_mc_remove(struct platform_device *pdev)
{
struct
mem_ctl_info
*
mci
=
platform_get_drvdata
(
pdev
);
device_remove_file
(
&
mci
->
dev
,
&
dev_attr_inject_ctrl
);
edac_mc_del_mc
(
&
pdev
->
dev
);
edac_mc_free
(
mci
);
return
0
;
}
static
const
struct
of_device_id
hb_ddr_ctrl_of_match
[]
=
{
{
.
compatible
=
"calxeda,hb-ddr-ctrl"
,
},
{},
};
MODULE_DEVICE_TABLE
(
of
,
hb_ddr_ctrl_of_match
);
static
struct
platform_driver
highbank_mc_edac_driver
=
{
.
probe
=
highbank_mc_probe
,
.
remove
=
highbank_mc_remove
,
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录