Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
613dac31
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,发现更多精彩内容 >>
提交
613dac31
编写于
9月 22, 2012
作者:
M
Mark Brown
浏览文件
操作
浏览文件
下载
差异文件
Merge remote-tracking branches 'regmap/topic/cache' and 'regmap/topic/irq' into regmap-next
上级
5698bd75
4d879514
81380739
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
83 addition
and
26 deletion
+83
-26
drivers/base/regmap/regmap-irq.c
drivers/base/regmap/regmap-irq.c
+75
-17
drivers/base/regmap/regmap.c
drivers/base/regmap/regmap.c
+4
-9
drivers/mfd/wm8994-irq.c
drivers/mfd/wm8994-irq.c
+1
-0
include/linux/regmap.h
include/linux/regmap.h
+3
-0
未找到文件。
drivers/base/regmap/regmap-irq.c
浏览文件 @
613dac31
...
...
@@ -16,12 +16,14 @@
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/irqdomain.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include "internal.h"
struct
regmap_irq_chip_data
{
struct
mutex
lock
;
struct
irq_chip
irq_chip
;
struct
regmap
*
map
;
const
struct
regmap_irq_chip
*
chip
;
...
...
@@ -59,6 +61,14 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
struct
regmap_irq_chip_data
*
d
=
irq_data_get_irq_chip_data
(
data
);
struct
regmap
*
map
=
d
->
map
;
int
i
,
ret
;
u32
reg
;
if
(
d
->
chip
->
runtime_pm
)
{
ret
=
pm_runtime_get_sync
(
map
->
dev
);
if
(
ret
<
0
)
dev_err
(
map
->
dev
,
"IRQ sync failed to resume: %d
\n
"
,
ret
);
}
/*
* If there's been a change in the mask write it back to the
...
...
@@ -66,15 +76,22 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
* suppress pointless writes.
*/
for
(
i
=
0
;
i
<
d
->
chip
->
num_regs
;
i
++
)
{
ret
=
regmap_update_bits
(
d
->
map
,
d
->
chip
->
mask_base
+
(
i
*
map
->
reg_stride
*
d
->
irq_reg_stride
),
reg
=
d
->
chip
->
mask_base
+
(
i
*
map
->
reg_stride
*
d
->
irq_reg_stride
);
if
(
d
->
chip
->
mask_invert
)
ret
=
regmap_update_bits
(
d
->
map
,
reg
,
d
->
mask_buf_def
[
i
],
~
d
->
mask_buf
[
i
]);
else
ret
=
regmap_update_bits
(
d
->
map
,
reg
,
d
->
mask_buf_def
[
i
],
d
->
mask_buf
[
i
]);
if
(
ret
!=
0
)
dev_err
(
d
->
map
->
dev
,
"Failed to sync masks in %x
\n
"
,
d
->
chip
->
mask_base
+
(
i
*
map
->
reg_stride
)
);
reg
);
}
if
(
d
->
chip
->
runtime_pm
)
pm_runtime_put
(
map
->
dev
);
/* If we've changed our wakeup count propagate it to the parent */
if
(
d
->
wake_count
<
0
)
for
(
i
=
d
->
wake_count
;
i
<
0
;
i
++
)
...
...
@@ -128,8 +145,7 @@ static int regmap_irq_set_wake(struct irq_data *data, unsigned int on)
return
0
;
}
static
struct
irq_chip
regmap_irq_chip
=
{
.
name
=
"regmap"
,
static
const
struct
irq_chip
regmap_irq_chip
=
{
.
irq_bus_lock
=
regmap_irq_lock
,
.
irq_bus_sync_unlock
=
regmap_irq_sync_unlock
,
.
irq_disable
=
regmap_irq_disable
,
...
...
@@ -144,6 +160,16 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
struct
regmap
*
map
=
data
->
map
;
int
ret
,
i
;
bool
handled
=
false
;
u32
reg
;
if
(
chip
->
runtime_pm
)
{
ret
=
pm_runtime_get_sync
(
map
->
dev
);
if
(
ret
<
0
)
{
dev_err
(
map
->
dev
,
"IRQ thread failed to resume: %d
\n
"
,
ret
);
return
IRQ_NONE
;
}
}
/*
* Ignore masked IRQs and ack if we need to; we ack early so
...
...
@@ -160,20 +186,20 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
if
(
ret
!=
0
)
{
dev_err
(
map
->
dev
,
"Failed to read IRQ status: %d
\n
"
,
ret
);
if
(
chip
->
runtime_pm
)
pm_runtime_put
(
map
->
dev
);
return
IRQ_NONE
;
}
data
->
status_buf
[
i
]
&=
~
data
->
mask_buf
[
i
];
if
(
data
->
status_buf
[
i
]
&&
chip
->
ack_base
)
{
ret
=
regmap_write
(
map
,
chip
->
ack_base
+
(
i
*
map
->
reg_stride
*
data
->
irq_reg_stride
),
data
->
status_buf
[
i
]);
reg
=
chip
->
ack_base
+
(
i
*
map
->
reg_stride
*
data
->
irq_reg_stride
);
ret
=
regmap_write
(
map
,
reg
,
data
->
status_buf
[
i
]);
if
(
ret
!=
0
)
dev_err
(
map
->
dev
,
"Failed to ack 0x%x: %d
\n
"
,
chip
->
ack_base
+
(
i
*
map
->
reg_stride
),
ret
);
reg
,
ret
);
}
}
...
...
@@ -185,6 +211,9 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
}
}
if
(
chip
->
runtime_pm
)
pm_runtime_put
(
map
->
dev
);
if
(
handled
)
return
IRQ_HANDLED
;
else
...
...
@@ -197,7 +226,7 @@ static int regmap_irq_map(struct irq_domain *h, unsigned int virq,
struct
regmap_irq_chip_data
*
data
=
h
->
host_data
;
irq_set_chip_data
(
virq
,
data
);
irq_set_chip
_and_handler
(
virq
,
&
regmap_irq_chip
,
handle_edge_irq
);
irq_set_chip
(
virq
,
&
data
->
irq_chip
);
irq_set_nested_thread
(
virq
,
1
);
/* ARM needs us to explicitly flag the IRQ as valid
...
...
@@ -238,6 +267,7 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
struct
regmap_irq_chip_data
*
d
;
int
i
;
int
ret
=
-
ENOMEM
;
u32
reg
;
for
(
i
=
0
;
i
<
chip
->
num_irqs
;
i
++
)
{
if
(
chip
->
irqs
[
i
].
reg_offset
%
map
->
reg_stride
)
...
...
@@ -284,6 +314,13 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
goto
err_alloc
;
}
d
->
irq_chip
=
regmap_irq_chip
;
d
->
irq_chip
.
name
=
chip
->
name
;
if
(
!
chip
->
wake_base
)
{
d
->
irq_chip
.
irq_set_wake
=
NULL
;
d
->
irq_chip
.
flags
|=
IRQCHIP_MASK_ON_SUSPEND
|
IRQCHIP_SKIP_SET_WAKE
;
}
d
->
irq
=
irq
;
d
->
map
=
map
;
d
->
chip
=
chip
;
...
...
@@ -303,16 +340,37 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
/* Mask all the interrupts by default */
for
(
i
=
0
;
i
<
chip
->
num_regs
;
i
++
)
{
d
->
mask_buf
[
i
]
=
d
->
mask_buf_def
[
i
];
ret
=
regmap_write
(
map
,
chip
->
mask_base
+
(
i
*
map
->
reg_stride
*
d
->
irq_reg_stride
),
d
->
mask_buf
[
i
]);
reg
=
chip
->
mask_base
+
(
i
*
map
->
reg_stride
*
d
->
irq_reg_stride
);
if
(
chip
->
mask_invert
)
ret
=
regmap_update_bits
(
map
,
reg
,
d
->
mask_buf
[
i
],
~
d
->
mask_buf
[
i
]);
else
ret
=
regmap_update_bits
(
map
,
reg
,
d
->
mask_buf
[
i
],
d
->
mask_buf
[
i
]);
if
(
ret
!=
0
)
{
dev_err
(
map
->
dev
,
"Failed to set masks in 0x%x: %d
\n
"
,
chip
->
mask_base
+
(
i
*
map
->
reg_stride
)
,
ret
);
reg
,
ret
);
goto
err_alloc
;
}
}
/* Wake is disabled by default */
if
(
d
->
wake_buf
)
{
for
(
i
=
0
;
i
<
chip
->
num_regs
;
i
++
)
{
d
->
wake_buf
[
i
]
=
d
->
mask_buf_def
[
i
];
reg
=
chip
->
wake_base
+
(
i
*
map
->
reg_stride
*
d
->
irq_reg_stride
);
ret
=
regmap_update_bits
(
map
,
reg
,
d
->
wake_buf
[
i
],
d
->
wake_buf
[
i
]);
if
(
ret
!=
0
)
{
dev_err
(
map
->
dev
,
"Failed to set masks in 0x%x: %d
\n
"
,
reg
,
ret
);
goto
err_alloc
;
}
}
}
if
(
irq_base
)
d
->
domain
=
irq_domain_add_legacy
(
map
->
dev
->
of_node
,
chip
->
num_irqs
,
irq_base
,
0
,
...
...
drivers/base/regmap/regmap.c
浏览文件 @
613dac31
...
...
@@ -659,13 +659,12 @@ EXPORT_SYMBOL_GPL(devm_regmap_init);
* new cache. This can be used to restore the cache to defaults or to
* update the cache configuration to reflect runtime discovery of the
* hardware.
*
* No explicit locking is done here, the user needs to ensure that
* this function will not race with other calls to regmap.
*/
int
regmap_reinit_cache
(
struct
regmap
*
map
,
const
struct
regmap_config
*
config
)
{
int
ret
;
map
->
lock
(
map
);
regcache_exit
(
map
);
regmap_debugfs_exit
(
map
);
...
...
@@ -681,11 +680,7 @@ int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config)
map
->
cache_bypass
=
false
;
map
->
cache_only
=
false
;
ret
=
regcache_init
(
map
,
config
);
map
->
unlock
(
map
);
return
ret
;
return
regcache_init
(
map
,
config
);
}
EXPORT_SYMBOL_GPL
(
regmap_reinit_cache
);
...
...
drivers/mfd/wm8994-irq.c
浏览文件 @
613dac31
...
...
@@ -135,6 +135,7 @@ static struct regmap_irq_chip wm8994_irq_chip = {
.
status_base
=
WM8994_INTERRUPT_STATUS_1
,
.
mask_base
=
WM8994_INTERRUPT_STATUS_1_MASK
,
.
ack_base
=
WM8994_INTERRUPT_STATUS_1
,
.
runtime_pm
=
true
,
};
int
wm8994_irq_init
(
struct
wm8994
*
wm8994
)
...
...
include/linux/regmap.h
浏览文件 @
613dac31
...
...
@@ -285,6 +285,7 @@ struct regmap_irq {
* @ack_base: Base ack address. If zero then the chip is clear on read.
* @wake_base: Base address for wake enables. If zero unsupported.
* @irq_reg_stride: Stride to use for chips where registers are not contiguous.
* @runtime_pm: Hold a runtime PM lock on the device when accessing it.
*
* @num_regs: Number of registers in each control bank.
* @irqs: Descriptors for individual IRQs. Interrupt numbers are
...
...
@@ -299,6 +300,8 @@ struct regmap_irq_chip {
unsigned
int
ack_base
;
unsigned
int
wake_base
;
unsigned
int
irq_reg_stride
;
unsigned
int
mask_invert
;
bool
runtime_pm
;
int
num_regs
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录