Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
1446f17a
Commit
1446f17a
authored
Nov 16, 2013
by
Borislav Petkov
Browse files
Options
Browse Files
Download
Plain Diff
Merge tag 'edac_calxeda_for_3.13' into edac-for-3.13
Pull Calxeda Highbank stuff from Robert Richter.
parents
959f5854
78cfbf0b
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
151 additions
and
110 deletions
+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
No files found.
Documentation/devicetree/bindings/arm/calxeda/mem-ctrlr.txt
View file @
1446f17a
Calxeda DDR memory controller
Calxeda DDR memory controller
Properties:
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.
- reg : Address and size for DDR controller registers.
- interrupts : Interrupt for DDR controller.
- interrupts : Interrupt for DDR controller.
...
...
MAINTAINERS
View file @
1446f17a
...
@@ -3047,6 +3047,14 @@ W: bluesmoke.sourceforge.net
...
@@ -3047,6 +3047,14 @@ W: bluesmoke.sourceforge.net
S: Maintained
S: Maintained
F: drivers/edac/amd64_edac*
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
EDAC-CAVIUM
M: Ralf Baechle <ralf@linux-mips.org>
M: Ralf Baechle <ralf@linux-mips.org>
M: David Daney <david.daney@cavium.com>
M: David Daney <david.daney@cavium.com>
...
...
arch/arm/boot/dts/ecx-2000.dts
View file @
1446f17a
...
@@ -85,6 +85,12 @@ timer {
...
@@ -85,6 +85,12 @@ timer {
<
1
10
0xf08
>;
<
1
10
0xf08
>;
};
};
memory
-
controller
@
fff00000
{
compatible
=
"calxeda,ecx-2000-ddr-ctrl"
;
reg
=
<
0xfff00000
0x1000
>;
interrupts
=
<
0
91
4
>;
};
intc
:
interrupt
-
controller
@
fff11000
{
intc
:
interrupt
-
controller
@
fff11000
{
compatible
=
"arm,cortex-a15-gic"
;
compatible
=
"arm,cortex-a15-gic"
;
#
interrupt
-
cells
=
<
3
>;
#
interrupt
-
cells
=
<
3
>;
...
...
arch/arm/boot/dts/ecx-common.dtsi
View file @
1446f17a
...
@@ -45,12 +45,6 @@ sdhci@ffe0e000 {
...
@@ -45,12 +45,6 @@ sdhci@ffe0e000 {
status = "disabled";
status = "disabled";
};
};
memory-controller@fff00000 {
compatible = "calxeda,hb-ddr-ctrl";
reg = <0xfff00000 0x1000>;
interrupts = <0 91 4>;
};
ipc@fff20000 {
ipc@fff20000 {
compatible = "arm,pl320", "arm,primecell";
compatible = "arm,pl320", "arm,primecell";
reg = <0xfff20000 0x1000>;
reg = <0xfff20000 0x1000>;
...
...
arch/arm/boot/dts/highbank.dts
View file @
1446f17a
...
@@ -86,6 +86,12 @@ memory {
...
@@ -86,6 +86,12 @@ memory {
soc
{
soc
{
ranges
=
<
0x00000000
0x00000000
0xffffffff
>;
ranges
=
<
0x00000000
0x00000000
0xffffffff
>;
memory
-
controller
@
fff00000
{
compatible
=
"calxeda,hb-ddr-ctrl"
;
reg
=
<
0xfff00000
0x1000
>;
interrupts
=
<
0
91
4
>;
};
timer
@
fff10600
{
timer
@
fff10600
{
compatible
=
"arm,cortex-a9-twd-timer"
;
compatible
=
"arm,cortex-a9-twd-timer"
;
reg
=
<
0xfff10600
0x20
>;
reg
=
<
0xfff10600
0x20
>;
...
...
drivers/edac/edac_device.c
View file @
1446f17a
...
@@ -530,12 +530,9 @@ int edac_device_add_device(struct edac_device_ctl_info *edac_dev)
...
@@ -530,12 +530,9 @@ int edac_device_add_device(struct edac_device_ctl_info *edac_dev)
/* Report action taken */
/* Report action taken */
edac_device_printk
(
edac_dev
,
KERN_INFO
,
edac_device_printk
(
edac_dev
,
KERN_INFO
,
"Giving out device to module '%s' controller "
"Giving out device to module %s controller %s: DEV %s (%s)
\n
"
,
"'%s': DEV '%s' (%s)
\n
"
,
edac_dev
->
mod_name
,
edac_dev
->
ctl_name
,
edac_dev
->
dev_name
,
edac_dev
->
mod_name
,
edac_op_state_to_string
(
edac_dev
->
op_state
));
edac_dev
->
ctl_name
,
edac_dev_name
(
edac_dev
),
edac_op_state_to_string
(
edac_dev
->
op_state
));
mutex_unlock
(
&
device_ctls_mutex
);
mutex_unlock
(
&
device_ctls_mutex
);
return
0
;
return
0
;
...
...
drivers/edac/edac_mc.c
View file @
1446f17a
...
@@ -788,8 +788,10 @@ int edac_mc_add_mc(struct mem_ctl_info *mci)
...
@@ -788,8 +788,10 @@ int edac_mc_add_mc(struct mem_ctl_info *mci)
}
}
/* Report action taken */
/* Report action taken */
edac_mc_printk
(
mci
,
KERN_INFO
,
"Giving out device to '%s' '%s':"
edac_mc_printk
(
mci
,
KERN_INFO
,
" DEV %s
\n
"
,
mci
->
mod_name
,
mci
->
ctl_name
,
edac_dev_name
(
mci
));
"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
;
edac_mc_owner
=
mci
->
mod_name
;
...
...
drivers/edac/edac_pci.c
View file @
1446f17a
...
@@ -358,11 +358,9 @@ int edac_pci_add_device(struct edac_pci_ctl_info *pci, int edac_idx)
...
@@ -358,11 +358,9 @@ int edac_pci_add_device(struct edac_pci_ctl_info *pci, int edac_idx)
}
}
edac_pci_printk
(
pci
,
KERN_INFO
,
edac_pci_printk
(
pci
,
KERN_INFO
,
"Giving out device to module '%s' controller '%s':"
"Giving out device to module %s controller %s: DEV %s (%s)
\n
"
,
" DEV '%s' (%s)
\n
"
,
pci
->
mod_name
,
pci
->
ctl_name
,
pci
->
dev_name
,
pci
->
mod_name
,
edac_op_state_to_string
(
pci
->
op_state
));
pci
->
ctl_name
,
edac_dev_name
(
pci
),
edac_op_state_to_string
(
pci
->
op_state
));
mutex_unlock
(
&
edac_pci_ctls_mutex
);
mutex_unlock
(
&
edac_pci_ctls_mutex
);
return
0
;
return
0
;
...
...
drivers/edac/highbank_l2_edac.c
View file @
1446f17a
...
@@ -50,8 +50,15 @@ static irqreturn_t highbank_l2_err_handler(int irq, void *dev_id)
...
@@ -50,8 +50,15 @@ static irqreturn_t highbank_l2_err_handler(int irq, void *dev_id)
return
IRQ_HANDLED
;
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
)
static
int
highbank_l2_err_probe
(
struct
platform_device
*
pdev
)
{
{
const
struct
of_device_id
*
id
;
struct
edac_device_ctl_info
*
dci
;
struct
edac_device_ctl_info
*
dci
;
struct
hb_l2_drvdata
*
drvdata
;
struct
hb_l2_drvdata
*
drvdata
;
struct
resource
*
r
;
struct
resource
*
r
;
...
@@ -90,28 +97,32 @@ static int highbank_l2_err_probe(struct platform_device *pdev)
...
@@ -90,28 +97,32 @@ static int highbank_l2_err_probe(struct platform_device *pdev)
goto
err
;
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
);
drvdata
->
db_irq
=
platform_get_irq
(
pdev
,
0
);
res
=
devm_request_irq
(
&
pdev
->
dev
,
drvdata
->
db_irq
,
res
=
devm_request_irq
(
&
pdev
->
dev
,
drvdata
->
db_irq
,
highbank_l2_err_handler
,
highbank_l2_err_handler
,
0
,
dev_name
(
&
pdev
->
dev
),
dci
);
0
,
dev_name
(
&
pdev
->
dev
),
dci
);
if
(
res
<
0
)
if
(
res
<
0
)
goto
err
;
goto
err
2
;
drvdata
->
sb_irq
=
platform_get_irq
(
pdev
,
1
);
drvdata
->
sb_irq
=
platform_get_irq
(
pdev
,
1
);
res
=
devm_request_irq
(
&
pdev
->
dev
,
drvdata
->
sb_irq
,
res
=
devm_request_irq
(
&
pdev
->
dev
,
drvdata
->
sb_irq
,
highbank_l2_err_handler
,
highbank_l2_err_handler
,
0
,
dev_name
(
&
pdev
->
dev
),
dci
);
0
,
dev_name
(
&
pdev
->
dev
),
dci
);
if
(
res
<
0
)
if
(
res
<
0
)
goto
err
;
goto
err2
;
dci
->
mod_name
=
dev_name
(
&
pdev
->
dev
);
dci
->
dev_name
=
dev_name
(
&
pdev
->
dev
);
if
(
edac_device_add_device
(
dci
))
goto
err
;
devres_close_group
(
&
pdev
->
dev
,
NULL
);
devres_close_group
(
&
pdev
->
dev
,
NULL
);
return
0
;
return
0
;
err2:
edac_device_del_device
(
&
pdev
->
dev
);
err:
err:
devres_release_group
(
&
pdev
->
dev
,
NULL
);
devres_release_group
(
&
pdev
->
dev
,
NULL
);
edac_device_free_ctl_info
(
dci
);
edac_device_free_ctl_info
(
dci
);
...
@@ -127,12 +138,6 @@ static int highbank_l2_err_remove(struct platform_device *pdev)
...
@@ -127,12 +138,6 @@ static int highbank_l2_err_remove(struct platform_device *pdev)
return
0
;
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
=
{
static
struct
platform_driver
highbank_l2_edac_driver
=
{
.
probe
=
highbank_l2_err_probe
,
.
probe
=
highbank_l2_err_probe
,
.
remove
=
highbank_l2_err_remove
,
.
remove
=
highbank_l2_err_remove
,
...
...
drivers/edac/highbank_mc_edac.c
View file @
1446f17a
...
@@ -26,31 +26,40 @@
...
@@ -26,31 +26,40 @@
#include "edac_module.h"
#include "edac_module.h"
/* DDR Ctrlr Error Registers */
/* 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_ERR_BASE 0x128
#define HB_DDR_ECC_INT_STAT_DOUBLE_CE 0x10
#define MW_DDR_ECC_ERR_BASE 0x1b4
#define HB_DDR_ECC_INT_STAT_UE 0x20
#define HB_DDR_ECC_INT_STAT_DOUBLE_UE 0x40
#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_MODE_MASK 0x3
#define HB_DDR_ECC_OPT_FWC 0x100
#define HB_DDR_ECC_OPT_FWC 0x100
#define HB_DDR_ECC_OPT_XOR_SHIFT 16
#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
{
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
)
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)
...
@@ -60,10 +69,10 @@ static irqreturn_t highbank_mc_err_handler(int irq, void *dev_id)
u32
status
,
err_addr
;
u32
status
,
err_addr
;
/* Read the interrupt status register */
/* 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
)
{
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
,
edac_mc_handle_error
(
HW_EVENT_ERR_UNCORRECTED
,
mci
,
1
,
err_addr
>>
PAGE_SHIFT
,
err_addr
>>
PAGE_SHIFT
,
err_addr
&
~
PAGE_MASK
,
0
,
err_addr
&
~
PAGE_MASK
,
0
,
...
@@ -71,9 +80,9 @@ static irqreturn_t highbank_mc_err_handler(int irq, void *dev_id)
...
@@ -71,9 +80,9 @@ static irqreturn_t highbank_mc_err_handler(int irq, void *dev_id)
mci
->
ctl_name
,
""
);
mci
->
ctl_name
,
""
);
}
}
if
(
status
&
HB_DDR_ECC_INT_STAT_CE
)
{
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
;
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
,
edac_mc_handle_error
(
HW_EVENT_ERR_CORRECTED
,
mci
,
1
,
err_addr
>>
PAGE_SHIFT
,
err_addr
>>
PAGE_SHIFT
,
err_addr
&
~
PAGE_MASK
,
syndrome
,
err_addr
&
~
PAGE_MASK
,
syndrome
,
...
@@ -82,66 +91,79 @@ static irqreturn_t highbank_mc_err_handler(int irq, void *dev_id)
...
@@ -82,66 +91,79 @@ static irqreturn_t highbank_mc_err_handler(int irq, void *dev_id)
}
}
/* clear the error, clears the interrupt */
/* 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
;
return
IRQ_HANDLED
;
}
}
#ifdef CONFIG_EDAC_DEBUG
static
void
highbank_mc_err_inject
(
struct
mem_ctl_info
*
mci
,
u8
synd
)
static
ssize_t
highbank_mc_err_inject_write
(
struct
file
*
file
,
const
char
__user
*
data
,
size_t
count
,
loff_t
*
ppos
)
{
{
struct
mem_ctl_info
*
mci
=
file
->
private_data
;
struct
hb_mc_drvdata
*
pdata
=
mci
->
pvt_info
;
struct
hb_mc_drvdata
*
pdata
=
mci
->
pvt_info
;
char
buf
[
32
];
size_t
buf_size
;
u32
reg
;
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
;
u8
synd
;
buf_size
=
min
(
count
,
(
sizeof
(
buf
)
-
1
));
if
(
kstrtou8
(
buf
,
16
,
&
synd
))
if
(
copy_from_user
(
buf
,
data
,
buf_size
))
return
-
EINVAL
;
return
-
EFAULT
;
buf
[
buf_size
]
=
0
;
if
(
!
kstrtou8
(
buf
,
16
,
&
synd
))
{
highbank_mc_err_inject
(
mci
,
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
);
}
return
count
;
return
count
;
}
}
static
const
struct
file_operations
highbank_mc_debug_inject_fops
=
{
static
DEVICE_ATTR
(
inject_ctrl
,
S_IWUSR
,
NULL
,
highbank_mc_inject_ctrl
);
.
open
=
simple_open
,
.
write
=
highbank_mc_err_inject_write
,
struct
hb_mc_settings
{
.
llseek
=
generic_file_llseek
,
int
err_offset
;
int
int_offset
;
};
};
static
void
highbank_mc_create_debugfs_nodes
(
struct
mem_ctl_info
*
mci
)
static
struct
hb_mc_settings
hb_settings
=
{
{
.
err_offset
=
HB_DDR_ECC_ERR_BASE
,
if
(
mci
->
debugfs
)
.
int_offset
=
HB_DDR_ECC_INT_BASE
,
debugfs_create_file
(
"inject_ctrl"
,
S_IWUSR
,
mci
->
debugfs
,
mci
,
};
&
highbank_mc_debug_inject_fops
);
;
static
struct
hb_mc_settings
mw_settings
=
{
}
.
err_offset
=
MW_DDR_ECC_ERR_BASE
,
#else
.
int_offset
=
MW_DDR_ECC_INT_BASE
,
static
void
highbank_mc_create_debugfs_nodes
(
struct
mem_ctl_info
*
mci
)
};
{}
#endif
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
)
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
edac_mc_layer
layers
[
2
];
struct
mem_ctl_info
*
mci
;
struct
mem_ctl_info
*
mci
;
struct
hb_mc_drvdata
*
drvdata
;
struct
hb_mc_drvdata
*
drvdata
;
struct
dimm_info
*
dimm
;
struct
dimm_info
*
dimm
;
struct
resource
*
r
;
struct
resource
*
r
;
void
__iomem
*
base
;
u32
control
;
u32
control
;
int
irq
;
int
irq
;
int
res
=
0
;
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
].
type
=
EDAC_MC_LAYER_CHIP_SELECT
;
layers
[
0
].
size
=
1
;
layers
[
0
].
size
=
1
;
layers
[
0
].
is_virt_csrow
=
true
;
layers
[
0
].
is_virt_csrow
=
true
;
...
@@ -174,35 +196,31 @@ static int highbank_mc_probe(struct platform_device *pdev)
...
@@ -174,35 +196,31 @@ static int highbank_mc_probe(struct platform_device *pdev)
goto
err
;
goto
err
;
}
}
drvdata
->
mc_vbase
=
devm_ioremap
(
&
pdev
->
dev
,
base
=
devm_ioremap
(
&
pdev
->
dev
,
r
->
start
,
resource_size
(
r
));
r
->
start
,
resource_size
(
r
));
if
(
!
base
)
{
if
(
!
drvdata
->
mc_vbase
)
{
dev_err
(
&
pdev
->
dev
,
"Unable to map regs
\n
"
);
dev_err
(
&
pdev
->
dev
,
"Unable to map regs
\n
"
);
res
=
-
ENOMEM
;
res
=
-
ENOMEM
;
goto
err
;
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
))
{
if
(
!
control
||
(
control
==
0x2
))
{
dev_err
(
&
pdev
->
dev
,
"No ECC present, or ECC disabled
\n
"
);
dev_err
(
&
pdev
->
dev
,
"No ECC present, or ECC disabled
\n
"
);
res
=
-
ENODEV
;
res
=
-
ENODEV
;
goto
err
;
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
->
mtype_cap
=
MEM_FLAG_DDR3
;
mci
->
edac_ctl_cap
=
EDAC_FLAG_NONE
|
EDAC_FLAG_SECDED
;
mci
->
edac_ctl_cap
=
EDAC_FLAG_NONE
|
EDAC_FLAG_SECDED
;
mci
->
edac_cap
=
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
->
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
;
mci
->
scrub_mode
=
SCRUB_SW_SRC
;
/* Only a single 4GB DIMM is supported */
/* Only a single 4GB DIMM is supported */
...
@@ -217,10 +235,20 @@ static int highbank_mc_probe(struct platform_device *pdev)
...
@@ -217,10 +235,20 @@ static int highbank_mc_probe(struct platform_device *pdev)
if
(
res
<
0
)
if
(
res
<
0
)
goto
err
;
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
);
devres_close_group
(
&
pdev
->
dev
,
NULL
);
return
0
;
return
0
;
err2:
edac_mc_del_mc
(
&
pdev
->
dev
);
err:
err:
devres_release_group
(
&
pdev
->
dev
,
NULL
);
devres_release_group
(
&
pdev
->
dev
,
NULL
);
edac_mc_free
(
mci
);
edac_mc_free
(
mci
);
...
@@ -231,17 +259,12 @@ static int highbank_mc_remove(struct platform_device *pdev)
...
@@ -231,17 +259,12 @@ static int highbank_mc_remove(struct platform_device *pdev)
{
{
struct
mem_ctl_info
*
mci
=
platform_get_drvdata
(
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_del_mc
(
&
pdev
->
dev
);
edac_mc_free
(
mci
);
edac_mc_free
(
mci
);
return
0
;
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
=
{
static
struct
platform_driver
highbank_mc_edac_driver
=
{
.
probe
=
highbank_mc_probe
,
.
probe
=
highbank_mc_probe
,
.
remove
=
highbank_mc_remove
,
.
remove
=
highbank_mc_remove
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment