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
ecca1a34
Commit
ecca1a34
authored
May 31, 2010
by
Benjamin Herrenschmidt
Browse files
Options
Browse Files
Download
Plain Diff
Merge commit 'kumar/next' into next
Conflicts: arch/powerpc/sysdev/fsl_msi.c
parents
3d00d4ff
48936a08
Changes
19
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
1494 additions
and
250 deletions
+1494
-250
arch/powerpc/Kconfig
arch/powerpc/Kconfig
+1
-1
arch/powerpc/boot/dts/mpc8548cds.dts
arch/powerpc/boot/dts/mpc8548cds.dts
+0
-4
arch/powerpc/boot/dts/mpc8572ds_camp_core0.dts
arch/powerpc/boot/dts/mpc8572ds_camp_core0.dts
+13
-2
arch/powerpc/boot/dts/mpc8572ds_camp_core1.dts
arch/powerpc/boot/dts/mpc8572ds_camp_core1.dts
+2
-5
arch/powerpc/boot/dts/p1021mds.dts
arch/powerpc/boot/dts/p1021mds.dts
+698
-0
arch/powerpc/include/asm/cputable.h
arch/powerpc/include/asm/cputable.h
+1
-0
arch/powerpc/include/asm/kexec.h
arch/powerpc/include/asm/kexec.h
+13
-0
arch/powerpc/include/asm/reg_booke.h
arch/powerpc/include/asm/reg_booke.h
+23
-10
arch/powerpc/kernel/Makefile
arch/powerpc/kernel/Makefile
+6
-2
arch/powerpc/kernel/cputable.c
arch/powerpc/kernel/cputable.c
+1
-1
arch/powerpc/kernel/crash.c
arch/powerpc/kernel/crash.c
+4
-0
arch/powerpc/kernel/fsl_booke_entry_mapping.S
arch/powerpc/kernel/fsl_booke_entry_mapping.S
+237
-0
arch/powerpc/kernel/head_fsl_booke.S
arch/powerpc/kernel/head_fsl_booke.S
+3
-197
arch/powerpc/kernel/misc_32.S
arch/powerpc/kernel/misc_32.S
+17
-0
arch/powerpc/kernel/swsusp_booke.S
arch/powerpc/kernel/swsusp_booke.S
+193
-0
arch/powerpc/kernel/traps.c
arch/powerpc/kernel/traps.c
+87
-1
arch/powerpc/platforms/85xx/mpc85xx_mds.c
arch/powerpc/platforms/85xx/mpc85xx_mds.c
+99
-3
arch/powerpc/sysdev/fsl_msi.c
arch/powerpc/sysdev/fsl_msi.c
+93
-24
arch/powerpc/sysdev/fsl_msi.h
arch/powerpc/sysdev/fsl_msi.h
+3
-0
No files found.
arch/powerpc/Kconfig
View file @
ecca1a34
...
@@ -351,7 +351,7 @@ config ARCH_ENABLE_MEMORY_HOTREMOVE
...
@@ -351,7 +351,7 @@ config ARCH_ENABLE_MEMORY_HOTREMOVE
config KEXEC
config KEXEC
bool "kexec system call (EXPERIMENTAL)"
bool "kexec system call (EXPERIMENTAL)"
depends on
PPC_BOOK3S
&& EXPERIMENTAL
depends on
(PPC_BOOK3S || (FSL_BOOKE && !SMP))
&& EXPERIMENTAL
help
help
kexec is a system call that implements the ability to shutdown your
kexec is a system call that implements the ability to shutdown your
current kernel, and to start another kernel. It is like a reboot
current kernel, and to start another kernel. It is like a reboot
...
...
arch/powerpc/boot/dts/mpc8548cds.dts
View file @
ecca1a34
...
@@ -20,10 +20,8 @@ / {
...
@@ -20,10 +20,8 @@ / {
aliases
{
aliases
{
ethernet0
=
&
enet0
;
ethernet0
=
&
enet0
;
ethernet1
=
&
enet1
;
ethernet1
=
&
enet1
;
/*
ethernet2
=
&
enet2
;
ethernet2
=
&
enet2
;
ethernet3
=
&
enet3
;
ethernet3
=
&
enet3
;
*/
serial0
=
&
serial0
;
serial0
=
&
serial0
;
serial1
=
&
serial1
;
serial1
=
&
serial1
;
pci0
=
&
pci0
;
pci0
=
&
pci0
;
...
@@ -254,7 +252,6 @@ tbi1: tbi-phy@11 {
...
@@ -254,7 +252,6 @@ tbi1: tbi-phy@11 {
};
};
};
};
/*
eTSEC
3
/
4
are
currently
broken
enet2
:
ethernet
@
26000
{
enet2
:
ethernet
@
26000
{
#
address
-
cells
=
<
1
>;
#
address
-
cells
=
<
1
>;
#
size
-
cells
=
<
1
>;
#
size
-
cells
=
<
1
>;
...
@@ -310,7 +307,6 @@ tbi3: tbi-phy@11 {
...
@@ -310,7 +307,6 @@ tbi3: tbi-phy@11 {
};
};
};
};
};
};
*/
serial0
:
serial
@
4500
{
serial0
:
serial
@
4500
{
cell
-
index
=
<
0
>;
cell
-
index
=
<
0
>;
...
...
arch/powerpc/boot/dts/mpc8572ds_camp_core0.dts
View file @
ecca1a34
...
@@ -215,6 +215,18 @@ serial0: serial@4500 {
...
@@ -215,6 +215,18 @@ serial0: serial@4500 {
clock
-
frequency
=
<
0
>;
clock
-
frequency
=
<
0
>;
};
};
msi
@
41600
{
compatible
=
"fsl,mpc8572-msi"
,
"fsl,mpic-msi"
;
reg
=
<
0x41600
0x80
>;
msi
-
available
-
ranges
=
<
0
0x80
>;
interrupts
=
<
0xe0
0
0xe1
0
0xe2
0
0xe3
0
>;
interrupt
-
parent
=
<&
mpic
>;
};
global
-
utilities
@
e0000
{
//
global
utilities
block
global
-
utilities
@
e0000
{
//
global
utilities
block
compatible
=
"fsl,mpc8572-guts"
;
compatible
=
"fsl,mpc8572-guts"
;
reg
=
<
0xe0000
0x1000
>;
reg
=
<
0xe0000
0x1000
>;
...
@@ -243,8 +255,7 @@ mpic: pic@40000 {
...
@@ -243,8 +255,7 @@ mpic: pic@40000 {
protected
-
sources
=
<
protected
-
sources
=
<
31
32
33
37
38
39
/*
enet2
enet3
*/
31
32
33
37
38
39
/*
enet2
enet3
*/
76
77
78
79
26
42
/*
dma2
pci2
serial
*/
76
77
78
79
26
42
/*
dma2
pci2
serial
*/
0xe0
0xe1
0xe2
0xe3
/*
msi
*/
0xe4
0xe5
0xe6
0xe7
/*
msi
*/
0xe4
0xe5
0xe6
0xe7
>;
>;
};
};
};
};
...
...
arch/powerpc/boot/dts/mpc8572ds_camp_core1.dts
View file @
ecca1a34
...
@@ -154,12 +154,8 @@ enet3: ethernet@27000 {
...
@@ -154,12 +154,8 @@ enet3: ethernet@27000 {
msi@41600 {
msi@41600 {
compatible = "fsl,mpc8572-msi", "fsl,mpic-msi";
compatible = "fsl,mpc8572-msi", "fsl,mpic-msi";
reg = <0x41600 0x80>;
reg = <0x41600 0x80>;
msi-available-ranges = <0
0x10
0>;
msi-available-ranges = <0
x80 0x8
0>;
interrupts = <
interrupts = <
0xe0 0
0xe1 0
0xe2 0
0xe3 0
0xe4 0
0xe4 0
0xe5 0
0xe5 0
0xe6 0
0xe6 0
...
@@ -190,6 +186,7 @@ mpic: pic@40000 {
...
@@ -190,6 +186,7 @@ mpic: pic@40000 {
0x1 0x2 0x3 0x4 /* pci slot */
0x1 0x2 0x3 0x4 /* pci slot */
0x9 0xa 0xb 0xc /* usb */
0x9 0xa 0xb 0xc /* usb */
0x6 0x7 0xe 0x5 /* Audio elgacy SATA */
0x6 0x7 0xe 0x5 /* Audio elgacy SATA */
0xe0 0xe1 0xe2 0xe3 /* msi */
>;
>;
};
};
};
};
...
...
arch/powerpc/boot/dts/p1021mds.dts
0 → 100644
View file @
ecca1a34
This diff is collapsed.
Click to expand it.
arch/powerpc/include/asm/cputable.h
View file @
ecca1a34
...
@@ -70,6 +70,7 @@ struct pt_regs;
...
@@ -70,6 +70,7 @@ struct pt_regs;
extern
int
machine_check_generic
(
struct
pt_regs
*
regs
);
extern
int
machine_check_generic
(
struct
pt_regs
*
regs
);
extern
int
machine_check_4xx
(
struct
pt_regs
*
regs
);
extern
int
machine_check_4xx
(
struct
pt_regs
*
regs
);
extern
int
machine_check_440A
(
struct
pt_regs
*
regs
);
extern
int
machine_check_440A
(
struct
pt_regs
*
regs
);
extern
int
machine_check_e500mc
(
struct
pt_regs
*
regs
);
extern
int
machine_check_e500
(
struct
pt_regs
*
regs
);
extern
int
machine_check_e500
(
struct
pt_regs
*
regs
);
extern
int
machine_check_e200
(
struct
pt_regs
*
regs
);
extern
int
machine_check_e200
(
struct
pt_regs
*
regs
);
extern
int
machine_check_47x
(
struct
pt_regs
*
regs
);
extern
int
machine_check_47x
(
struct
pt_regs
*
regs
);
...
...
arch/powerpc/include/asm/kexec.h
View file @
ecca1a34
...
@@ -2,6 +2,18 @@
...
@@ -2,6 +2,18 @@
#define _ASM_POWERPC_KEXEC_H
#define _ASM_POWERPC_KEXEC_H
#ifdef __KERNEL__
#ifdef __KERNEL__
#ifdef CONFIG_FSL_BOOKE
/*
* On FSL-BookE we setup a 1:1 mapping which covers the first 2GiB of memory
* and therefore we can only deal with memory within this range
*/
#define KEXEC_SOURCE_MEMORY_LIMIT (2 * 1024 * 1024 * 1024UL)
#define KEXEC_DESTINATION_MEMORY_LIMIT (2 * 1024 * 1024 * 1024UL)
#define KEXEC_CONTROL_MEMORY_LIMIT (2 * 1024 * 1024 * 1024UL)
#else
/*
/*
* Maximum page that is mapped directly into kernel memory.
* Maximum page that is mapped directly into kernel memory.
* XXX: Since we copy virt we can use any page we allocate
* XXX: Since we copy virt we can use any page we allocate
...
@@ -21,6 +33,7 @@
...
@@ -21,6 +33,7 @@
/* TASK_SIZE, probably left over from use_mm ?? */
/* TASK_SIZE, probably left over from use_mm ?? */
#define KEXEC_CONTROL_MEMORY_LIMIT TASK_SIZE
#define KEXEC_CONTROL_MEMORY_LIMIT TASK_SIZE
#endif
#endif
#endif
#define KEXEC_CONTROL_PAGE_SIZE 4096
#define KEXEC_CONTROL_PAGE_SIZE 4096
...
...
arch/powerpc/include/asm/reg_booke.h
View file @
ecca1a34
...
@@ -4,6 +4,12 @@
...
@@ -4,6 +4,12 @@
* are not true Book E PowerPCs, they borrowed a number of features
* are not true Book E PowerPCs, they borrowed a number of features
* before Book E was finalized, and are included here as well. Unfortunatly,
* before Book E was finalized, and are included here as well. Unfortunatly,
* they sometimes used different locations than true Book E CPUs did.
* they sometimes used different locations than true Book E CPUs did.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* Copyright 2009-2010 Freescale Semiconductor, Inc.
*/
*/
#ifdef __KERNEL__
#ifdef __KERNEL__
#ifndef __ASM_POWERPC_REG_BOOKE_H__
#ifndef __ASM_POWERPC_REG_BOOKE_H__
...
@@ -88,6 +94,7 @@
...
@@ -88,6 +94,7 @@
#define SPRN_IVOR35 0x213
/* Interrupt Vector Offset Register 35 */
#define SPRN_IVOR35 0x213
/* Interrupt Vector Offset Register 35 */
#define SPRN_IVOR36 0x214
/* Interrupt Vector Offset Register 36 */
#define SPRN_IVOR36 0x214
/* Interrupt Vector Offset Register 36 */
#define SPRN_IVOR37 0x215
/* Interrupt Vector Offset Register 37 */
#define SPRN_IVOR37 0x215
/* Interrupt Vector Offset Register 37 */
#define SPRN_MCARU 0x239
/* Machine Check Address Register Upper */
#define SPRN_MCSRR0 0x23A
/* Machine Check Save and Restore Register 0 */
#define SPRN_MCSRR0 0x23A
/* Machine Check Save and Restore Register 0 */
#define SPRN_MCSRR1 0x23B
/* Machine Check Save and Restore Register 1 */
#define SPRN_MCSRR1 0x23B
/* Machine Check Save and Restore Register 1 */
#define SPRN_MCSR 0x23C
/* Machine Check Status Register */
#define SPRN_MCSR 0x23C
/* Machine Check Status Register */
...
@@ -196,8 +203,11 @@
...
@@ -196,8 +203,11 @@
#define PPC47x_MCSR_IPR 0x00400000
/* Imprecise Machine Check Exception */
#define PPC47x_MCSR_IPR 0x00400000
/* Imprecise Machine Check Exception */
#ifdef CONFIG_E500
#ifdef CONFIG_E500
/* All e500 */
#define MCSR_MCP 0x80000000UL
/* Machine Check Input Pin */
#define MCSR_MCP 0x80000000UL
/* Machine Check Input Pin */
#define MCSR_ICPERR 0x40000000UL
/* I-Cache Parity Error */
#define MCSR_ICPERR 0x40000000UL
/* I-Cache Parity Error */
/* e500v1/v2 */
#define MCSR_DCP_PERR 0x20000000UL
/* D-Cache Push Parity Error */
#define MCSR_DCP_PERR 0x20000000UL
/* D-Cache Push Parity Error */
#define MCSR_DCPERR 0x10000000UL
/* D-Cache Parity Error */
#define MCSR_DCPERR 0x10000000UL
/* D-Cache Parity Error */
#define MCSR_BUS_IAERR 0x00000080UL
/* Instruction Address Error */
#define MCSR_BUS_IAERR 0x00000080UL
/* Instruction Address Error */
...
@@ -209,12 +219,20 @@
...
@@ -209,12 +219,20 @@
#define MCSR_BUS_IPERR 0x00000002UL
/* Instruction parity Error */
#define MCSR_BUS_IPERR 0x00000002UL
/* Instruction parity Error */
#define MCSR_BUS_RPERR 0x00000001UL
/* Read parity Error */
#define MCSR_BUS_RPERR 0x00000001UL
/* Read parity Error */
/* e500 parts may set unused bits in MCSR; mask these off */
/* e500mc */
#define MCSR_MASK (MCSR_MCP | MCSR_ICPERR | MCSR_DCP_PERR | \
#define MCSR_DCPERR_MC 0x20000000UL
/* D-Cache Parity Error */
MCSR_DCPERR | MCSR_BUS_IAERR | MCSR_BUS_RAERR | \
#define MCSR_L2MMU_MHIT 0x04000000UL
/* Hit on multiple TLB entries */
MCSR_BUS_WAERR | MCSR_BUS_IBERR | MCSR_BUS_RBERR | \
#define MCSR_NMI 0x00100000UL
/* Non-Maskable Interrupt */
MCSR_BUS_WBERR | MCSR_BUS_IPERR | MCSR_BUS_RPERR)
#define MCSR_MAV 0x00080000UL
/* MCAR address valid */
#define MCSR_MEA 0x00040000UL
/* MCAR is effective address */
#define MCSR_IF 0x00010000UL
/* Instruction Fetch */
#define MCSR_LD 0x00008000UL
/* Load */
#define MCSR_ST 0x00004000UL
/* Store */
#define MCSR_LDG 0x00002000UL
/* Guarded Load */
#define MCSR_TLBSYNC 0x00000002UL
/* Multiple tlbsyncs detected */
#define MCSR_BSL2_ERR 0x00000001UL
/* Backside L2 cache error */
#endif
#endif
#ifdef CONFIG_E200
#ifdef CONFIG_E200
#define MCSR_MCP 0x80000000UL
/* Machine Check Input Pin */
#define MCSR_MCP 0x80000000UL
/* Machine Check Input Pin */
#define MCSR_CP_PERR 0x20000000UL
/* Cache Push Parity Error */
#define MCSR_CP_PERR 0x20000000UL
/* Cache Push Parity Error */
...
@@ -225,11 +243,6 @@
...
@@ -225,11 +243,6 @@
#define MCSR_BUS_DRERR 0x00000008UL
/* Read Bus Error on data load */
#define MCSR_BUS_DRERR 0x00000008UL
/* Read Bus Error on data load */
#define MCSR_BUS_WRERR 0x00000004UL
/* Write Bus Error on buffered
#define MCSR_BUS_WRERR 0x00000004UL
/* Write Bus Error on buffered
store or cache line push */
store or cache line push */
/* e200 parts may set unused bits in MCSR; mask these off */
#define MCSR_MASK (MCSR_MCP | MCSR_CP_PERR | MCSR_CPERR | \
MCSR_EXCP_ERR | MCSR_BUS_IRERR | MCSR_BUS_DRERR | \
MCSR_BUS_WRERR)
#endif
#endif
/* Bit definitions for the DBSR. */
/* Bit definitions for the DBSR. */
...
...
arch/powerpc/kernel/Makefile
View file @
ecca1a34
...
@@ -57,8 +57,12 @@ obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
...
@@ -57,8 +57,12 @@ obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
obj-$(CONFIG_E500)
+=
idle_e500.o
obj-$(CONFIG_E500)
+=
idle_e500.o
obj-$(CONFIG_6xx)
+=
idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o
obj-$(CONFIG_6xx)
+=
idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o
obj-$(CONFIG_TAU)
+=
tau_6xx.o
obj-$(CONFIG_TAU)
+=
tau_6xx.o
obj-$(CONFIG_HIBERNATION)
+=
swsusp.o suspend.o
\
obj-$(CONFIG_HIBERNATION)
+=
swsusp.o suspend.o
swsusp_
$(CONFIG_WORD_SIZE)
.o
ifeq
($(CONFIG_FSL_BOOKE),y)
obj-$(CONFIG_HIBERNATION)
+=
swsusp_booke.o
else
obj-$(CONFIG_HIBERNATION)
+=
swsusp_
$(CONFIG_WORD_SIZE)
.o
endif
obj64-$(CONFIG_HIBERNATION)
+=
swsusp_asm64.o
obj64-$(CONFIG_HIBERNATION)
+=
swsusp_asm64.o
obj-$(CONFIG_MODULES)
+=
module.o module_
$(CONFIG_WORD_SIZE)
.o
obj-$(CONFIG_MODULES)
+=
module.o module_
$(CONFIG_WORD_SIZE)
.o
obj-$(CONFIG_44x)
+=
cpu_setup_44x.o
obj-$(CONFIG_44x)
+=
cpu_setup_44x.o
...
...
arch/powerpc/kernel/cputable.c
View file @
ecca1a34
...
@@ -1840,7 +1840,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
...
@@ -1840,7 +1840,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
.
oprofile_cpu_type
=
"ppc/e500mc"
,
.
oprofile_cpu_type
=
"ppc/e500mc"
,
.
oprofile_type
=
PPC_OPROFILE_FSL_EMB
,
.
oprofile_type
=
PPC_OPROFILE_FSL_EMB
,
.
cpu_setup
=
__setup_cpu_e500mc
,
.
cpu_setup
=
__setup_cpu_e500mc
,
.
machine_check
=
machine_check_e500
,
.
machine_check
=
machine_check_e500
mc
,
.
platform
=
"ppce500mc"
,
.
platform
=
"ppce500mc"
,
},
},
{
/* default match */
{
/* default match */
...
...
arch/powerpc/kernel/crash.c
View file @
ecca1a34
...
@@ -163,6 +163,7 @@ static void crash_kexec_prepare_cpus(int cpu)
...
@@ -163,6 +163,7 @@ static void crash_kexec_prepare_cpus(int cpu)
}
}
/* wait for all the CPUs to hit real mode but timeout if they don't come in */
/* wait for all the CPUs to hit real mode but timeout if they don't come in */
#ifdef CONFIG_PPC_STD_MMU_64
static
void
crash_kexec_wait_realmode
(
int
cpu
)
static
void
crash_kexec_wait_realmode
(
int
cpu
)
{
{
unsigned
int
msecs
;
unsigned
int
msecs
;
...
@@ -187,6 +188,7 @@ static void crash_kexec_wait_realmode(int cpu)
...
@@ -187,6 +188,7 @@ static void crash_kexec_wait_realmode(int cpu)
}
}
mb
();
mb
();
}
}
#endif
/*
/*
* This function will be called by secondary cpus or by kexec cpu
* This function will be called by secondary cpus or by kexec cpu
...
@@ -445,7 +447,9 @@ void default_machine_crash_shutdown(struct pt_regs *regs)
...
@@ -445,7 +447,9 @@ void default_machine_crash_shutdown(struct pt_regs *regs)
crash_kexec_prepare_cpus
(
crashing_cpu
);
crash_kexec_prepare_cpus
(
crashing_cpu
);
cpu_set
(
crashing_cpu
,
cpus_in_crash
);
cpu_set
(
crashing_cpu
,
cpus_in_crash
);
crash_kexec_stop_spus
();
crash_kexec_stop_spus
();
#ifdef CONFIG_PPC_STD_MMU_64
crash_kexec_wait_realmode
(
crashing_cpu
);
crash_kexec_wait_realmode
(
crashing_cpu
);
#endif
if
(
ppc_md
.
kexec_cpu_down
)
if
(
ppc_md
.
kexec_cpu_down
)
ppc_md
.
kexec_cpu_down
(
1
,
0
);
ppc_md
.
kexec_cpu_down
(
1
,
0
);
}
}
arch/powerpc/kernel/fsl_booke_entry_mapping.S
0 → 100644
View file @
ecca1a34
/*
1.
Find
the
index
of
the
entry
we
're executing in */
bl
invstr
/*
Find
our
address
*/
invstr
:
mflr
r6
/*
Make
it
accessible
*/
mfmsr
r7
rlwinm
r4
,
r7
,
27
,
31
,
31
/*
extract
MSR
[
IS
]
*/
mfspr
r7
,
SPRN_PID0
slwi
r7
,
r7
,
16
or
r7
,
r7
,
r4
mtspr
SPRN_MAS6
,
r7
tlbsx
0
,
r6
/*
search
MSR
[
IS
],
SPID
=
PID0
*/
mfspr
r7
,
SPRN_MAS1
andis
.
r7
,
r7
,
MAS1_VALID
@
h
bne
match_TLB
mfspr
r7
,
SPRN_MMUCFG
rlwinm
r7
,
r7
,
21
,
28
,
31
/*
extract
MMUCFG
[
NPIDS
]
*/
cmpwi
r7
,
3
bne
match_TLB
/*
skip
if
NPIDS
!=
3
*/
mfspr
r7
,
SPRN_PID1
slwi
r7
,
r7
,
16
or
r7
,
r7
,
r4
mtspr
SPRN_MAS6
,
r7
tlbsx
0
,
r6
/*
search
MSR
[
IS
],
SPID
=
PID1
*/
mfspr
r7
,
SPRN_MAS1
andis
.
r7
,
r7
,
MAS1_VALID
@
h
bne
match_TLB
mfspr
r7
,
SPRN_PID2
slwi
r7
,
r7
,
16
or
r7
,
r7
,
r4
mtspr
SPRN_MAS6
,
r7
tlbsx
0
,
r6
/*
Fall
through
,
we
had
to
match
*/
match_TLB
:
mfspr
r7
,
SPRN_MAS0
rlwinm
r3
,
r7
,
16
,
20
,
31
/*
Extract
MAS0
(
Entry
)
*/
mfspr
r7
,
SPRN_MAS1
/*
Insure
IPROT
set
*/
oris
r7
,
r7
,
MAS1_IPROT
@
h
mtspr
SPRN_MAS1
,
r7
tlbwe
/*
2.
Invalidate
all
entries
except
the
entry
we
're executing in */
mfspr
r9
,
SPRN_TLB1CFG
andi
.
r9
,
r9
,
0xfff
li
r6
,
0
/*
Set
Entry
counter
to
0
*/
1
:
lis
r7
,
0x1000
/*
Set
MAS0
(
TLBSEL
)
=
1
*/
rlwimi
r7
,
r6
,
16
,
4
,
15
/*
Setup
MAS0
=
TLBSEL
|
ESEL
(
r6
)
*/
mtspr
SPRN_MAS0
,
r7
tlbre
mfspr
r7
,
SPRN_MAS1
rlwinm
r7
,
r7
,
0
,
2
,
31
/*
Clear
MAS1
Valid
and
IPROT
*/
cmpw
r3
,
r6
beq
skpinv
/*
Dont
update
the
current
execution
TLB
*/
mtspr
SPRN_MAS1
,
r7
tlbwe
isync
skpinv
:
addi
r6
,
r6
,
1
/*
Increment
*/
cmpw
r6
,
r9
/*
Are
we
done
?
*/
bne
1
b
/*
If
not
,
repeat
*/
/
*
Invalidate
TLB0
*/
li
r6
,
0x04
tlbivax
0
,
r6
TLBSYNC
/
*
Invalidate
TLB1
*/
li
r6
,
0x0c
tlbivax
0
,
r6
TLBSYNC
/*
3.
Setup
a
temp
mapping
and
jump
to
it
*/
andi
.
r5
,
r3
,
0x1
/*
Find
an
entry
not
used
and
is
non
-
zero
*/
addi
r5
,
r5
,
0x1
lis
r7
,
0x1000
/*
Set
MAS0
(
TLBSEL
)
=
1
*/
rlwimi
r7
,
r3
,
16
,
4
,
15
/*
Setup
MAS0
=
TLBSEL
|
ESEL
(
r3
)
*/
mtspr
SPRN_MAS0
,
r7
tlbre
/
*
grab
and
fixup
the
RPN
*/
mfspr
r6
,
SPRN_MAS1
/*
extract
MAS1
[
SIZE
]
*/
rlwinm
r6
,
r6
,
25
,
27
,
31
li
r8
,-
1
addi
r6
,
r6
,
10
slw
r6
,
r8
,
r6
/*
convert
to
mask
*/
bl
1
f
/*
Find
our
address
*/
1
:
mflr
r7
mfspr
r8
,
SPRN_MAS3
#ifdef CONFIG_PHYS_64BIT
mfspr
r23
,
SPRN_MAS7
#endif
and
r8
,
r6
,
r8
subfic
r9
,
r6
,-
4096
and
r9
,
r9
,
r7
or
r25
,
r8
,
r9
ori
r8
,
r25
,(
MAS3_SX|MAS3_SW|MAS3_SR
)
/
*
Just
modify
the
entry
ID
and
EPN
for
the
temp
mapping
*/
lis
r7
,
0x1000
/*
Set
MAS0
(
TLBSEL
)
=
1
*/
rlwimi
r7
,
r5
,
16
,
4
,
15
/*
Setup
MAS0
=
TLBSEL
|
ESEL
(
r5
)
*/
mtspr
SPRN_MAS0
,
r7
xori
r6
,
r4
,
1
/*
Setup
TMP
mapping
in
the
other
Address
space
*/
slwi
r6
,
r6
,
12
oris
r6
,
r6
,(
MAS1_VALID
|
MAS1_IPROT
)
@
h
ori
r6
,
r6
,(
MAS1_TSIZE
(
BOOK3E_PAGESZ_4K
))
@
l
mtspr
SPRN_MAS1
,
r6
mfspr
r6
,
SPRN_MAS2
li
r7
,
0
/*
temp
EPN
=
0
*/
rlwimi
r7
,
r6
,
0
,
20
,
31
mtspr
SPRN_MAS2
,
r7
mtspr
SPRN_MAS3
,
r8
tlbwe
xori
r6
,
r4
,
1
slwi
r6
,
r6
,
5
/*
setup
new
context
with
other
address
space
*/
bl
1
f
/*
Find
our
address
*/
1
:
mflr
r9
rlwimi
r7
,
r9
,
0
,
20
,
31
addi
r7
,
r7
,(
2
f
-
1
b
)
mtspr
SPRN_SRR0
,
r7
mtspr
SPRN_SRR1
,
r6
rfi
2
:
/*
4.
Clear
out
PIDs
&
Search
info
*/
li
r6
,
0
mtspr
SPRN_MAS6
,
r6
mtspr
SPRN_PID0
,
r6
mfspr
r7
,
SPRN_MMUCFG
rlwinm
r7
,
r7
,
21
,
28
,
31
/*
extract
MMUCFG
[
NPIDS
]
*/
cmpwi
r7
,
3
bne
2
f
/*
skip
if
NPIDS
!=
3
*/
mtspr
SPRN_PID1
,
r6
mtspr
SPRN_PID2
,
r6
/*
5.
Invalidate
mapping
we
started
in
*/
2
:
lis
r7
,
0x1000
/*
Set
MAS0
(
TLBSEL
)
=
1
*/
rlwimi
r7
,
r3
,
16
,
4
,
15
/*
Setup
MAS0
=
TLBSEL
|
ESEL
(
r3
)
*/
mtspr
SPRN_MAS0
,
r7
tlbre
mfspr
r6
,
SPRN_MAS1
rlwinm
r6
,
r6
,
0
,
2
,
0
/*
clear
IPROT
*/
mtspr
SPRN_MAS1
,
r6
tlbwe
/
*
Invalidate
TLB1
*/
li
r9
,
0x0c
tlbivax
0
,
r9
TLBSYNC
/*
The
mapping
only
needs
to
be
cache
-
coherent
on
SMP
*/
#ifdef CONFIG_SMP
#define M_IF_SMP MAS2_M
#else
#define M_IF_SMP 0
#endif
#if defined(ENTRY_MAPPING_BOOT_SETUP)
/*
6.
Setup
KERNELBASE
mapping
in
TLB1
[
0
]
*/
lis
r6
,
0x1000
/*
Set
MAS0
(
TLBSEL
)
=
TLB1
(
1
),
ESEL
=
0
*/
mtspr
SPRN_MAS0
,
r6
lis
r6
,(
MAS1_VALID
|
MAS1_IPROT
)
@
h
ori
r6
,
r6
,(
MAS1_TSIZE
(
BOOK3E_PAGESZ_64M
))
@
l
mtspr
SPRN_MAS1
,
r6
lis
r6
,
MAS2_VAL
(
PAGE_OFFSET
,
BOOK3E_PAGESZ_64M
,
M_IF_SMP
)
@
h
ori
r6
,
r6
,
MAS2_VAL
(
PAGE_OFFSET
,
BOOK3E_PAGESZ_64M
,
M_IF_SMP
)
@
l
mtspr
SPRN_MAS2
,
r6
mtspr
SPRN_MAS3
,
r8
tlbwe
/*
7.
Jump
to
KERNELBASE
mapping
*/
lis
r6
,(
KERNELBASE
&
~
0xfff
)
@
h
ori
r6
,
r6
,(
KERNELBASE
&
~
0xfff
)
@
l
#elif defined(ENTRY_MAPPING_KEXEC_SETUP)
/*
*
6
.
Setup
a
1
:
1
mapping
in
TLB1
.
Esel
0
is
unsued
,
1
or
2
contains
the
tmp
*
mapping
so
we
start
at
3
.
We
setup
8
mappings
,
each
256
MiB
in
size
.
This
*
will
cover
the
first
2
GiB
of
memory
.
*/
lis
r10
,
(
MAS1_VALID
|
MAS1_IPROT
)
@
h
ori
r10
,
r10
,
(
MAS1_TSIZE
(
BOOK3E_PAGESZ_256M
))
@
l
li
r11
,
0
li
r0
,
8
mtctr
r0
next_tlb_setup
:
addi
r0
,
r11
,
3
rlwinm
r0
,
r0
,
16
,
4
,
15
//
Compute
esel
rlwinm
r9
,
r11
,
28
,
0
,
3
//
Compute
[
ER
]
PN
oris
r0
,
r0
,
(
MAS0_TLBSEL
(
1
))
@
h
mtspr
SPRN_MAS0
,
r0
mtspr
SPRN_MAS1
,
r10
mtspr
SPRN_MAS2
,
r9
ori
r9
,
r9
,
(
MAS3_SX|MAS3_SW|MAS3_SR
)
mtspr
SPRN_MAS3
,
r9
tlbwe
addi
r11
,
r11
,
1
bdnz
+
next_tlb_setup
/*
7.
Jump
to
our
1
:
1
mapping
*/
li
r6
,
0
#else
#error You need to specify the mapping or not use this at all.
#endif
lis
r7
,
MSR_KERNEL
@
h
ori
r7
,
r7
,
MSR_KERNEL
@
l
bl
1
f
/*
Find
our
address
*/
1
:
mflr
r9
rlwimi
r6
,
r9
,
0
,
20
,
31
addi
r6
,
r6
,(
2
f
-
1
b
)
add
r6
,
r6
,
r25
mtspr
SPRN_SRR0
,
r6
mtspr
SPRN_SRR1
,
r7
rfi
/*
start
execution
out
of
TLB1
[
0
]
entry
*/
/*
8.
Clear
out
the
temp
mapping
*/
2
:
lis
r7
,
0x1000
/*
Set
MAS0
(
TLBSEL
)
=
1
*/
rlwimi
r7
,
r5
,
16
,
4
,
15
/*
Setup
MAS0
=
TLBSEL
|
ESEL
(
r5
)
*/
mtspr
SPRN_MAS0
,
r7
tlbre
mfspr
r8
,
SPRN_MAS1
rlwinm
r8
,
r8
,
0
,
2
,
0
/*
clear
IPROT
*/
mtspr
SPRN_MAS1
,
r8
tlbwe
/
*
Invalidate
TLB1
*/
li
r9
,
0x0c
tlbivax
0
,
r9
TLBSYNC
arch/powerpc/kernel/head_fsl_booke.S
View file @
ecca1a34
...
@@ -94,204 +94,10 @@ _ENTRY(_start);
...
@@ -94,204 +94,10 @@ _ENTRY(_start);
*/
*/
_ENTRY
(
__early_start
)
_ENTRY
(
__early_start
)
/*
1.
Find
the
index
of
the
entry
we
're executing in */
bl
invstr
/*
Find
our
address
*/
invstr
:
mflr
r6
/*
Make
it
accessible
*/
mfmsr
r7
rlwinm
r4
,
r7
,
27
,
31
,
31
/*
extract
MSR
[
IS
]
*/
mfspr
r7
,
SPRN_PID0
slwi
r7
,
r7
,
16
or
r7
,
r7
,
r4
mtspr
SPRN_MAS6
,
r7
tlbsx
0
,
r6
/*
search
MSR
[
IS
],
SPID
=
PID0
*/
mfspr
r7
,
SPRN_MAS1
andis
.
r7
,
r7
,
MAS1_VALID
@
h
bne
match_TLB
mfspr
r7
,
SPRN_MMUCFG
rlwinm
r7
,
r7
,
21
,
28
,
31
/*
extract
MMUCFG
[
NPIDS
]
*/
cmpwi
r7
,
3
bne
match_TLB
/*
skip
if
NPIDS
!=
3
*/
mfspr
r7
,
SPRN_PID1
slwi
r7
,
r7
,
16
or
r7
,
r7
,
r4
mtspr
SPRN_MAS6
,
r7
tlbsx
0
,
r6
/*
search
MSR
[
IS
],
SPID
=
PID1
*/
mfspr
r7
,
SPRN_MAS1
andis
.
r7
,
r7
,
MAS1_VALID
@
h
bne
match_TLB
mfspr
r7
,
SPRN_PID2
slwi
r7
,
r7
,
16
or
r7
,
r7
,
r4
mtspr
SPRN_MAS6
,
r7
tlbsx
0
,
r6
/*
Fall
through
,
we
had
to
match
*/
match_TLB
:
mfspr
r7
,
SPRN_MAS0
rlwinm
r3
,
r7
,
16
,
20
,
31
/*
Extract
MAS0
(
Entry
)
*/
mfspr
r7
,
SPRN_MAS1
/*
Insure
IPROT
set
*/
oris
r7
,
r7
,
MAS1_IPROT
@
h
mtspr
SPRN_MAS1
,
r7
tlbwe
/*
2.
Invalidate
all
entries
except
the
entry
we
're executing in */
mfspr
r9
,
SPRN_TLB1CFG
andi
.
r9
,
r9
,
0xfff
li
r6
,
0
/*
Set
Entry
counter
to
0
*/
1
:
lis
r7
,
0x1000
/*
Set
MAS0
(
TLBSEL
)
=
1
*/
rlwimi
r7
,
r6
,
16
,
4
,
15
/*
Setup
MAS0
=
TLBSEL
|
ESEL
(
r6
)
*/
mtspr
SPRN_MAS0
,
r7
tlbre
mfspr
r7
,
SPRN_MAS1
rlwinm
r7
,
r7
,
0
,
2
,
31
/*
Clear
MAS1
Valid
and
IPROT
*/
cmpw
r3
,
r6
beq
skpinv
/*
Dont
update
the
current
execution
TLB
*/
mtspr
SPRN_MAS1
,
r7
tlbwe
isync
skpinv
:
addi
r6
,
r6
,
1
/*
Increment
*/
cmpw
r6
,
r9
/*
Are
we
done
?
*/
bne
1
b
/*
If
not
,
repeat
*/
/
*
Invalidate
TLB0
*/
li
r6
,
0x04
tlbivax
0
,
r6
TLBSYNC
/
*
Invalidate
TLB1
*/
li
r6
,
0x0c
tlbivax
0
,
r6
TLBSYNC
/*
3.
Setup
a
temp
mapping
and
jump
to
it
*/
andi
.
r5
,
r3
,
0x1
/*
Find
an
entry
not
used
and
is
non
-
zero
*/
addi
r5
,
r5
,
0x1
lis
r7
,
0x1000
/*
Set
MAS0
(
TLBSEL
)
=
1
*/
rlwimi
r7
,
r3
,
16
,
4
,
15
/*
Setup
MAS0
=
TLBSEL
|
ESEL
(
r3
)
*/
mtspr
SPRN_MAS0
,
r7
tlbre
/
*
grab
and
fixup
the
RPN
*/
mfspr
r6
,
SPRN_MAS1
/*
extract
MAS1
[
SIZE
]
*/
rlwinm
r6
,
r6
,
25
,
27
,
31
li
r8
,-
1
addi
r6
,
r6
,
10
slw
r6
,
r8
,
r6
/*
convert
to
mask
*/
bl
1
f
/*
Find
our
address
*/
1
:
mflr
r7
mfspr
r8
,
SPRN_MAS3
#ifdef CONFIG_PHYS_64BIT
mfspr
r23
,
SPRN_MAS7
#endif
and
r8
,
r6
,
r8
subfic
r9
,
r6
,-
4096
and
r9
,
r9
,
r7
or
r25
,
r8
,
r9
ori
r8
,
r25
,(
MAS3_SX|MAS3_SW|MAS3_SR
)
/
*
Just
modify
the
entry
ID
and
EPN
for
the
temp
mapping
*/
lis
r7
,
0x1000
/*
Set
MAS0
(
TLBSEL
)
=
1
*/
rlwimi
r7
,
r5
,
16
,
4
,
15
/*
Setup
MAS0
=
TLBSEL
|
ESEL
(
r5
)
*/
mtspr
SPRN_MAS0
,
r7
xori
r6
,
r4
,
1
/*
Setup
TMP
mapping
in
the
other
Address
space
*/
slwi
r6
,
r6
,
12
oris
r6
,
r6
,(
MAS1_VALID
|
MAS1_IPROT
)
@
h
ori
r6
,
r6
,(
MAS1_TSIZE
(
BOOK3E_PAGESZ_4K
))
@
l
mtspr
SPRN_MAS1
,
r6
mfspr
r6
,
SPRN_MAS2
li
r7
,
0
/*
temp
EPN
=
0
*/
rlwimi
r7
,
r6
,
0
,
20
,
31
mtspr
SPRN_MAS2
,
r7
mtspr
SPRN_MAS3
,
r8
tlbwe
xori
r6
,
r4
,
1
slwi
r6
,
r6
,
5
/*
setup
new
context
with
other
address
space
*/
bl
1
f
/*
Find
our
address
*/
1
:
mflr
r9
rlwimi
r7
,
r9
,
0
,
20
,
31
addi
r7
,
r7
,(
2
f
-
1
b
)
mtspr
SPRN_SRR0
,
r7
mtspr
SPRN_SRR1
,
r6
rfi
2
:
/*
4.
Clear
out
PIDs
&
Search
info
*/
li
r6
,
0
mtspr
SPRN_MAS6
,
r6
mtspr
SPRN_PID0
,
r6
mfspr
r7
,
SPRN_MMUCFG
rlwinm
r7
,
r7
,
21
,
28
,
31
/*
extract
MMUCFG
[
NPIDS
]
*/
cmpwi
r7
,
3
bne
2
f
/*
skip
if
NPIDS
!=
3
*/
mtspr
SPRN_PID1
,
r6
#define ENTRY_MAPPING_BOOT_SETUP
mtspr
SPRN_PID2
,
r6
#include "fsl_booke_entry_mapping.S"
#undef ENTRY_MAPPING_BOOT_SETUP
/*
5.
Invalidate
mapping
we
started
in
*/
2
:
lis
r7
,
0x1000
/*
Set
MAS0
(
TLBSEL
)
=
1
*/
rlwimi
r7
,
r3
,
16
,
4
,
15
/*
Setup
MAS0
=
TLBSEL
|
ESEL
(
r3
)
*/
mtspr
SPRN_MAS0
,
r7
tlbre
mfspr
r6
,
SPRN_MAS1
rlwinm
r6
,
r6
,
0
,
2
,
0
/*
clear
IPROT
*/
mtspr
SPRN_MAS1
,
r6
tlbwe
/
*
Invalidate
TLB1
*/
li
r9
,
0x0c
tlbivax
0
,
r9
TLBSYNC
/*
The
mapping
only
needs
to
be
cache
-
coherent
on
SMP
*/
#ifdef CONFIG_SMP
#define M_IF_SMP MAS2_M
#else
#define M_IF_SMP 0
#endif
/*
6.
Setup
KERNELBASE
mapping
in
TLB1
[
0
]
*/
lis
r6
,
0x1000
/*
Set
MAS0
(
TLBSEL
)
=
TLB1
(
1
),
ESEL
=
0
*/
mtspr
SPRN_MAS0
,
r6
lis
r6
,(
MAS1_VALID
|
MAS1_IPROT
)
@
h
ori
r6
,
r6
,(
MAS1_TSIZE
(
BOOK3E_PAGESZ_64M
))
@
l
mtspr
SPRN_MAS1
,
r6
lis
r6
,
MAS2_VAL
(
PAGE_OFFSET
,
BOOK3E_PAGESZ_64M
,
M_IF_SMP
)
@
h
ori
r6
,
r6
,
MAS2_VAL
(
PAGE_OFFSET
,
BOOK3E_PAGESZ_64M
,
M_IF_SMP
)
@
l
mtspr
SPRN_MAS2
,
r6
mtspr
SPRN_MAS3
,
r8
tlbwe
/*
7.
Jump
to
KERNELBASE
mapping
*/
lis
r6
,(
KERNELBASE
&
~
0xfff
)
@
h
ori
r6
,
r6
,(
KERNELBASE
&
~
0xfff
)
@
l
lis
r7
,
MSR_KERNEL
@
h
ori
r7
,
r7
,
MSR_KERNEL
@
l
bl
1
f
/*
Find
our
address
*/
1
:
mflr
r9
rlwimi
r6
,
r9
,
0
,
20
,
31
addi
r6
,
r6
,(
2
f
-
1
b
)
mtspr
SPRN_SRR0
,
r6
mtspr
SPRN_SRR1
,
r7
rfi
/*
start
execution
out
of
TLB1
[
0
]
entry
*/
/*
8.
Clear
out
the
temp
mapping
*/
2
:
lis
r7
,
0x1000
/*
Set
MAS0
(
TLBSEL
)
=
1
*/
rlwimi
r7
,
r5
,
16
,
4
,
15
/*
Setup
MAS0
=
TLBSEL
|
ESEL
(
r5
)
*/
mtspr
SPRN_MAS0
,
r7
tlbre
mfspr
r8
,
SPRN_MAS1
rlwinm
r8
,
r8
,
0
,
2
,
0
/*
clear
IPROT
*/
mtspr
SPRN_MAS1
,
r8
tlbwe
/
*
Invalidate
TLB1
*/
li
r9
,
0x0c
tlbivax
0
,
r9
TLBSYNC
/
*
Establish
the
interrupt
vector
offsets
*/
/
*
Establish
the
interrupt
vector
offsets
*/
SET_IVOR
(0,
CriticalInput
)
;
SET_IVOR
(0,
CriticalInput
)
;
...
...
arch/powerpc/kernel/misc_32.S
View file @
ecca1a34
...
@@ -711,6 +711,22 @@ relocate_new_kernel:
...
@@ -711,6 +711,22 @@ relocate_new_kernel:
/
*
r4
=
reboot_code_buffer
*/
/
*
r4
=
reboot_code_buffer
*/
/
*
r5
=
start_address
*/
/
*
r5
=
start_address
*/
#ifdef CONFIG_FSL_BOOKE
mr
r29
,
r3
mr
r30
,
r4
mr
r31
,
r5
#define ENTRY_MAPPING_KEXEC_SETUP
#include "fsl_booke_entry_mapping.S"
#undef ENTRY_MAPPING_KEXEC_SETUP
mr
r3
,
r29
mr
r4
,
r30
mr
r5
,
r31
li
r0
,
0
#else
li
r0
,
0
li
r0
,
0
/
*
/
*
...
@@ -727,6 +743,7 @@ relocate_new_kernel:
...
@@ -727,6 +743,7 @@ relocate_new_kernel:
rfi
rfi
1
:
1
:
#endif
/
*
from
this
point
address
translation
is
turned
off
*/
/
*
from
this
point
address
translation
is
turned
off
*/
/
*
and
interrupts
are
disabled
*/
/
*
and
interrupts
are
disabled
*/
...
...
arch/powerpc/kernel/swsusp_booke.S
0 → 100644
View file @
ecca1a34
/*
*
Based
on
swsusp_32
.
S
,
modified
for
FSL
BookE
by
*
Anton
Vorontsov
<
avorontsov
@
ru
.
mvista
.
com
>
*
Copyright
(
c
)
2009
-
2010
MontaVista
Software
,
LLC
.
*/
#include <linux/threads.h>
#include <asm/processor.h>
#include <asm/page.h>
#include <asm/cputable.h>
#include <asm/thread_info.h>
#include <asm/ppc_asm.h>
#include <asm/asm-offsets.h>
#include <asm/mmu.h>
/*
*
Structure
for
storing
CPU
registers
on
the
save
area
.
*/
#define SL_SP 0
#define SL_PC 4
#define SL_MSR 8
#define SL_TCR 0xc
#define SL_SPRG0 0x10
#define SL_SPRG1 0x14
#define SL_SPRG2 0x18
#define SL_SPRG3 0x1c
#define SL_SPRG4 0x20
#define SL_SPRG5 0x24
#define SL_SPRG6 0x28
#define SL_SPRG7 0x2c
#define SL_TBU 0x30
#define SL_TBL 0x34
#define SL_R2 0x38
#define SL_CR 0x3c
#define SL_LR 0x40
#define SL_R12 0x44 /* r12 to r31 */
#define SL_SIZE (SL_R12 + 80)
.
section
.
data
.
align
5
_GLOBAL
(
swsusp_save_area
)
.
space
SL_SIZE
.
section
.
text
.
align
5
_GLOBAL
(
swsusp_arch_suspend
)
lis
r11
,
swsusp_save_area
@
h
ori
r11
,
r11
,
swsusp_save_area
@
l
mflr
r0
stw
r0
,
SL_LR
(
r11
)
mfcr
r0
stw
r0
,
SL_CR
(
r11
)
stw
r1
,
SL_SP
(
r11
)
stw
r2
,
SL_R2
(
r11
)
stmw
r12
,
SL_R12
(
r11
)
/
*
Save
MSR
&
TCR
*/
mfmsr
r4
stw
r4
,
SL_MSR
(
r11
)
mfspr
r4
,
SPRN_TCR
stw
r4
,
SL_TCR
(
r11
)
/
*
Get
a
stable
timebase
and
save
it
*/
1
:
mfspr
r4
,
SPRN_TBRU
stw
r4
,
SL_TBU
(
r11
)
mfspr
r5
,
SPRN_TBRL
stw
r5
,
SL_TBL
(
r11
)
mfspr
r3
,
SPRN_TBRU
cmpw
r3
,
r4
bne
1
b
/
*
Save
SPRGs
*/
mfsprg
r4
,
0
stw
r4
,
SL_SPRG0
(
r11
)
mfsprg
r4
,
1
stw
r4
,
SL_SPRG1
(
r11
)
mfsprg
r4
,
2
stw
r4
,
SL_SPRG2
(
r11
)
mfsprg
r4
,
3
stw
r4
,
SL_SPRG3
(
r11
)
mfsprg
r4
,
4
stw
r4
,
SL_SPRG4
(
r11
)
mfsprg
r4
,
5
stw
r4
,
SL_SPRG5
(
r11
)
mfsprg
r4
,
6
stw
r4
,
SL_SPRG6
(
r11
)
mfsprg
r4
,
7
stw
r4
,
SL_SPRG7
(
r11
)
/
*
Call
the
low
level
suspend
stuff
(
we
should
probably
have
made
*
a
stackframe
...
*/
bl
swsusp_save
/
*
Restore
LR
from
the
save
area
*/
lis
r11
,
swsusp_save_area
@
h
ori
r11
,
r11
,
swsusp_save_area
@
l
lwz
r0
,
SL_LR
(
r11
)
mtlr
r0
blr
_GLOBAL
(
swsusp_arch_resume
)
sync
/
*
Load
ptr
the
list
of
pages
to
copy
in
r3
*/
lis
r11
,(
restore_pblist
)
@
h
ori
r11
,
r11
,
restore_pblist
@
l
lwz
r3
,
0
(
r11
)
/
*
Copy
the
pages
.
This
is
a
very
basic
implementation
,
to
*
be
replaced
by
something
more
cache
efficient
*/
1
:
li
r0
,
256
mtctr
r0
lwz
r5
,
pbe_address
(
r3
)
/*
source
*/
lwz
r6
,
pbe_orig_address
(
r3
)
/*
destination
*/
2
:
lwz
r8
,
0
(
r5
)
lwz
r9
,
4
(
r5
)
lwz
r10
,
8
(
r5
)
lwz
r11
,
12
(
r5
)
addi
r5
,
r5
,
16
stw
r8
,
0
(
r6
)
stw
r9
,
4
(
r6
)
stw
r10
,
8
(
r6
)
stw
r11
,
12
(
r6
)
addi
r6
,
r6
,
16
bdnz
2
b
lwz
r3
,
pbe_next
(
r3
)
cmpwi
0
,
r3
,
0
bne
1
b
bl
flush_dcache_L1
bl
flush_instruction_cache
lis
r11
,
swsusp_save_area
@
h
ori
r11
,
r11
,
swsusp_save_area
@
l
lwz
r4
,
SL_SPRG0
(
r11
)
mtsprg
0
,
r4
lwz
r4
,
SL_SPRG1
(
r11
)
mtsprg
1
,
r4
lwz
r4
,
SL_SPRG2
(
r11
)
mtsprg
2
,
r4
lwz
r4
,
SL_SPRG3
(
r11
)
mtsprg
3
,
r4
lwz
r4
,
SL_SPRG4
(
r11
)
mtsprg
4
,
r4
lwz
r4
,
SL_SPRG5
(
r11
)
mtsprg
5
,
r4
lwz
r4
,
SL_SPRG6
(
r11
)
mtsprg
6
,
r4
lwz
r4
,
SL_SPRG7
(
r11
)
mtsprg
7
,
r4
/
*
restore
the
MSR
*/
lwz
r3
,
SL_MSR
(
r11
)
mtmsr
r3
/
*
Restore
TB
*/
li
r3
,
0
mtspr
SPRN_TBWL
,
r3
lwz
r3
,
SL_TBU
(
r11
)
lwz
r4
,
SL_TBL
(
r11
)
mtspr
SPRN_TBWU
,
r3
mtspr
SPRN_TBWL
,
r4
/
*
Restore
TCR
and
clear
any
pending
bits
in
TSR
.
*/
lwz
r4
,
SL_TCR
(
r11
)
mtspr
SPRN_TCR
,
r4
lis
r4
,
(
TSR_ENW
| TSR_WIS |
TSR_DIS
|
TSR_FIS
)
@
h
mtspr
SPRN_TSR
,
r4
/
*
Kick
decrementer
*/
li
r0
,
1
mtdec
r0
/
*
Restore
the
callee
-
saved
registers
and
return
*/
lwz
r0
,
SL_CR
(
r11
)
mtcr
r0
lwz
r2
,
SL_R2
(
r11
)
lmw
r12
,
SL_R12
(
r11
)
lwz
r1
,
SL_SP
(
r11
)
lwz
r0
,
SL_LR
(
r11
)
mtlr
r0
li
r3
,
0
blr
arch/powerpc/kernel/traps.c
View file @
ecca1a34
/*
/*
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
* Copyright 2007-2010 Freescale Semiconductor, Inc.
*
*
* This program is free software; you can redistribute it and/or
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* modify it under the terms of the GNU General Public License
...
@@ -305,7 +306,7 @@ static inline int check_io_access(struct pt_regs *regs)
...
@@ -305,7 +306,7 @@ static inline int check_io_access(struct pt_regs *regs)
#ifndef CONFIG_FSL_BOOKE
#ifndef CONFIG_FSL_BOOKE
#define get_mc_reason(regs) ((regs)->dsisr)
#define get_mc_reason(regs) ((regs)->dsisr)
#else
#else
#define get_mc_reason(regs) (mfspr(SPRN_MCSR)
& MCSR_MASK
)
#define get_mc_reason(regs) (mfspr(SPRN_MCSR))
#endif
#endif
#define REASON_FP ESR_FP
#define REASON_FP ESR_FP
#define REASON_ILLEGAL (ESR_PIL | ESR_PUO)
#define REASON_ILLEGAL (ESR_PIL | ESR_PUO)
...
@@ -421,6 +422,91 @@ int machine_check_47x(struct pt_regs *regs)
...
@@ -421,6 +422,91 @@ int machine_check_47x(struct pt_regs *regs)
return
0
;
return
0
;
}
}
#elif defined(CONFIG_E500)
#elif defined(CONFIG_E500)
int
machine_check_e500mc
(
struct
pt_regs
*
regs
)
{
unsigned
long
mcsr
=
mfspr
(
SPRN_MCSR
);
unsigned
long
reason
=
mcsr
;
int
recoverable
=
1
;
printk
(
"Machine check in kernel mode.
\n
"
);
printk
(
"Caused by (from MCSR=%lx): "
,
reason
);
if
(
reason
&
MCSR_MCP
)
printk
(
"Machine Check Signal
\n
"
);
if
(
reason
&
MCSR_ICPERR
)
{
printk
(
"Instruction Cache Parity Error
\n
"
);
/*
* This is recoverable by invalidating the i-cache.
*/
mtspr
(
SPRN_L1CSR1
,
mfspr
(
SPRN_L1CSR1
)
|
L1CSR1_ICFI
);
while
(
mfspr
(
SPRN_L1CSR1
)
&
L1CSR1_ICFI
)
;
/*
* This will generally be accompanied by an instruction
* fetch error report -- only treat MCSR_IF as fatal
* if it wasn't due to an L1 parity error.
*/
reason
&=
~
MCSR_IF
;
}
if
(
reason
&
MCSR_DCPERR_MC
)
{
printk
(
"Data Cache Parity Error
\n
"
);
recoverable
=
0
;
}
if
(
reason
&
MCSR_L2MMU_MHIT
)
{
printk
(
"Hit on multiple TLB entries
\n
"
);
recoverable
=
0
;
}
if
(
reason
&
MCSR_NMI
)
printk
(
"Non-maskable interrupt
\n
"
);
if
(
reason
&
MCSR_IF
)
{
printk
(
"Instruction Fetch Error Report
\n
"
);
recoverable
=
0
;
}
if
(
reason
&
MCSR_LD
)
{
printk
(
"Load Error Report
\n
"
);
recoverable
=
0
;
}
if
(
reason
&
MCSR_ST
)
{
printk
(
"Store Error Report
\n
"
);
recoverable
=
0
;
}
if
(
reason
&
MCSR_LDG
)
{
printk
(
"Guarded Load Error Report
\n
"
);
recoverable
=
0
;
}
if
(
reason
&
MCSR_TLBSYNC
)
printk
(
"Simultaneous tlbsync operations
\n
"
);
if
(
reason
&
MCSR_BSL2_ERR
)
{
printk
(
"Level 2 Cache Error
\n
"
);
recoverable
=
0
;
}
if
(
reason
&
MCSR_MAV
)
{
u64
addr
;
addr
=
mfspr
(
SPRN_MCAR
);
addr
|=
(
u64
)
mfspr
(
SPRN_MCARU
)
<<
32
;
printk
(
"Machine Check %s Address: %#llx
\n
"
,
reason
&
MCSR_MEA
?
"Effective"
:
"Physical"
,
addr
);
}
mtspr
(
SPRN_MCSR
,
mcsr
);
return
mfspr
(
SPRN_MCSR
)
==
0
&&
recoverable
;
}
int
machine_check_e500
(
struct
pt_regs
*
regs
)
int
machine_check_e500
(
struct
pt_regs
*
regs
)
{
{
unsigned
long
reason
=
get_mc_reason
(
regs
);
unsigned
long
reason
=
get_mc_reason
(
regs
);
...
...
arch/powerpc/platforms/85xx/mpc85xx_mds.c
View file @
ecca1a34
/*
/*
* Copyright (C) Freescale Semicondutor, Inc. 2006-20
07
. All rights reserved.
* Copyright (C) Freescale Semicondutor, Inc. 2006-20
10
. All rights reserved.
*
*
* Author: Andy Fleming <afleming@freescale.com>
* Author: Andy Fleming <afleming@freescale.com>
*
*
...
@@ -154,6 +154,10 @@ static int mpc8568_mds_phy_fixups(struct phy_device *phydev)
...
@@ -154,6 +154,10 @@ static int mpc8568_mds_phy_fixups(struct phy_device *phydev)
* Setup the architecture
* Setup the architecture
*
*
*/
*/
#ifdef CONFIG_SMP
extern
void
__init
mpc85xx_smp_init
(
void
);
#endif
static
void
__init
mpc85xx_mds_setup_arch
(
void
)
static
void
__init
mpc85xx_mds_setup_arch
(
void
)
{
{
struct
device_node
*
np
;
struct
device_node
*
np
;
...
@@ -194,6 +198,10 @@ static void __init mpc85xx_mds_setup_arch(void)
...
@@ -194,6 +198,10 @@ static void __init mpc85xx_mds_setup_arch(void)
}
}
#endif
#endif
#ifdef CONFIG_SMP
mpc85xx_smp_init
();
#endif
#ifdef CONFIG_QUICC_ENGINE
#ifdef CONFIG_QUICC_ENGINE
np
=
of_find_compatible_node
(
NULL
,
NULL
,
"fsl,qe"
);
np
=
of_find_compatible_node
(
NULL
,
NULL
,
"fsl,qe"
);
if
(
!
np
)
{
if
(
!
np
)
{
...
@@ -271,9 +279,49 @@ static void __init mpc85xx_mds_setup_arch(void)
...
@@ -271,9 +279,49 @@ static void __init mpc85xx_mds_setup_arch(void)
BCSR_UCC_RGMII
,
BCSR_UCC_RTBI
);
BCSR_UCC_RGMII
,
BCSR_UCC_RTBI
);
}
}
}
else
if
(
machine_is
(
p1021_mds
))
{
#define BCSR11_ENET_MICRST (0x1 << 5)
/* Reset Micrel PHY */
clrbits8
(
&
bcsr_regs
[
11
],
BCSR11_ENET_MICRST
);
setbits8
(
&
bcsr_regs
[
11
],
BCSR11_ENET_MICRST
);
}
}
iounmap
(
bcsr_regs
);
iounmap
(
bcsr_regs
);
}
}
if
(
machine_is
(
p1021_mds
))
{
#define MPC85xx_PMUXCR_OFFSET 0x60
#define MPC85xx_PMUXCR_QE0 0x00008000
#define MPC85xx_PMUXCR_QE3 0x00001000
#define MPC85xx_PMUXCR_QE9 0x00000040
#define MPC85xx_PMUXCR_QE12 0x00000008
static
__be32
__iomem
*
pmuxcr
;
np
=
of_find_node_by_name
(
NULL
,
"global-utilities"
);
if
(
np
)
{
pmuxcr
=
of_iomap
(
np
,
0
)
+
MPC85xx_PMUXCR_OFFSET
;
if
(
!
pmuxcr
)
printk
(
KERN_EMERG
"Error: Alternate function"
" signal multiplex control register not"
" mapped!
\n
"
);
else
/* P1021 has pins muxed for QE and other functions. To
* enable QE UEC mode, we need to set bit QE0 for UCC1
* in Eth mode, QE0 and QE3 for UCC5 in Eth mode, QE9
* and QE12 for QE MII management singals in PMUXCR
* register.
*/
setbits32
(
pmuxcr
,
MPC85xx_PMUXCR_QE0
|
MPC85xx_PMUXCR_QE3
|
MPC85xx_PMUXCR_QE9
|
MPC85xx_PMUXCR_QE12
);
of_node_put
(
np
);
}
}
#endif
/* CONFIG_QUICC_ENGINE */
#endif
/* CONFIG_QUICC_ENGINE */
#ifdef CONFIG_SWIOTLB
#ifdef CONFIG_SWIOTLB
...
@@ -330,6 +378,16 @@ static struct of_device_id mpc85xx_ids[] = {
...
@@ -330,6 +378,16 @@ static struct of_device_id mpc85xx_ids[] = {
{},
{},
};
};
static
struct
of_device_id
p1021_ids
[]
=
{
{
.
type
=
"soc"
,
},
{
.
compatible
=
"soc"
,
},
{
.
compatible
=
"simple-bus"
,
},
{
.
type
=
"qe"
,
},
{
.
compatible
=
"fsl,qe"
,
},
{
.
compatible
=
"gianfar"
,
},
{},
};
static
int
__init
mpc85xx_publish_devices
(
void
)
static
int
__init
mpc85xx_publish_devices
(
void
)
{
{
if
(
machine_is
(
mpc8568_mds
))
if
(
machine_is
(
mpc8568_mds
))
...
@@ -342,11 +400,22 @@ static int __init mpc85xx_publish_devices(void)
...
@@ -342,11 +400,22 @@ static int __init mpc85xx_publish_devices(void)
return
0
;
return
0
;
}
}
static
int
__init
p1021_publish_devices
(
void
)
{
/* Publish the QE devices */
of_platform_bus_probe
(
NULL
,
p1021_ids
,
NULL
);
return
0
;
}
machine_device_initcall
(
mpc8568_mds
,
mpc85xx_publish_devices
);
machine_device_initcall
(
mpc8568_mds
,
mpc85xx_publish_devices
);
machine_device_initcall
(
mpc8569_mds
,
mpc85xx_publish_devices
);
machine_device_initcall
(
mpc8569_mds
,
mpc85xx_publish_devices
);
machine_device_initcall
(
p1021_mds
,
p1021_publish_devices
);
machine_arch_initcall
(
mpc8568_mds
,
swiotlb_setup_bus_notifier
);
machine_arch_initcall
(
mpc8568_mds
,
swiotlb_setup_bus_notifier
);
machine_arch_initcall
(
mpc8569_mds
,
swiotlb_setup_bus_notifier
);
machine_arch_initcall
(
mpc8569_mds
,
swiotlb_setup_bus_notifier
);
machine_arch_initcall
(
p1021_mds
,
swiotlb_setup_bus_notifier
);
static
void
__init
mpc85xx_mds_pic_init
(
void
)
static
void
__init
mpc85xx_mds_pic_init
(
void
)
{
{
...
@@ -366,7 +435,7 @@ static void __init mpc85xx_mds_pic_init(void)
...
@@ -366,7 +435,7 @@ static void __init mpc85xx_mds_pic_init(void)
mpic
=
mpic_alloc
(
np
,
r
.
start
,
mpic
=
mpic_alloc
(
np
,
r
.
start
,
MPIC_PRIMARY
|
MPIC_WANTS_RESET
|
MPIC_BIG_ENDIAN
|
MPIC_PRIMARY
|
MPIC_WANTS_RESET
|
MPIC_BIG_ENDIAN
|
MPIC_BROKEN_FRR_NIRQS
,
MPIC_BROKEN_FRR_NIRQS
|
MPIC_SINGLE_DEST_CPU
,
0
,
256
,
" OpenPIC "
);
0
,
256
,
" OpenPIC "
);
BUG_ON
(
mpic
==
NULL
);
BUG_ON
(
mpic
==
NULL
);
of_node_put
(
np
);
of_node_put
(
np
);
...
@@ -380,7 +449,11 @@ static void __init mpc85xx_mds_pic_init(void)
...
@@ -380,7 +449,11 @@ static void __init mpc85xx_mds_pic_init(void)
if
(
!
np
)
if
(
!
np
)
return
;
return
;
}
}
qe_ic_init
(
np
,
0
,
qe_ic_cascade_muxed_mpic
,
NULL
);
if
(
machine_is
(
p1021_mds
))
qe_ic_init
(
np
,
0
,
qe_ic_cascade_low_mpic
,
qe_ic_cascade_high_mpic
);
else
qe_ic_init
(
np
,
0
,
qe_ic_cascade_muxed_mpic
,
NULL
);
of_node_put
(
np
);
of_node_put
(
np
);
#endif
/* CONFIG_QUICC_ENGINE */
#endif
/* CONFIG_QUICC_ENGINE */
}
}
...
@@ -426,3 +499,26 @@ define_machine(mpc8569_mds) {
...
@@ -426,3 +499,26 @@ define_machine(mpc8569_mds) {
.
pcibios_fixup_bus
=
fsl_pcibios_fixup_bus
,
.
pcibios_fixup_bus
=
fsl_pcibios_fixup_bus
,
#endif
#endif
};
};
static
int
__init
p1021_mds_probe
(
void
)
{
unsigned
long
root
=
of_get_flat_dt_root
();
return
of_flat_dt_is_compatible
(
root
,
"fsl,P1021MDS"
);
}
define_machine
(
p1021_mds
)
{
.
name
=
"P1021 MDS"
,
.
probe
=
p1021_mds_probe
,
.
setup_arch
=
mpc85xx_mds_setup_arch
,
.
init_IRQ
=
mpc85xx_mds_pic_init
,
.
get_irq
=
mpic_get_irq
,
.
restart
=
fsl_rstcr_restart
,
.
calibrate_decr
=
generic_calibrate_decr
,
.
progress
=
udbg_progress
,
#ifdef CONFIG_PCI
.
pcibios_fixup_bus
=
fsl_pcibios_fixup_bus
,
#endif
};
arch/powerpc/sysdev/fsl_msi.c
View file @
ecca1a34
/*
/*
* Copyright (C) 2007-20
08 Freescale Semiconductor, Inc. All rights reserved
.
* Copyright (C) 2007-20
10 Freescale Semiconductor, Inc
.
*
*
* Author: Tony Li <tony.li@freescale.com>
* Author: Tony Li <tony.li@freescale.com>
* Jason Jin <Jason.jin@freescale.com>
* Jason Jin <Jason.jin@freescale.com>
...
@@ -22,14 +22,20 @@
...
@@ -22,14 +22,20 @@
#include <asm/prom.h>
#include <asm/prom.h>
#include <asm/hw_irq.h>
#include <asm/hw_irq.h>
#include <asm/ppc-pci.h>
#include <asm/ppc-pci.h>
#include <asm/mpic.h>
#include "fsl_msi.h"
#include "fsl_msi.h"
LIST_HEAD
(
msi_head
);
struct
fsl_msi_feature
{
struct
fsl_msi_feature
{
u32
fsl_pic_ip
;
u32
fsl_pic_ip
;
u32
msiir_offset
;
u32
msiir_offset
;
};
};
static
struct
fsl_msi
*
fsl_msi
;
struct
fsl_msi_cascade_data
{
struct
fsl_msi
*
msi_data
;
int
index
;
};
static
inline
u32
fsl_msi_read
(
u32
__iomem
*
base
,
unsigned
int
reg
)
static
inline
u32
fsl_msi_read
(
u32
__iomem
*
base
,
unsigned
int
reg
)
{
{
...
@@ -54,10 +60,12 @@ static struct irq_chip fsl_msi_chip = {
...
@@ -54,10 +60,12 @@ static struct irq_chip fsl_msi_chip = {
static
int
fsl_msi_host_map
(
struct
irq_host
*
h
,
unsigned
int
virq
,
static
int
fsl_msi_host_map
(
struct
irq_host
*
h
,
unsigned
int
virq
,
irq_hw_number_t
hw
)
irq_hw_number_t
hw
)
{
{
struct
fsl_msi
*
msi_data
=
h
->
host_data
;
struct
irq_chip
*
chip
=
&
fsl_msi_chip
;
struct
irq_chip
*
chip
=
&
fsl_msi_chip
;
irq_to_desc
(
virq
)
->
status
|=
IRQ_TYPE_EDGE_FALLING
;
irq_to_desc
(
virq
)
->
status
|=
IRQ_TYPE_EDGE_FALLING
;
set_irq_chip_data
(
virq
,
msi_data
);
set_irq_chip_and_handler
(
virq
,
chip
,
handle_edge_irq
);
set_irq_chip_and_handler
(
virq
,
chip
,
handle_edge_irq
);
return
0
;
return
0
;
...
@@ -96,11 +104,12 @@ static int fsl_msi_check_device(struct pci_dev *pdev, int nvec, int type)
...
@@ -96,11 +104,12 @@ static int fsl_msi_check_device(struct pci_dev *pdev, int nvec, int type)
static
void
fsl_teardown_msi_irqs
(
struct
pci_dev
*
pdev
)
static
void
fsl_teardown_msi_irqs
(
struct
pci_dev
*
pdev
)
{
{
struct
msi_desc
*
entry
;
struct
msi_desc
*
entry
;
struct
fsl_msi
*
msi_data
=
fsl_msi
;
struct
fsl_msi
*
msi_data
;
list_for_each_entry
(
entry
,
&
pdev
->
msi_list
,
list
)
{
list_for_each_entry
(
entry
,
&
pdev
->
msi_list
,
list
)
{
if
(
entry
->
irq
==
NO_IRQ
)
if
(
entry
->
irq
==
NO_IRQ
)
continue
;
continue
;
msi_data
=
get_irq_data
(
entry
->
irq
);
set_irq_msi
(
entry
->
irq
,
NULL
);
set_irq_msi
(
entry
->
irq
,
NULL
);
msi_bitmap_free_hwirqs
(
&
msi_data
->
bitmap
,
msi_bitmap_free_hwirqs
(
&
msi_data
->
bitmap
,
virq_to_hw
(
entry
->
irq
),
1
);
virq_to_hw
(
entry
->
irq
),
1
);
...
@@ -111,9 +120,10 @@ static void fsl_teardown_msi_irqs(struct pci_dev *pdev)
...
@@ -111,9 +120,10 @@ static void fsl_teardown_msi_irqs(struct pci_dev *pdev)
}
}
static
void
fsl_compose_msi_msg
(
struct
pci_dev
*
pdev
,
int
hwirq
,
static
void
fsl_compose_msi_msg
(
struct
pci_dev
*
pdev
,
int
hwirq
,
struct
msi_msg
*
msg
)
struct
msi_msg
*
msg
,
struct
fsl_msi
*
fsl_msi_data
)
{
{
struct
fsl_msi
*
msi_data
=
fsl_msi
;
struct
fsl_msi
*
msi_data
=
fsl_msi
_data
;
struct
pci_controller
*
hose
=
pci_bus_to_host
(
pdev
->
bus
);
struct
pci_controller
*
hose
=
pci_bus_to_host
(
pdev
->
bus
);
u32
base
=
0
;
u32
base
=
0
;
...
@@ -130,14 +140,19 @@ static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq,
...
@@ -130,14 +140,19 @@ static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq,
static
int
fsl_setup_msi_irqs
(
struct
pci_dev
*
pdev
,
int
nvec
,
int
type
)
static
int
fsl_setup_msi_irqs
(
struct
pci_dev
*
pdev
,
int
nvec
,
int
type
)
{
{
int
rc
,
hwirq
;
int
rc
,
hwirq
=
-
ENOMEM
;
unsigned
int
virq
;
unsigned
int
virq
;
struct
msi_desc
*
entry
;
struct
msi_desc
*
entry
;
struct
msi_msg
msg
;
struct
msi_msg
msg
;
struct
fsl_msi
*
msi_data
=
fsl_msi
;
struct
fsl_msi
*
msi_data
;
list_for_each_entry
(
entry
,
&
pdev
->
msi_list
,
list
)
{
list_for_each_entry
(
entry
,
&
pdev
->
msi_list
,
list
)
{
hwirq
=
msi_bitmap_alloc_hwirqs
(
&
msi_data
->
bitmap
,
1
);
list_for_each_entry
(
msi_data
,
&
msi_head
,
list
)
{
hwirq
=
msi_bitmap_alloc_hwirqs
(
&
msi_data
->
bitmap
,
1
);
if
(
hwirq
>=
0
)
break
;
}
if
(
hwirq
<
0
)
{
if
(
hwirq
<
0
)
{
rc
=
hwirq
;
rc
=
hwirq
;
pr_debug
(
"%s: fail allocating msi interrupt
\n
"
,
pr_debug
(
"%s: fail allocating msi interrupt
\n
"
,
...
@@ -154,25 +169,31 @@ static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
...
@@ -154,25 +169,31 @@ static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
rc
=
-
ENOSPC
;
rc
=
-
ENOSPC
;
goto
out_free
;
goto
out_free
;
}
}
set_irq_data
(
virq
,
msi_data
);
set_irq_msi
(
virq
,
entry
);
set_irq_msi
(
virq
,
entry
);
fsl_compose_msi_msg
(
pdev
,
hwirq
,
&
msg
);
fsl_compose_msi_msg
(
pdev
,
hwirq
,
&
msg
,
msi_data
);
write_msi_msg
(
virq
,
&
msg
);
write_msi_msg
(
virq
,
&
msg
);
}
}
return
0
;
return
0
;
out_free:
out_free:
/* free by the caller of this function */
return
rc
;
return
rc
;
}
}
static
void
fsl_msi_cascade
(
unsigned
int
irq
,
struct
irq_desc
*
desc
)
static
void
fsl_msi_cascade
(
unsigned
int
irq
,
struct
irq_desc
*
desc
)
{
{
unsigned
int
cascade_irq
;
unsigned
int
cascade_irq
;
struct
fsl_msi
*
msi_data
=
fsl_msi
;
struct
fsl_msi
*
msi_data
;
int
msir_index
=
-
1
;
int
msir_index
=
-
1
;
u32
msir_value
=
0
;
u32
msir_value
=
0
;
u32
intr_index
;
u32
intr_index
;
u32
have_shift
=
0
;
u32
have_shift
=
0
;
struct
fsl_msi_cascade_data
*
cascade_data
;
cascade_data
=
(
struct
fsl_msi_cascade_data
*
)
get_irq_data
(
irq
);
msi_data
=
cascade_data
->
msi_data
;
raw_spin_lock
(
&
desc
->
lock
);
raw_spin_lock
(
&
desc
->
lock
);
if
((
msi_data
->
feature
&
FSL_PIC_IP_MASK
)
==
FSL_PIC_IP_IPIC
)
{
if
((
msi_data
->
feature
&
FSL_PIC_IP_MASK
)
==
FSL_PIC_IP_IPIC
)
{
...
@@ -187,13 +208,13 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
...
@@ -187,13 +208,13 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
if
(
unlikely
(
desc
->
status
&
IRQ_INPROGRESS
))
if
(
unlikely
(
desc
->
status
&
IRQ_INPROGRESS
))
goto
unlock
;
goto
unlock
;
msir_index
=
(
int
)
desc
->
handler_data
;
msir_index
=
cascade_data
->
index
;
if
(
msir_index
>=
NR_MSI_REG
)
if
(
msir_index
>=
NR_MSI_REG
)
cascade_irq
=
NO_IRQ
;
cascade_irq
=
NO_IRQ
;
desc
->
status
|=
IRQ_INPROGRESS
;
desc
->
status
|=
IRQ_INPROGRESS
;
switch
(
fsl_msi
->
feature
&
FSL_PIC_IP_MASK
)
{
switch
(
msi_data
->
feature
&
FSL_PIC_IP_MASK
)
{
case
FSL_PIC_IP_MPIC
:
case
FSL_PIC_IP_MPIC
:
msir_value
=
fsl_msi_read
(
msi_data
->
msi_regs
,
msir_value
=
fsl_msi_read
(
msi_data
->
msi_regs
,
msir_index
*
0x10
);
msir_index
*
0x10
);
...
@@ -229,6 +250,30 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
...
@@ -229,6 +250,30 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
raw_spin_unlock
(
&
desc
->
lock
);
raw_spin_unlock
(
&
desc
->
lock
);
}
}
static
int
fsl_of_msi_remove
(
struct
of_device
*
ofdev
)
{
struct
fsl_msi
*
msi
=
ofdev
->
dev
.
platform_data
;
int
virq
,
i
;
struct
fsl_msi_cascade_data
*
cascade_data
;
if
(
msi
->
list
.
prev
!=
NULL
)
list_del
(
&
msi
->
list
);
for
(
i
=
0
;
i
<
NR_MSI_REG
;
i
++
)
{
virq
=
msi
->
msi_virqs
[
i
];
if
(
virq
!=
NO_IRQ
)
{
cascade_data
=
get_irq_data
(
virq
);
kfree
(
cascade_data
);
irq_dispose_mapping
(
virq
);
}
}
if
(
msi
->
bitmap
.
bitmap
)
msi_bitmap_free
(
&
msi
->
bitmap
);
iounmap
(
msi
->
msi_regs
);
kfree
(
msi
);
return
0
;
}
static
int
__devinit
fsl_of_msi_probe
(
struct
of_device
*
dev
,
static
int
__devinit
fsl_of_msi_probe
(
struct
of_device
*
dev
,
const
struct
of_device_id
*
match
)
const
struct
of_device_id
*
match
)
{
{
...
@@ -239,15 +284,18 @@ static int __devinit fsl_of_msi_probe(struct of_device *dev,
...
@@ -239,15 +284,18 @@ static int __devinit fsl_of_msi_probe(struct of_device *dev,
int
virt_msir
;
int
virt_msir
;
const
u32
*
p
;
const
u32
*
p
;
struct
fsl_msi_feature
*
features
=
match
->
data
;
struct
fsl_msi_feature
*
features
=
match
->
data
;
struct
fsl_msi_cascade_data
*
cascade_data
=
NULL
;
int
len
;
u32
offset
;
printk
(
KERN_DEBUG
"Setting up Freescale MSI support
\n
"
);
printk
(
KERN_DEBUG
"Setting up Freescale MSI support
\n
"
);
msi
=
kzalloc
(
sizeof
(
struct
fsl_msi
),
GFP_KERNEL
);
msi
=
kzalloc
(
sizeof
(
struct
fsl_msi
),
GFP_KERNEL
);
if
(
!
msi
)
{
if
(
!
msi
)
{
dev_err
(
&
dev
->
dev
,
"No memory for MSI structure
\n
"
);
dev_err
(
&
dev
->
dev
,
"No memory for MSI structure
\n
"
);
err
=
-
ENOMEM
;
return
-
ENOMEM
;
goto
error_out
;
}
}
dev
->
dev
.
platform_data
=
msi
;
msi
->
irqhost
=
irq_alloc_host
(
dev
->
dev
.
of_node
,
IRQ_HOST_MAP_LINEAR
,
msi
->
irqhost
=
irq_alloc_host
(
dev
->
dev
.
of_node
,
IRQ_HOST_MAP_LINEAR
,
NR_MSI_IRQS
,
&
fsl_msi_host_ops
,
0
);
NR_MSI_IRQS
,
&
fsl_msi_host_ops
,
0
);
...
@@ -298,27 +346,47 @@ static int __devinit fsl_of_msi_probe(struct of_device *dev,
...
@@ -298,27 +346,47 @@ static int __devinit fsl_of_msi_probe(struct of_device *dev,
err
=
-
EINVAL
;
err
=
-
EINVAL
;
goto
error_out
;
goto
error_out
;
}
}
offset
=
0
;
p
=
of_get_property
(
dev
->
node
,
"msi-available-ranges"
,
&
len
);
if
(
p
)
offset
=
*
p
/
IRQS_PER_MSI_REG
;
count
/=
sizeof
(
u32
);
count
/=
sizeof
(
u32
);
for
(
i
=
0
;
i
<
count
/
2
;
i
++
)
{
for
(
i
=
0
;
i
<
min
(
count
/
2
,
NR_MSI_REG
);
i
++
)
{
if
(
i
>
NR_MSI_REG
)
break
;
virt_msir
=
irq_of_parse_and_map
(
dev
->
dev
.
of_node
,
i
);
virt_msir
=
irq_of_parse_and_map
(
dev
->
dev
.
of_node
,
i
);
if
(
virt_msir
!=
NO_IRQ
)
{
if
(
virt_msir
!=
NO_IRQ
)
{
set_irq_data
(
virt_msir
,
(
void
*
)
i
);
cascade_data
=
kzalloc
(
sizeof
(
struct
fsl_msi_cascade_data
),
GFP_KERNEL
);
if
(
!
cascade_data
)
{
dev_err
(
&
dev
->
dev
,
"No memory for MSI cascade data
\n
"
);
err
=
-
ENOMEM
;
goto
error_out
;
}
msi
->
msi_virqs
[
i
]
=
virt_msir
;
cascade_data
->
index
=
i
+
offset
;
cascade_data
->
msi_data
=
msi
;
set_irq_data
(
virt_msir
,
(
void
*
)
cascade_data
);
set_irq_chained_handler
(
virt_msir
,
fsl_msi_cascade
);
set_irq_chained_handler
(
virt_msir
,
fsl_msi_cascade
);
}
}
}
}
fsl_msi
=
msi
;
list_add_tail
(
&
msi
->
list
,
&
msi_head
)
;
WARN_ON
(
ppc_md
.
setup_msi_irqs
);
/* The multiple setting ppc_md.setup_msi_irqs will not harm things */
ppc_md
.
setup_msi_irqs
=
fsl_setup_msi_irqs
;
if
(
!
ppc_md
.
setup_msi_irqs
)
{
ppc_md
.
teardown_msi_irqs
=
fsl_teardown_msi_irqs
;
ppc_md
.
setup_msi_irqs
=
fsl_setup_msi_irqs
;
ppc_md
.
msi_check_device
=
fsl_msi_check_device
;
ppc_md
.
teardown_msi_irqs
=
fsl_teardown_msi_irqs
;
ppc_md
.
msi_check_device
=
fsl_msi_check_device
;
}
else
if
(
ppc_md
.
setup_msi_irqs
!=
fsl_setup_msi_irqs
)
{
dev_err
(
&
dev
->
dev
,
"Different MSI driver already installed!
\n
"
);
err
=
-
ENODEV
;
goto
error_out
;
}
return
0
;
return
0
;
error_out:
error_out:
kfree
(
msi
);
fsl_of_msi_remove
(
dev
);
return
err
;
return
err
;
}
}
...
@@ -351,6 +419,7 @@ static struct of_platform_driver fsl_of_msi_driver = {
...
@@ -351,6 +419,7 @@ static struct of_platform_driver fsl_of_msi_driver = {
.
of_match_table
=
fsl_of_msi_ids
,
.
of_match_table
=
fsl_of_msi_ids
,
},
},
.
probe
=
fsl_of_msi_probe
,
.
probe
=
fsl_of_msi_probe
,
.
remove
=
fsl_of_msi_remove
,
};
};
static
__init
int
fsl_of_msi_init
(
void
)
static
__init
int
fsl_of_msi_init
(
void
)
...
...
arch/powerpc/sysdev/fsl_msi.h
View file @
ecca1a34
...
@@ -32,8 +32,11 @@ struct fsl_msi {
...
@@ -32,8 +32,11 @@ struct fsl_msi {
u32
msi_addr_hi
;
u32
msi_addr_hi
;
void
__iomem
*
msi_regs
;
void
__iomem
*
msi_regs
;
u32
feature
;
u32
feature
;
int
msi_virqs
[
NR_MSI_REG
];
struct
msi_bitmap
bitmap
;
struct
msi_bitmap
bitmap
;
struct
list_head
list
;
/* support multiple MSI banks */
};
};
#endif
/* _POWERPC_SYSDEV_FSL_MSI_H */
#endif
/* _POWERPC_SYSDEV_FSL_MSI_H */
...
...
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