Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
56d8adc5
cloud-kernel
项目概览
openanolis
/
cloud-kernel
大约 1 年 前同步成功
通知
158
Star
36
Fork
7
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
10
列表
看板
标记
里程碑
合并请求
2
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
cloud-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
10
Issue
10
列表
看板
标记
里程碑
合并请求
2
合并请求
2
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
56d8adc5
编写于
12月 09, 2010
作者:
B
Benjamin Herrenschmidt
浏览文件
操作
浏览文件
下载
差异文件
Merge remote branch 'jwb/next' into next
上级
f4b98415
ee2ffd8b
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
439 addition
and
26 deletion
+439
-26
Documentation/powerpc/dts-bindings/4xx/cpm.txt
Documentation/powerpc/dts-bindings/4xx/cpm.txt
+52
-0
arch/powerpc/Kconfig
arch/powerpc/Kconfig
+10
-3
arch/powerpc/boot/dts/canyonlands.dts
arch/powerpc/boot/dts/canyonlands.dts
+9
-22
arch/powerpc/boot/dts/kilauea.dts
arch/powerpc/boot/dts/kilauea.dts
+9
-0
arch/powerpc/configs/40x/kilauea_defconfig
arch/powerpc/configs/40x/kilauea_defconfig
+5
-0
arch/powerpc/configs/44x/canyonlands_defconfig
arch/powerpc/configs/44x/canyonlands_defconfig
+3
-0
arch/powerpc/platforms/44x/Makefile
arch/powerpc/platforms/44x/Makefile
+4
-1
arch/powerpc/sysdev/Makefile
arch/powerpc/sysdev/Makefile
+1
-0
arch/powerpc/sysdev/ppc4xx_cpm.c
arch/powerpc/sysdev/ppc4xx_cpm.c
+346
-0
未找到文件。
Documentation/powerpc/dts-bindings/4xx/cpm.txt
0 → 100644
浏览文件 @
56d8adc5
PPC4xx Clock Power Management (CPM) node
Required properties:
- compatible : compatible list, currently only "ibm,cpm"
- dcr-access-method : "native"
- dcr-reg : < DCR register range >
Optional properties:
- er-offset : All 4xx SoCs with a CPM controller have
one of two different order for the CPM
registers. Some have the CPM registers
in the following order (ER,FR,SR). The
others have them in the following order
(SR,ER,FR). For the second case set
er-offset = <1>.
- unused-units : specifier consist of one cell. For each
bit in the cell, the corresponding bit
in CPM will be set to turn off unused
devices.
- idle-doze : specifier consist of one cell. For each
bit in the cell, the corresponding bit
in CPM will be set to turn off unused
devices. This is usually just CPM[CPU].
- standby : specifier consist of one cell. For each
bit in the cell, the corresponding bit
in CPM will be set on standby and
restored on resume.
- suspend : specifier consist of one cell. For each
bit in the cell, the corresponding bit
in CPM will be set on suspend (mem) and
restored on resume. Note, for standby
and suspend the corresponding bits can
be different or the same. Usually for
standby only class 2 and 3 units are set.
However, the interface does not care.
If they are the same, the additional
power saving will be seeing if support
is available to put the DDR in self
refresh mode and any additional power
saving techniques for the specific SoC.
Example:
CPM0: cpm {
compatible = "ibm,cpm";
dcr-access-method = "native";
dcr-reg = <0x160 0x003>;
er-offset = <0>;
unused-units = <0x00000100>;
idle-doze = <0x02000000>;
standby = <0xfeff0000>;
suspend = <0xfeff791d>;
};
arch/powerpc/Kconfig
浏览文件 @
56d8adc5
...
...
@@ -212,7 +212,7 @@ config ARCH_HIBERNATION_POSSIBLE
config ARCH_SUSPEND_POSSIBLE
def_bool y
depends on ADB_PMU || PPC_EFIKA || PPC_LITE5200 || PPC_83xx || \
PPC_85xx || PPC_86xx || PPC_PSERIES
PPC_85xx || PPC_86xx || PPC_PSERIES
|| 44x || 40x
config PPC_DCR_NATIVE
bool
...
...
@@ -598,13 +598,11 @@ config EXTRA_TARGETS
If unsure, leave blank
if !44x || BROKEN
config ARCH_WANTS_FREEZER_CONTROL
def_bool y
depends on ADB_PMU
source kernel/power/Kconfig
endif
config SECCOMP
bool "Enable seccomp to safely compute untrusted bytecode"
...
...
@@ -685,6 +683,15 @@ config FSL_PMC
Freescale MPC85xx/MPC86xx power management controller support
(suspend/resume). For MPC83xx see platforms/83xx/suspend.c
config PPC4xx_CPM
bool
default y
depends on SUSPEND && (44x || 40x)
help
PPC4xx Clock Power Management (CPM) support (suspend/resume).
It also enables support for two different idle states (idle-wait
and idle-doze).
config 4xx_SOC
bool
...
...
arch/powerpc/boot/dts/canyonlands.dts
浏览文件 @
56d8adc5
...
...
@@ -105,6 +105,15 @@
dcr
-
reg
=
<
0x00c
0x002
>;
};
CPM0
:
cpm
{
compatible
=
"ibm,cpm"
;
dcr
-
access
-
method
=
"native"
;
dcr
-
reg
=
<
0x160
0x003
>;
unused
-
units
=
<
0x00000100
>;
idle
-
doze
=
<
0x02000000
>;
standby
=
<
0xfeff791d
>;
};
L2C0
:
l2c
{
compatible
=
"ibm,l2-cache-460ex"
,
"ibm,l2-cache"
;
dcr
-
reg
=
<
0x020
0x008
/*
Internal
SRAM
DCR
's */
...
...
@@ -270,28 +279,6 @@
interrupts
=
<
0x1
0x4
>;
};
UART2
:
serial
@
ef600500
{
device_type
=
"serial"
;
compatible
=
"ns16550"
;
reg
=
<
0xef600500
0x00000008
>;
virtual
-
reg
=
<
0xef600500
>;
clock
-
frequency
=
<
0
>;
/*
Filled
in
by
U
-
Boot
*/
current
-
speed
=
<
0
>;
/*
Filled
in
by
U
-
Boot
*/
interrupt
-
parent
=
<&
UIC1
>;
interrupts
=
<
28
0x4
>;
};
UART3
:
serial
@
ef600600
{
device_type
=
"serial"
;
compatible
=
"ns16550"
;
reg
=
<
0xef600600
0x00000008
>;
virtual
-
reg
=
<
0xef600600
>;
clock
-
frequency
=
<
0
>;
/*
Filled
in
by
U
-
Boot
*/
current
-
speed
=
<
0
>;
/*
Filled
in
by
U
-
Boot
*/
interrupt
-
parent
=
<&
UIC1
>;
interrupts
=
<
29
0x4
>;
};
IIC0
:
i2c
@
ef600700
{
compatible
=
"ibm,iic-460ex"
,
"ibm,iic"
;
reg
=
<
0xef600700
0x00000014
>;
...
...
arch/powerpc/boot/dts/kilauea.dts
浏览文件 @
56d8adc5
...
...
@@ -82,6 +82,15 @@
interrupt
-
parent
=
<&
UIC0
>;
};
CPM0
:
cpm
{
compatible
=
"ibm,cpm"
;
dcr
-
access
-
method
=
"native"
;
dcr
-
reg
=
<
0x0b0
0x003
>;
unused
-
units
=
<
0x00000000
>;
idle
-
doze
=
<
0x02000000
>;
standby
=
<
0xe3e74800
>;
};
plb
{
compatible
=
"ibm,plb-405ex"
,
"ibm,plb4"
;
#
address
-
cells
=
<
1
>;
...
...
arch/powerpc/configs/40x/kilauea_defconfig
浏览文件 @
56d8adc5
...
...
@@ -12,6 +12,8 @@ CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_BLK_DEV_BSG is not set
CONFIG_KILAUEA=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
# CONFIG_WALNUT is not set
CONFIG_SPARSE_IRQ=y
CONFIG_PCI=y
...
...
@@ -42,6 +44,9 @@ CONFIG_MTD_PHYSMAP_OF=y
CONFIG_MTD_NAND=y
CONFIG_MTD_NAND_NDFC=y
CONFIG_PROC_DEVICETREE=y
CONFIG_PM=y
CONFIG_SUSPEND=y
CONFIG_PPC4xx_CPM=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=35000
# CONFIG_MISC_DEVICES is not set
...
...
arch/powerpc/configs/44x/canyonlands_defconfig
浏览文件 @
56d8adc5
...
...
@@ -42,6 +42,9 @@ CONFIG_MTD_PHYSMAP_OF=y
CONFIG_MTD_NAND=y
CONFIG_MTD_NAND_NDFC=y
CONFIG_PROC_DEVICETREE=y
CONFIG_PM=y
CONFIG_SUSPEND=y
CONFIG_PPC4xx_CPM=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=35000
# CONFIG_MISC_DEVICES is not set
...
...
arch/powerpc/platforms/44x/Makefile
浏览文件 @
56d8adc5
obj-$(CONFIG_44x)
:=
misc_44x.o idle.o
obj-$(CONFIG_44x)
+=
misc_44x.o
ifneq
($(CONFIG_PPC4xx_CPM),y)
obj-$(CONFIG_44x)
+=
idle.o
endif
obj-$(CONFIG_PPC44x_SIMPLE)
+=
ppc44x_simple.o
obj-$(CONFIG_EBONY)
+=
ebony.o
obj-$(CONFIG_SAM440EP)
+=
sam440ep.o
...
...
arch/powerpc/sysdev/Makefile
浏览文件 @
56d8adc5
...
...
@@ -41,6 +41,7 @@ obj-$(CONFIG_OF_RTC) += of_rtc.o
ifeq
($(CONFIG_PCI),y)
obj-$(CONFIG_4xx)
+=
ppc4xx_pci.o
endif
obj-$(CONFIG_PPC4xx_CPM)
+=
ppc4xx_cpm.o
obj-$(CONFIG_PPC4xx_GPIO)
+=
ppc4xx_gpio.o
obj-$(CONFIG_CPM)
+=
cpm_common.o
...
...
arch/powerpc/sysdev/ppc4xx_cpm.c
0 → 100644
浏览文件 @
56d8adc5
/*
* PowerPC 4xx Clock and Power Management
*
* Copyright (C) 2010, Applied Micro Circuits Corporation
* Victor Gallardo (vgallardo@apm.com)
*
* Based on arch/powerpc/platforms/44x/idle.c:
* Jerone Young <jyoung5@us.ibm.com>
* Copyright 2008 IBM Corp.
*
* Based on arch/powerpc/sysdev/fsl_pmc.c:
* Anton Vorontsov <avorontsov@ru.mvista.com>
* Copyright 2009 MontaVista Software, Inc.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <linux/kernel.h>
#include <linux/of_platform.h>
#include <linux/sysfs.h>
#include <linux/cpu.h>
#include <linux/suspend.h>
#include <asm/dcr.h>
#include <asm/dcr-native.h>
#include <asm/machdep.h>
#define CPM_ER 0
#define CPM_FR 1
#define CPM_SR 2
#define CPM_IDLE_WAIT 0
#define CPM_IDLE_DOZE 1
struct
cpm
{
dcr_host_t
dcr_host
;
unsigned
int
dcr_offset
[
3
];
unsigned
int
powersave_off
;
unsigned
int
unused
;
unsigned
int
idle_doze
;
unsigned
int
standby
;
unsigned
int
suspend
;
};
static
struct
cpm
cpm
;
struct
cpm_idle_mode
{
unsigned
int
enabled
;
const
char
*
name
;
};
static
struct
cpm_idle_mode
idle_mode
[]
=
{
[
CPM_IDLE_WAIT
]
=
{
1
,
"wait"
},
/* default */
[
CPM_IDLE_DOZE
]
=
{
0
,
"doze"
},
};
static
unsigned
int
cpm_set
(
unsigned
int
cpm_reg
,
unsigned
int
mask
)
{
unsigned
int
value
;
/* CPM controller supports 3 different types of sleep interface
* known as class 1, 2 and 3. For class 1 units, they are
* unconditionally put to sleep when the corresponding CPM bit is
* set. For class 2 and 3 units this is not case; if they can be
* put to to sleep, they will. Here we do not verify, we just
* set them and expect them to eventually go off when they can.
*/
value
=
dcr_read
(
cpm
.
dcr_host
,
cpm
.
dcr_offset
[
cpm_reg
]);
dcr_write
(
cpm
.
dcr_host
,
cpm
.
dcr_offset
[
cpm_reg
],
value
|
mask
);
/* return old state, to restore later if needed */
return
value
;
}
static
void
cpm_idle_wait
(
void
)
{
unsigned
long
msr_save
;
/* save off initial state */
msr_save
=
mfmsr
();
/* sync required when CPM0_ER[CPU] is set */
mb
();
/* set wait state MSR */
mtmsr
(
msr_save
|
MSR_WE
|
MSR_EE
|
MSR_CE
|
MSR_DE
);
isync
();
/* return to initial state */
mtmsr
(
msr_save
);
isync
();
}
static
void
cpm_idle_sleep
(
unsigned
int
mask
)
{
unsigned
int
er_save
;
/* update CPM_ER state */
er_save
=
cpm_set
(
CPM_ER
,
mask
);
/* go to wait state so that CPM0_ER[CPU] can take effect */
cpm_idle_wait
();
/* restore CPM_ER state */
dcr_write
(
cpm
.
dcr_host
,
cpm
.
dcr_offset
[
CPM_ER
],
er_save
);
}
static
void
cpm_idle_doze
(
void
)
{
cpm_idle_sleep
(
cpm
.
idle_doze
);
}
static
void
cpm_idle_config
(
int
mode
)
{
int
i
;
if
(
idle_mode
[
mode
].
enabled
)
return
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
idle_mode
);
i
++
)
idle_mode
[
i
].
enabled
=
0
;
idle_mode
[
mode
].
enabled
=
1
;
}
static
ssize_t
cpm_idle_show
(
struct
kobject
*
kobj
,
struct
kobj_attribute
*
attr
,
char
*
buf
)
{
char
*
s
=
buf
;
int
i
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
idle_mode
);
i
++
)
{
if
(
idle_mode
[
i
].
enabled
)
s
+=
sprintf
(
s
,
"[%s] "
,
idle_mode
[
i
].
name
);
else
s
+=
sprintf
(
s
,
"%s "
,
idle_mode
[
i
].
name
);
}
*
(
s
-
1
)
=
'\n'
;
/* convert the last space to a newline */
return
s
-
buf
;
}
static
ssize_t
cpm_idle_store
(
struct
kobject
*
kobj
,
struct
kobj_attribute
*
attr
,
const
char
*
buf
,
size_t
n
)
{
int
i
;
char
*
p
;
int
len
;
p
=
memchr
(
buf
,
'\n'
,
n
);
len
=
p
?
p
-
buf
:
n
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
idle_mode
);
i
++
)
{
if
(
strncmp
(
buf
,
idle_mode
[
i
].
name
,
len
)
==
0
)
{
cpm_idle_config
(
i
);
return
n
;
}
}
return
-
EINVAL
;
}
static
struct
kobj_attribute
cpm_idle_attr
=
__ATTR
(
idle
,
0644
,
cpm_idle_show
,
cpm_idle_store
);
static
void
cpm_idle_config_sysfs
(
void
)
{
struct
sys_device
*
sys_dev
;
unsigned
long
ret
;
sys_dev
=
get_cpu_sysdev
(
0
);
ret
=
sysfs_create_file
(
&
sys_dev
->
kobj
,
&
cpm_idle_attr
.
attr
);
if
(
ret
)
printk
(
KERN_WARNING
"cpm: failed to create idle sysfs entry
\n
"
);
}
static
void
cpm_idle
(
void
)
{
if
(
idle_mode
[
CPM_IDLE_DOZE
].
enabled
)
cpm_idle_doze
();
else
cpm_idle_wait
();
}
static
int
cpm_suspend_valid
(
suspend_state_t
state
)
{
switch
(
state
)
{
case
PM_SUSPEND_STANDBY
:
return
!!
cpm
.
standby
;
case
PM_SUSPEND_MEM
:
return
!!
cpm
.
suspend
;
default:
return
0
;
}
}
static
void
cpm_suspend_standby
(
unsigned
int
mask
)
{
unsigned
long
tcr_save
;
/* disable decrement interrupt */
tcr_save
=
mfspr
(
SPRN_TCR
);
mtspr
(
SPRN_TCR
,
tcr_save
&
~
TCR_DIE
);
/* go to sleep state */
cpm_idle_sleep
(
mask
);
/* restore decrement interrupt */
mtspr
(
SPRN_TCR
,
tcr_save
);
}
static
int
cpm_suspend_enter
(
suspend_state_t
state
)
{
switch
(
state
)
{
case
PM_SUSPEND_STANDBY
:
cpm_suspend_standby
(
cpm
.
standby
);
break
;
case
PM_SUSPEND_MEM
:
cpm_suspend_standby
(
cpm
.
suspend
);
break
;
}
return
0
;
}
static
struct
platform_suspend_ops
cpm_suspend_ops
=
{
.
valid
=
cpm_suspend_valid
,
.
enter
=
cpm_suspend_enter
,
};
static
int
cpm_get_uint_property
(
struct
device_node
*
np
,
const
char
*
name
)
{
int
len
;
const
unsigned
int
*
prop
=
of_get_property
(
np
,
name
,
&
len
);
if
(
prop
==
NULL
||
len
<
sizeof
(
u32
))
return
0
;
return
*
prop
;
}
static
int
__init
cpm_init
(
void
)
{
struct
device_node
*
np
;
int
dcr_base
,
dcr_len
;
int
ret
=
0
;
if
(
!
cpm
.
powersave_off
)
{
cpm_idle_config
(
CPM_IDLE_WAIT
);
ppc_md
.
power_save
=
&
cpm_idle
;
}
np
=
of_find_compatible_node
(
NULL
,
NULL
,
"ibm,cpm"
);
if
(
!
np
)
{
ret
=
-
EINVAL
;
goto
out
;
}
dcr_base
=
dcr_resource_start
(
np
,
0
);
dcr_len
=
dcr_resource_len
(
np
,
0
);
if
(
dcr_base
==
0
||
dcr_len
==
0
)
{
printk
(
KERN_ERR
"cpm: could not parse dcr property for %s
\n
"
,
np
->
full_name
);
ret
=
-
EINVAL
;
goto
out
;
}
cpm
.
dcr_host
=
dcr_map
(
np
,
dcr_base
,
dcr_len
);
if
(
!
DCR_MAP_OK
(
cpm
.
dcr_host
))
{
printk
(
KERN_ERR
"cpm: failed to map dcr property for %s
\n
"
,
np
->
full_name
);
ret
=
-
EINVAL
;
goto
out
;
}
/* All 4xx SoCs with a CPM controller have one of two
* different order for the CPM registers. Some have the
* CPM registers in the following order (ER,FR,SR). The
* others have them in the following order (SR,ER,FR).
*/
if
(
cpm_get_uint_property
(
np
,
"er-offset"
)
==
0
)
{
cpm
.
dcr_offset
[
CPM_ER
]
=
0
;
cpm
.
dcr_offset
[
CPM_FR
]
=
1
;
cpm
.
dcr_offset
[
CPM_SR
]
=
2
;
}
else
{
cpm
.
dcr_offset
[
CPM_ER
]
=
1
;
cpm
.
dcr_offset
[
CPM_FR
]
=
2
;
cpm
.
dcr_offset
[
CPM_SR
]
=
0
;
}
/* Now let's see what IPs to turn off for the following modes */
cpm
.
unused
=
cpm_get_uint_property
(
np
,
"unused-units"
);
cpm
.
idle_doze
=
cpm_get_uint_property
(
np
,
"idle-doze"
);
cpm
.
standby
=
cpm_get_uint_property
(
np
,
"standby"
);
cpm
.
suspend
=
cpm_get_uint_property
(
np
,
"suspend"
);
/* If some IPs are unused let's turn them off now */
if
(
cpm
.
unused
)
{
cpm_set
(
CPM_ER
,
cpm
.
unused
);
cpm_set
(
CPM_FR
,
cpm
.
unused
);
}
/* Now let's export interfaces */
if
(
!
cpm
.
powersave_off
&&
cpm
.
idle_doze
)
cpm_idle_config_sysfs
();
if
(
cpm
.
standby
||
cpm
.
suspend
)
suspend_set_ops
(
&
cpm_suspend_ops
);
out:
if
(
np
)
of_node_put
(
np
);
return
ret
;
}
late_initcall
(
cpm_init
);
static
int
__init
cpm_powersave_off
(
char
*
arg
)
{
cpm
.
powersave_off
=
1
;
return
0
;
}
__setup
(
"powersave=off"
,
cpm_powersave_off
);
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录