Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
d4f2016f
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看板
提交
d4f2016f
编写于
11月 18, 2014
作者:
M
Michael Turquette
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'clk-next-shmobile' into clk-next
上级
40ba3f0f
bfadcadf
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
113 addition
and
18 deletion
+113
-18
Documentation/devicetree/bindings/clock/renesas,cpg-div6-clocks.txt
...ion/devicetree/bindings/clock/renesas,cpg-div6-clocks.txt
+12
-6
drivers/clk/shmobile/clk-div6.c
drivers/clk/shmobile/clk-div6.c
+101
-12
未找到文件。
Documentation/devicetree/bindings/clock/renesas,cpg-div6-clocks.txt
浏览文件 @
d4f2016f
...
...
@@ -7,11 +7,16 @@ to 64.
Required Properties:
- compatible: Must be one of the following
- "renesas,r8a73a4-div6-clock" for R8A73A4 (R-Mobile APE6) DIV6 clocks
- "renesas,r8a7740-div6-clock" for R8A7740 (R-Mobile A1) DIV6 clocks
- "renesas,r8a7790-div6-clock" for R8A7790 (R-Car H2) DIV6 clocks
- "renesas,r8a7791-div6-clock" for R8A7791 (R-Car M2) DIV6 clocks
- "renesas,sh73a0-div6-clock" for SH73A0 (SH-Mobile AG5) DIV6 clocks
- "renesas,cpg-div6-clock" for generic DIV6 clocks
- reg: Base address and length of the memory resource used by the DIV6 clock
- clocks: Reference to the parent clock
- clocks: Reference to the parent clock(s); either one, four, or eight
clocks must be specified. For clocks with multiple parents, invalid
settings must be specified as "<0>".
- #clock-cells: Must be 0
- clock-output-names: The name of the clock as a free-form string
...
...
@@ -19,10 +24,11 @@ Required Properties:
Example
-------
sd2_clk: sd2_clk@e6150078 {
compatible = "renesas,r8a7790-div6-clock", "renesas,cpg-div6-clock";
reg = <0 0xe6150078 0 4>;
clocks = <&pll1_div2_clk>;
sdhi2_clk: sdhi2_clk@e615007c {
compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock";
reg = <0 0xe615007c 0 4>;
clocks = <&pll1_div2_clk>, <&cpg_clocks R8A73A4_CLK_PLL2S>,
<0>, <&extal2_clk>;
#clock-cells = <0>;
clock-output-names = "sd
2
";
clock-output-names = "sd
hi2ck
";
};
drivers/clk/shmobile/clk-div6.c
浏览文件 @
d4f2016f
...
...
@@ -32,6 +32,9 @@ struct div6_clock {
struct
clk_hw
hw
;
void
__iomem
*
reg
;
unsigned
int
div
;
u32
src_shift
;
u32
src_width
;
u8
*
parents
;
};
#define to_div6_clock(_hw) container_of(_hw, struct div6_clock, hw)
...
...
@@ -39,8 +42,11 @@ struct div6_clock {
static
int
cpg_div6_clock_enable
(
struct
clk_hw
*
hw
)
{
struct
div6_clock
*
clock
=
to_div6_clock
(
hw
);
u32
val
;
clk_writel
(
CPG_DIV6_DIV
(
clock
->
div
-
1
),
clock
->
reg
);
val
=
(
clk_readl
(
clock
->
reg
)
&
~
(
CPG_DIV6_DIV_MASK
|
CPG_DIV6_CKSTP
))
|
CPG_DIV6_DIV
(
clock
->
div
-
1
);
clk_writel
(
val
,
clock
->
reg
);
return
0
;
}
...
...
@@ -52,7 +58,7 @@ static void cpg_div6_clock_disable(struct clk_hw *hw)
/* DIV6 clocks require the divisor field to be non-zero when stopping
* the clock.
*/
clk_writel
(
CPG_DIV6_CKSTP
|
CPG_DIV6_DIV
(
CPG_DIV6_DIV_MASK
)
,
clk_writel
(
clk_readl
(
clock
->
reg
)
|
CPG_DIV6_CKSTP
|
CPG_DIV6_DIV_MASK
,
clock
->
reg
);
}
...
...
@@ -94,12 +100,53 @@ static int cpg_div6_clock_set_rate(struct clk_hw *hw, unsigned long rate,
{
struct
div6_clock
*
clock
=
to_div6_clock
(
hw
);
unsigned
int
div
=
cpg_div6_clock_calc_div
(
rate
,
parent_rate
);
u32
val
;
clock
->
div
=
div
;
val
=
clk_readl
(
clock
->
reg
)
&
~
CPG_DIV6_DIV_MASK
;
/* Only program the new divisor if the clock isn't stopped. */
if
(
!
(
clk_readl
(
clock
->
reg
)
&
CPG_DIV6_CKSTP
))
clk_writel
(
CPG_DIV6_DIV
(
clock
->
div
-
1
),
clock
->
reg
);
if
(
!
(
val
&
CPG_DIV6_CKSTP
))
clk_writel
(
val
|
CPG_DIV6_DIV
(
clock
->
div
-
1
),
clock
->
reg
);
return
0
;
}
static
u8
cpg_div6_clock_get_parent
(
struct
clk_hw
*
hw
)
{
struct
div6_clock
*
clock
=
to_div6_clock
(
hw
);
unsigned
int
i
;
u8
hw_index
;
if
(
clock
->
src_width
==
0
)
return
0
;
hw_index
=
(
clk_readl
(
clock
->
reg
)
>>
clock
->
src_shift
)
&
(
BIT
(
clock
->
src_width
)
-
1
);
for
(
i
=
0
;
i
<
__clk_get_num_parents
(
hw
->
clk
);
i
++
)
{
if
(
clock
->
parents
[
i
]
==
hw_index
)
return
i
;
}
pr_err
(
"%s: %s DIV6 clock set to invalid parent %u
\n
"
,
__func__
,
__clk_get_name
(
hw
->
clk
),
hw_index
);
return
0
;
}
static
int
cpg_div6_clock_set_parent
(
struct
clk_hw
*
hw
,
u8
index
)
{
struct
div6_clock
*
clock
=
to_div6_clock
(
hw
);
u8
hw_index
;
u32
mask
;
if
(
index
>=
__clk_get_num_parents
(
hw
->
clk
))
return
-
EINVAL
;
mask
=
~
((
BIT
(
clock
->
src_width
)
-
1
)
<<
clock
->
src_shift
);
hw_index
=
clock
->
parents
[
index
];
clk_writel
((
clk_readl
(
clock
->
reg
)
&
mask
)
|
(
hw_index
<<
clock
->
src_shift
),
clock
->
reg
);
return
0
;
}
...
...
@@ -108,6 +155,8 @@ static const struct clk_ops cpg_div6_clock_ops = {
.
enable
=
cpg_div6_clock_enable
,
.
disable
=
cpg_div6_clock_disable
,
.
is_enabled
=
cpg_div6_clock_is_enabled
,
.
get_parent
=
cpg_div6_clock_get_parent
,
.
set_parent
=
cpg_div6_clock_set_parent
,
.
recalc_rate
=
cpg_div6_clock_recalc_rate
,
.
round_rate
=
cpg_div6_clock_round_rate
,
.
set_rate
=
cpg_div6_clock_set_rate
,
...
...
@@ -115,20 +164,33 @@ static const struct clk_ops cpg_div6_clock_ops = {
static
void
__init
cpg_div6_clock_init
(
struct
device_node
*
np
)
{
unsigned
int
num_parents
,
valid_parents
;
const
char
**
parent_names
;
struct
clk_init_data
init
;
struct
div6_clock
*
clock
;
const
char
*
parent_name
;
const
char
*
name
;
struct
clk
*
clk
;
unsigned
int
i
;
int
ret
;
clock
=
kzalloc
(
sizeof
(
*
clock
),
GFP_KERNEL
);
if
(
!
clock
)
{
pr_err
(
"%s: failed to allocate %s DIV6 clock
\n
"
,
if
(
!
clock
)
return
;
num_parents
=
of_clk_get_parent_count
(
np
);
if
(
num_parents
<
1
)
{
pr_err
(
"%s: no parent found for %s DIV6 clock
\n
"
,
__func__
,
np
->
name
);
return
;
}
clock
->
parents
=
kmalloc_array
(
num_parents
,
sizeof
(
*
clock
->
parents
),
GFP_KERNEL
);
parent_names
=
kmalloc_array
(
num_parents
,
sizeof
(
*
parent_names
),
GFP_KERNEL
);
if
(
!
parent_names
)
return
;
/* Remap the clock register and read the divisor. Disabling the
* clock overwrites the divisor, so we need to cache its value for the
* enable operation.
...
...
@@ -150,9 +212,34 @@ static void __init cpg_div6_clock_init(struct device_node *np)
goto
error
;
}
parent_name
=
of_clk_get_parent_name
(
np
,
0
);
if
(
parent_name
==
NULL
)
{
pr_err
(
"%s: failed to get %s DIV6 clock parent name
\n
"
,
for
(
i
=
0
,
valid_parents
=
0
;
i
<
num_parents
;
i
++
)
{
const
char
*
name
=
of_clk_get_parent_name
(
np
,
i
);
if
(
name
)
{
parent_names
[
valid_parents
]
=
name
;
clock
->
parents
[
valid_parents
]
=
i
;
valid_parents
++
;
}
}
switch
(
num_parents
)
{
case
1
:
/* fixed parent clock */
clock
->
src_shift
=
clock
->
src_width
=
0
;
break
;
case
4
:
/* clock with EXSRC bits 6-7 */
clock
->
src_shift
=
6
;
clock
->
src_width
=
2
;
break
;
case
8
:
/* VCLK with EXSRC bits 12-14 */
clock
->
src_shift
=
12
;
clock
->
src_width
=
3
;
break
;
default:
pr_err
(
"%s: invalid number of parents for DIV6 clock %s
\n
"
,
__func__
,
np
->
name
);
goto
error
;
}
...
...
@@ -161,8 +248,8 @@ static void __init cpg_div6_clock_init(struct device_node *np)
init
.
name
=
name
;
init
.
ops
=
&
cpg_div6_clock_ops
;
init
.
flags
=
CLK_IS_BASIC
;
init
.
parent_names
=
&
parent_name
;
init
.
num_parents
=
1
;
init
.
parent_names
=
parent_names
;
init
.
num_parents
=
valid_parents
;
clock
->
hw
.
init
=
&
init
;
...
...
@@ -175,11 +262,13 @@ static void __init cpg_div6_clock_init(struct device_node *np)
of_clk_add_provider
(
np
,
of_clk_src_simple_get
,
clk
);
kfree
(
parent_names
);
return
;
error:
if
(
clock
->
reg
)
iounmap
(
clock
->
reg
);
kfree
(
parent_names
);
kfree
(
clock
);
}
CLK_OF_DECLARE
(
cpg_div6_clk
,
"renesas,cpg-div6-clock"
,
cpg_div6_clock_init
);
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录