Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xiphi1978
linux
提交
6ad29246
L
linux
项目概览
xiphi1978
/
linux
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
L
linux
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
6ad29246
编写于
6月 03, 2014
作者:
R
Rafael J. Wysocki
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'pm-clk'
* pm-clk: clk: new basic clk type for fractional divider
上级
2770b8b1
e2d0e90f
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
167 addition
and
0 deletion
+167
-0
drivers/clk/Makefile
drivers/clk/Makefile
+1
-0
drivers/clk/clk-fractional-divider.c
drivers/clk/clk-fractional-divider.c
+135
-0
include/linux/clk-provider.h
include/linux/clk-provider.h
+31
-0
未找到文件。
drivers/clk/Makefile
浏览文件 @
6ad29246
...
...
@@ -8,6 +8,7 @@ obj-$(CONFIG_COMMON_CLK) += clk-fixed-rate.o
obj-$(CONFIG_COMMON_CLK)
+=
clk-gate.o
obj-$(CONFIG_COMMON_CLK)
+=
clk-mux.o
obj-$(CONFIG_COMMON_CLK)
+=
clk-composite.o
obj-$(CONFIG_COMMON_CLK)
+=
clk-fractional-divider.o
# hardware specific clock types
# please keep this section sorted lexicographically by file/directory path name
...
...
drivers/clk/clk-fractional-divider.c
0 → 100644
浏览文件 @
6ad29246
/*
* Copyright (C) 2014 Intel Corporation
*
* 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.
*
* Adjustable fractional divider clock implementation.
* Output rate = (m / n) * parent_rate.
*/
#include <linux/clk-provider.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/gcd.h>
#define to_clk_fd(_hw) container_of(_hw, struct clk_fractional_divider, hw)
static
unsigned
long
clk_fd_recalc_rate
(
struct
clk_hw
*
hw
,
unsigned
long
parent_rate
)
{
struct
clk_fractional_divider
*
fd
=
to_clk_fd
(
hw
);
unsigned
long
flags
=
0
;
u32
val
,
m
,
n
;
u64
ret
;
if
(
fd
->
lock
)
spin_lock_irqsave
(
fd
->
lock
,
flags
);
val
=
clk_readl
(
fd
->
reg
);
if
(
fd
->
lock
)
spin_unlock_irqrestore
(
fd
->
lock
,
flags
);
m
=
(
val
&
fd
->
mmask
)
>>
fd
->
mshift
;
n
=
(
val
&
fd
->
nmask
)
>>
fd
->
nshift
;
ret
=
parent_rate
*
m
;
do_div
(
ret
,
n
);
return
ret
;
}
static
long
clk_fd_round_rate
(
struct
clk_hw
*
hw
,
unsigned
long
rate
,
unsigned
long
*
prate
)
{
struct
clk_fractional_divider
*
fd
=
to_clk_fd
(
hw
);
unsigned
maxn
=
(
fd
->
nmask
>>
fd
->
nshift
)
+
1
;
unsigned
div
;
if
(
!
rate
||
rate
>=
*
prate
)
return
*
prate
;
div
=
gcd
(
*
prate
,
rate
);
while
((
*
prate
/
div
)
>
maxn
)
{
div
<<=
1
;
rate
<<=
1
;
}
return
rate
;
}
static
int
clk_fd_set_rate
(
struct
clk_hw
*
hw
,
unsigned
long
rate
,
unsigned
long
parent_rate
)
{
struct
clk_fractional_divider
*
fd
=
to_clk_fd
(
hw
);
unsigned
long
flags
=
0
;
unsigned
long
div
;
unsigned
n
,
m
;
u32
val
;
div
=
gcd
(
parent_rate
,
rate
);
m
=
rate
/
div
;
n
=
parent_rate
/
div
;
if
(
fd
->
lock
)
spin_lock_irqsave
(
fd
->
lock
,
flags
);
val
=
clk_readl
(
fd
->
reg
);
val
&=
~
(
fd
->
mmask
|
fd
->
nmask
);
val
|=
(
m
<<
fd
->
mshift
)
|
(
n
<<
fd
->
nshift
);
clk_writel
(
val
,
fd
->
reg
);
if
(
fd
->
lock
)
spin_unlock_irqrestore
(
fd
->
lock
,
flags
);
return
0
;
}
const
struct
clk_ops
clk_fractional_divider_ops
=
{
.
recalc_rate
=
clk_fd_recalc_rate
,
.
round_rate
=
clk_fd_round_rate
,
.
set_rate
=
clk_fd_set_rate
,
};
EXPORT_SYMBOL_GPL
(
clk_fractional_divider_ops
);
struct
clk
*
clk_register_fractional_divider
(
struct
device
*
dev
,
const
char
*
name
,
const
char
*
parent_name
,
unsigned
long
flags
,
void
__iomem
*
reg
,
u8
mshift
,
u8
mwidth
,
u8
nshift
,
u8
nwidth
,
u8
clk_divider_flags
,
spinlock_t
*
lock
)
{
struct
clk_fractional_divider
*
fd
;
struct
clk_init_data
init
;
struct
clk
*
clk
;
fd
=
kzalloc
(
sizeof
(
*
fd
),
GFP_KERNEL
);
if
(
!
fd
)
{
dev_err
(
dev
,
"could not allocate fractional divider clk
\n
"
);
return
ERR_PTR
(
-
ENOMEM
);
}
init
.
name
=
name
;
init
.
ops
=
&
clk_fractional_divider_ops
;
init
.
flags
=
flags
|
CLK_IS_BASIC
;
init
.
parent_names
=
parent_name
?
&
parent_name
:
NULL
;
init
.
num_parents
=
parent_name
?
1
:
0
;
fd
->
reg
=
reg
;
fd
->
mshift
=
mshift
;
fd
->
mmask
=
(
BIT
(
mwidth
)
-
1
)
<<
mshift
;
fd
->
nshift
=
nshift
;
fd
->
nmask
=
(
BIT
(
nwidth
)
-
1
)
<<
nshift
;
fd
->
flags
=
clk_divider_flags
;
fd
->
lock
=
lock
;
fd
->
hw
.
init
=
&
init
;
clk
=
clk_register
(
dev
,
&
fd
->
hw
);
if
(
IS_ERR
(
clk
))
kfree
(
fd
);
return
clk
;
}
EXPORT_SYMBOL_GPL
(
clk_register_fractional_divider
);
include/linux/clk-provider.h
浏览文件 @
6ad29246
...
...
@@ -413,6 +413,37 @@ struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
const
char
*
parent_name
,
unsigned
long
flags
,
unsigned
int
mult
,
unsigned
int
div
);
/**
* struct clk_fractional_divider - adjustable fractional divider clock
*
* @hw: handle between common and hardware-specific interfaces
* @reg: register containing the divider
* @mshift: shift to the numerator bit field
* @mwidth: width of the numerator bit field
* @nshift: shift to the denominator bit field
* @nwidth: width of the denominator bit field
* @lock: register lock
*
* Clock with adjustable fractional divider affecting its output frequency.
*/
struct
clk_fractional_divider
{
struct
clk_hw
hw
;
void
__iomem
*
reg
;
u8
mshift
;
u32
mmask
;
u8
nshift
;
u32
nmask
;
u8
flags
;
spinlock_t
*
lock
;
};
extern
const
struct
clk_ops
clk_fractional_divider_ops
;
struct
clk
*
clk_register_fractional_divider
(
struct
device
*
dev
,
const
char
*
name
,
const
char
*
parent_name
,
unsigned
long
flags
,
void
__iomem
*
reg
,
u8
mshift
,
u8
mwidth
,
u8
nshift
,
u8
nwidth
,
u8
clk_divider_flags
,
spinlock_t
*
lock
);
/***
* struct clk_composite - aggregate clock of mux, divider and gate clocks
*
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录