Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
c0cc6fe1
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看板
提交
c0cc6fe1
编写于
4月 10, 2012
作者:
M
Mark Brown
浏览文件
操作
浏览文件
下载
差异文件
Merge branches 'regmap-core', 'regmap-mmio' and 'regmap-naming' into regmap-stride
上级
00341028
d939fb9a
851960ba
abec95ad
变更
11
隐藏空白更改
内联
并排
Showing
11 changed file
with
394 addition
and
69 deletion
+394
-69
drivers/base/regmap/Kconfig
drivers/base/regmap/Kconfig
+3
-0
drivers/base/regmap/Makefile
drivers/base/regmap/Makefile
+1
-0
drivers/base/regmap/internal.h
drivers/base/regmap/internal.h
+16
-5
drivers/base/regmap/regcache-rbtree.c
drivers/base/regmap/regcache-rbtree.c
+2
-2
drivers/base/regmap/regcache.c
drivers/base/regmap/regcache.c
+10
-10
drivers/base/regmap/regmap-debugfs.c
drivers/base/regmap/regmap-debugfs.c
+11
-3
drivers/base/regmap/regmap-i2c.c
drivers/base/regmap/regmap-i2c.c
+8
-5
drivers/base/regmap/regmap-mmio.c
drivers/base/regmap/regmap-mmio.c
+211
-0
drivers/base/regmap/regmap-spi.c
drivers/base/regmap/regmap-spi.c
+8
-5
drivers/base/regmap/regmap.c
drivers/base/regmap/regmap.c
+103
-36
include/linux/regmap.h
include/linux/regmap.h
+21
-3
未找到文件。
drivers/base/regmap/Kconfig
浏览文件 @
c0cc6fe1
...
...
@@ -14,5 +14,8 @@ config REGMAP_I2C
config REGMAP_SPI
tristate
config REGMAP_MMIO
tristate
config REGMAP_IRQ
bool
drivers/base/regmap/Makefile
浏览文件 @
c0cc6fe1
...
...
@@ -3,4 +3,5 @@ obj-$(CONFIG_REGMAP) += regcache-rbtree.o regcache-lzo.o
obj-$(CONFIG_DEBUG_FS)
+=
regmap-debugfs.o
obj-$(CONFIG_REGMAP_I2C)
+=
regmap-i2c.o
obj-$(CONFIG_REGMAP_SPI)
+=
regmap-spi.o
obj-$(CONFIG_REGMAP_MMIO)
+=
regmap-mmio.o
obj-$(CONFIG_REGMAP_IRQ)
+=
regmap-irq.o
drivers/base/regmap/internal.h
浏览文件 @
c0cc6fe1
...
...
@@ -26,21 +26,29 @@ struct regmap_format {
size_t
val_bytes
;
void
(
*
format_write
)(
struct
regmap
*
map
,
unsigned
int
reg
,
unsigned
int
val
);
void
(
*
format_reg
)(
void
*
buf
,
unsigned
int
reg
);
void
(
*
format_val
)(
void
*
buf
,
unsigned
int
val
);
void
(
*
format_reg
)(
void
*
buf
,
unsigned
int
reg
,
unsigned
int
shift
);
void
(
*
format_val
)(
void
*
buf
,
unsigned
int
val
,
unsigned
int
shift
);
unsigned
int
(
*
parse_val
)(
void
*
buf
);
};
typedef
void
(
*
regmap_lock
)(
struct
regmap
*
map
);
typedef
void
(
*
regmap_unlock
)(
struct
regmap
*
map
);
struct
regmap
{
struct
mutex
lock
;
struct
mutex
mutex
;
spinlock_t
spinlock
;
regmap_lock
lock
;
regmap_unlock
unlock
;
struct
device
*
dev
;
/* Device we do I/O on */
void
*
work_buf
;
/* Scratch buffer used to format I/O */
struct
regmap_format
format
;
/* Buffer format */
const
struct
regmap_bus
*
bus
;
void
*
bus_context
;
#ifdef CONFIG_DEBUG_FS
struct
dentry
*
debugfs
;
const
char
*
debugfs_name
;
#endif
unsigned
int
max_register
;
...
...
@@ -52,6 +60,9 @@ struct regmap {
u8
read_flag_mask
;
u8
write_flag_mask
;
/* number of bits to (left) shift the reg value when formatting*/
int
reg_shift
;
/* regcache specific members */
const
struct
regcache_ops
*
cache_ops
;
enum
regcache_type
cache_type
;
...
...
@@ -101,11 +112,11 @@ int _regmap_write(struct regmap *map, unsigned int reg,
#ifdef CONFIG_DEBUG_FS
extern
void
regmap_debugfs_initcall
(
void
);
extern
void
regmap_debugfs_init
(
struct
regmap
*
map
);
extern
void
regmap_debugfs_init
(
struct
regmap
*
map
,
const
char
*
name
);
extern
void
regmap_debugfs_exit
(
struct
regmap
*
map
);
#else
static
inline
void
regmap_debugfs_initcall
(
void
)
{
}
static
inline
void
regmap_debugfs_init
(
struct
regmap
*
map
)
{
}
static
inline
void
regmap_debugfs_init
(
struct
regmap
*
map
,
const
char
*
name
)
{
}
static
inline
void
regmap_debugfs_exit
(
struct
regmap
*
map
)
{
}
#endif
...
...
drivers/base/regmap/regcache-rbtree.c
浏览文件 @
c0cc6fe1
...
...
@@ -140,7 +140,7 @@ static int rbtree_show(struct seq_file *s, void *ignored)
int
registers
=
0
;
int
average
;
m
utex_lock
(
&
map
->
lock
);
m
ap
->
lock
(
map
);
for
(
node
=
rb_first
(
&
rbtree_ctx
->
root
);
node
!=
NULL
;
node
=
rb_next
(
node
))
{
...
...
@@ -161,7 +161,7 @@ static int rbtree_show(struct seq_file *s, void *ignored)
seq_printf
(
s
,
"%d nodes, %d registers, average %d registers
\n
"
,
nodes
,
registers
,
average
);
m
utex_unlock
(
&
map
->
lock
);
m
ap
->
unlock
(
map
);
return
0
;
}
...
...
drivers/base/regmap/regcache.c
浏览文件 @
c0cc6fe1
...
...
@@ -264,7 +264,7 @@ int regcache_sync(struct regmap *map)
BUG_ON
(
!
map
->
cache_ops
||
!
map
->
cache_ops
->
sync
);
m
utex_lock
(
&
map
->
lock
);
m
ap
->
lock
(
map
);
/* Remember the initial bypass state */
bypass
=
map
->
cache_bypass
;
dev_dbg
(
map
->
dev
,
"Syncing %s cache
\n
"
,
...
...
@@ -296,7 +296,7 @@ int regcache_sync(struct regmap *map)
trace_regcache_sync
(
map
->
dev
,
name
,
"stop"
);
/* Restore the bypass state */
map
->
cache_bypass
=
bypass
;
m
utex_unlock
(
&
map
->
lock
);
m
ap
->
unlock
(
map
);
return
ret
;
}
...
...
@@ -323,7 +323,7 @@ int regcache_sync_region(struct regmap *map, unsigned int min,
BUG_ON
(
!
map
->
cache_ops
||
!
map
->
cache_ops
->
sync
);
m
utex_lock
(
&
map
->
lock
);
m
ap
->
lock
(
map
);
/* Remember the initial bypass state */
bypass
=
map
->
cache_bypass
;
...
...
@@ -342,7 +342,7 @@ int regcache_sync_region(struct regmap *map, unsigned int min,
trace_regcache_sync
(
map
->
dev
,
name
,
"stop region"
);
/* Restore the bypass state */
map
->
cache_bypass
=
bypass
;
m
utex_unlock
(
&
map
->
lock
);
m
ap
->
unlock
(
map
);
return
ret
;
}
...
...
@@ -362,11 +362,11 @@ EXPORT_SYMBOL_GPL(regcache_sync_region);
*/
void
regcache_cache_only
(
struct
regmap
*
map
,
bool
enable
)
{
m
utex_lock
(
&
map
->
lock
);
m
ap
->
lock
(
map
);
WARN_ON
(
map
->
cache_bypass
&&
enable
);
map
->
cache_only
=
enable
;
trace_regmap_cache_only
(
map
->
dev
,
enable
);
m
utex_unlock
(
&
map
->
lock
);
m
ap
->
unlock
(
map
);
}
EXPORT_SYMBOL_GPL
(
regcache_cache_only
);
...
...
@@ -381,9 +381,9 @@ EXPORT_SYMBOL_GPL(regcache_cache_only);
*/
void
regcache_mark_dirty
(
struct
regmap
*
map
)
{
m
utex_lock
(
&
map
->
lock
);
m
ap
->
lock
(
map
);
map
->
cache_dirty
=
true
;
m
utex_unlock
(
&
map
->
lock
);
m
ap
->
unlock
(
map
);
}
EXPORT_SYMBOL_GPL
(
regcache_mark_dirty
);
...
...
@@ -400,11 +400,11 @@ EXPORT_SYMBOL_GPL(regcache_mark_dirty);
*/
void
regcache_cache_bypass
(
struct
regmap
*
map
,
bool
enable
)
{
m
utex_lock
(
&
map
->
lock
);
m
ap
->
lock
(
map
);
WARN_ON
(
map
->
cache_only
&&
enable
);
map
->
cache_bypass
=
enable
;
trace_regmap_cache_bypass
(
map
->
dev
,
enable
);
m
utex_unlock
(
&
map
->
lock
);
m
ap
->
unlock
(
map
);
}
EXPORT_SYMBOL_GPL
(
regcache_cache_bypass
);
...
...
drivers/base/regmap/regmap-debugfs.c
浏览文件 @
c0cc6fe1
...
...
@@ -242,10 +242,17 @@ static const struct file_operations regmap_access_fops = {
.
llseek
=
default_llseek
,
};
void
regmap_debugfs_init
(
struct
regmap
*
map
)
void
regmap_debugfs_init
(
struct
regmap
*
map
,
const
char
*
name
)
{
map
->
debugfs
=
debugfs_create_dir
(
dev_name
(
map
->
dev
),
regmap_debugfs_root
);
if
(
name
)
{
map
->
debugfs_name
=
kasprintf
(
GFP_KERNEL
,
"%s-%s"
,
dev_name
(
map
->
dev
),
name
);
name
=
map
->
debugfs_name
;
}
else
{
name
=
dev_name
(
map
->
dev
);
}
map
->
debugfs
=
debugfs_create_dir
(
name
,
regmap_debugfs_root
);
if
(
!
map
->
debugfs
)
{
dev_warn
(
map
->
dev
,
"Failed to create debugfs directory
\n
"
);
return
;
...
...
@@ -274,6 +281,7 @@ void regmap_debugfs_init(struct regmap *map)
void
regmap_debugfs_exit
(
struct
regmap
*
map
)
{
debugfs_remove_recursive
(
map
->
debugfs
);
kfree
(
map
->
debugfs_name
);
}
void
regmap_debugfs_initcall
(
void
)
...
...
drivers/base/regmap/regmap-i2c.c
浏览文件 @
c0cc6fe1
...
...
@@ -15,8 +15,9 @@
#include <linux/module.h>
#include <linux/init.h>
static
int
regmap_i2c_write
(
struct
device
*
dev
,
const
void
*
data
,
size_t
count
)
static
int
regmap_i2c_write
(
void
*
context
,
const
void
*
data
,
size_t
count
)
{
struct
device
*
dev
=
context
;
struct
i2c_client
*
i2c
=
to_i2c_client
(
dev
);
int
ret
;
...
...
@@ -29,10 +30,11 @@ static int regmap_i2c_write(struct device *dev, const void *data, size_t count)
return
-
EIO
;
}
static
int
regmap_i2c_gather_write
(
struct
device
*
dev
,
static
int
regmap_i2c_gather_write
(
void
*
context
,
const
void
*
reg
,
size_t
reg_size
,
const
void
*
val
,
size_t
val_size
)
{
struct
device
*
dev
=
context
;
struct
i2c_client
*
i2c
=
to_i2c_client
(
dev
);
struct
i2c_msg
xfer
[
2
];
int
ret
;
...
...
@@ -62,10 +64,11 @@ static int regmap_i2c_gather_write(struct device *dev,
return
-
EIO
;
}
static
int
regmap_i2c_read
(
struct
device
*
dev
,
static
int
regmap_i2c_read
(
void
*
context
,
const
void
*
reg
,
size_t
reg_size
,
void
*
val
,
size_t
val_size
)
{
struct
device
*
dev
=
context
;
struct
i2c_client
*
i2c
=
to_i2c_client
(
dev
);
struct
i2c_msg
xfer
[
2
];
int
ret
;
...
...
@@ -107,7 +110,7 @@ static struct regmap_bus regmap_i2c = {
struct
regmap
*
regmap_init_i2c
(
struct
i2c_client
*
i2c
,
const
struct
regmap_config
*
config
)
{
return
regmap_init
(
&
i2c
->
dev
,
&
regmap_i2c
,
config
);
return
regmap_init
(
&
i2c
->
dev
,
&
regmap_i2c
,
&
i2c
->
dev
,
config
);
}
EXPORT_SYMBOL_GPL
(
regmap_init_i2c
);
...
...
@@ -124,7 +127,7 @@ EXPORT_SYMBOL_GPL(regmap_init_i2c);
struct
regmap
*
devm_regmap_init_i2c
(
struct
i2c_client
*
i2c
,
const
struct
regmap_config
*
config
)
{
return
devm_regmap_init
(
&
i2c
->
dev
,
&
regmap_i2c
,
config
);
return
devm_regmap_init
(
&
i2c
->
dev
,
&
regmap_i2c
,
&
i2c
->
dev
,
config
);
}
EXPORT_SYMBOL_GPL
(
devm_regmap_init_i2c
);
...
...
drivers/base/regmap/regmap-mmio.c
0 → 100644
浏览文件 @
c0cc6fe1
/*
* Register map access API - MMIO support
*
* Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
*/
#include <linux/err.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/slab.h>
struct
regmap_mmio_context
{
void
__iomem
*
regs
;
unsigned
val_bytes
;
};
static
int
regmap_mmio_gather_write
(
void
*
context
,
const
void
*
reg
,
size_t
reg_size
,
const
void
*
val
,
size_t
val_size
)
{
struct
regmap_mmio_context
*
ctx
=
context
;
u32
offset
;
BUG_ON
(
reg_size
!=
4
);
offset
=
be32_to_cpup
(
reg
);
while
(
val_size
)
{
switch
(
ctx
->
val_bytes
)
{
case
1
:
writeb
(
*
(
u8
*
)
val
,
ctx
->
regs
+
offset
);
break
;
case
2
:
writew
(
be16_to_cpup
(
val
),
ctx
->
regs
+
offset
);
break
;
case
4
:
writel
(
be32_to_cpup
(
val
),
ctx
->
regs
+
offset
);
break
;
#ifdef CONFIG_64BIT
case
8
:
writeq
(
be64_to_cpup
(
val
),
ctx
->
regs
+
offset
);
break
;
#endif
default:
/* Should be caught by regmap_mmio_check_config */
BUG
();
}
val_size
-=
ctx
->
val_bytes
;
val
+=
ctx
->
val_bytes
;
offset
+=
ctx
->
val_bytes
;
}
return
0
;
}
static
int
regmap_mmio_write
(
void
*
context
,
const
void
*
data
,
size_t
count
)
{
BUG_ON
(
count
<
4
);
return
regmap_mmio_gather_write
(
context
,
data
,
4
,
data
+
4
,
count
-
4
);
}
static
int
regmap_mmio_read
(
void
*
context
,
const
void
*
reg
,
size_t
reg_size
,
void
*
val
,
size_t
val_size
)
{
struct
regmap_mmio_context
*
ctx
=
context
;
u32
offset
;
BUG_ON
(
reg_size
!=
4
);
offset
=
be32_to_cpup
(
reg
);
while
(
val_size
)
{
switch
(
ctx
->
val_bytes
)
{
case
1
:
*
(
u8
*
)
val
=
readb
(
ctx
->
regs
+
offset
);
break
;
case
2
:
*
(
u16
*
)
val
=
cpu_to_be16
(
readw
(
ctx
->
regs
+
offset
));
break
;
case
4
:
*
(
u32
*
)
val
=
cpu_to_be32
(
readl
(
ctx
->
regs
+
offset
));
break
;
#ifdef CONFIG_64BIT
case
8
:
*
(
u64
*
)
val
=
cpu_to_be32
(
readq
(
ctx
->
regs
+
offset
));
break
;
#endif
default:
/* Should be caught by regmap_mmio_check_config */
BUG
();
}
val_size
-=
ctx
->
val_bytes
;
val
+=
ctx
->
val_bytes
;
offset
+=
ctx
->
val_bytes
;
}
return
0
;
}
static
void
regmap_mmio_free_context
(
void
*
context
)
{
kfree
(
context
);
}
static
struct
regmap_bus
regmap_mmio
=
{
.
fast_io
=
true
,
.
write
=
regmap_mmio_write
,
.
gather_write
=
regmap_mmio_gather_write
,
.
read
=
regmap_mmio_read
,
.
free_context
=
regmap_mmio_free_context
,
};
struct
regmap_mmio_context
*
regmap_mmio_gen_context
(
void
__iomem
*
regs
,
const
struct
regmap_config
*
config
)
{
struct
regmap_mmio_context
*
ctx
;
if
(
config
->
reg_bits
!=
32
)
return
ERR_PTR
(
-
EINVAL
);
if
(
config
->
pad_bits
)
return
ERR_PTR
(
-
EINVAL
);
switch
(
config
->
val_bits
)
{
case
8
:
case
16
:
case
32
:
#ifdef CONFIG_64BIT
case
64
:
#endif
break
;
default:
return
ERR_PTR
(
-
EINVAL
);
}
ctx
=
kzalloc
(
GFP_KERNEL
,
sizeof
(
*
ctx
));
if
(
!
ctx
)
return
ERR_PTR
(
-
ENOMEM
);
ctx
->
regs
=
regs
;
ctx
->
val_bytes
=
config
->
val_bits
/
8
;
return
ctx
;
}
/**
* regmap_init_mmio(): Initialise register map
*
* @dev: Device that will be interacted with
* @regs: Pointer to memory-mapped IO region
* @config: Configuration for register map
*
* The return value will be an ERR_PTR() on error or a valid pointer to
* a struct regmap.
*/
struct
regmap
*
regmap_init_mmio
(
struct
device
*
dev
,
void
__iomem
*
regs
,
const
struct
regmap_config
*
config
)
{
struct
regmap_mmio_context
*
ctx
;
ctx
=
regmap_mmio_gen_context
(
regs
,
config
);
if
(
IS_ERR
(
ctx
))
return
ERR_CAST
(
ctx
);
return
regmap_init
(
dev
,
&
regmap_mmio
,
ctx
,
config
);
}
EXPORT_SYMBOL_GPL
(
regmap_init_mmio
);
/**
* devm_regmap_init_mmio(): Initialise managed register map
*
* @dev: Device that will be interacted with
* @regs: Pointer to memory-mapped IO region
* @config: Configuration for register map
*
* The return value will be an ERR_PTR() on error or a valid pointer
* to a struct regmap. The regmap will be automatically freed by the
* device management code.
*/
struct
regmap
*
devm_regmap_init_mmio
(
struct
device
*
dev
,
void
__iomem
*
regs
,
const
struct
regmap_config
*
config
)
{
struct
regmap_mmio_context
*
ctx
;
ctx
=
regmap_mmio_gen_context
(
regs
,
config
);
if
(
IS_ERR
(
ctx
))
return
ERR_CAST
(
ctx
);
return
devm_regmap_init
(
dev
,
&
regmap_mmio
,
ctx
,
config
);
}
EXPORT_SYMBOL_GPL
(
devm_regmap_init_mmio
);
MODULE_LICENSE
(
"GPL v2"
);
drivers/base/regmap/regmap-spi.c
浏览文件 @
c0cc6fe1
...
...
@@ -15,17 +15,19 @@
#include <linux/init.h>
#include <linux/module.h>
static
int
regmap_spi_write
(
struct
device
*
dev
,
const
void
*
data
,
size_t
count
)
static
int
regmap_spi_write
(
void
*
context
,
const
void
*
data
,
size_t
count
)
{
struct
device
*
dev
=
context
;
struct
spi_device
*
spi
=
to_spi_device
(
dev
);
return
spi_write
(
spi
,
data
,
count
);
}
static
int
regmap_spi_gather_write
(
struct
device
*
dev
,
static
int
regmap_spi_gather_write
(
void
*
context
,
const
void
*
reg
,
size_t
reg_len
,
const
void
*
val
,
size_t
val_len
)
{
struct
device
*
dev
=
context
;
struct
spi_device
*
spi
=
to_spi_device
(
dev
);
struct
spi_message
m
;
struct
spi_transfer
t
[
2
]
=
{
{
.
tx_buf
=
reg
,
.
len
=
reg_len
,
},
...
...
@@ -38,10 +40,11 @@ static int regmap_spi_gather_write(struct device *dev,
return
spi_sync
(
spi
,
&
m
);
}
static
int
regmap_spi_read
(
struct
device
*
dev
,
static
int
regmap_spi_read
(
void
*
context
,
const
void
*
reg
,
size_t
reg_size
,
void
*
val
,
size_t
val_size
)
{
struct
device
*
dev
=
context
;
struct
spi_device
*
spi
=
to_spi_device
(
dev
);
return
spi_write_then_read
(
spi
,
reg
,
reg_size
,
val
,
val_size
);
...
...
@@ -66,7 +69,7 @@ static struct regmap_bus regmap_spi = {
struct
regmap
*
regmap_init_spi
(
struct
spi_device
*
spi
,
const
struct
regmap_config
*
config
)
{
return
regmap_init
(
&
spi
->
dev
,
&
regmap_spi
,
config
);
return
regmap_init
(
&
spi
->
dev
,
&
regmap_spi
,
&
spi
->
dev
,
config
);
}
EXPORT_SYMBOL_GPL
(
regmap_init_spi
);
...
...
@@ -83,7 +86,7 @@ EXPORT_SYMBOL_GPL(regmap_init_spi);
struct
regmap
*
devm_regmap_init_spi
(
struct
spi_device
*
spi
,
const
struct
regmap_config
*
config
)
{
return
devm_regmap_init
(
&
spi
->
dev
,
&
regmap_spi
,
config
);
return
devm_regmap_init
(
&
spi
->
dev
,
&
regmap_spi
,
&
spi
->
dev
,
config
);
}
EXPORT_SYMBOL_GPL
(
devm_regmap_init_spi
);
...
...
drivers/base/regmap/regmap.c
浏览文件 @
c0cc6fe1
...
...
@@ -112,25 +112,36 @@ static void regmap_format_10_14_write(struct regmap *map,
out
[
0
]
=
reg
>>
2
;
}
static
void
regmap_format_8
(
void
*
buf
,
unsigned
int
val
)
static
void
regmap_format_8
(
void
*
buf
,
unsigned
int
val
,
unsigned
int
shift
)
{
u8
*
b
=
buf
;
b
[
0
]
=
val
;
b
[
0
]
=
val
<<
shift
;
}
static
void
regmap_format_16
(
void
*
buf
,
unsigned
int
val
)
static
void
regmap_format_16
(
void
*
buf
,
unsigned
int
val
,
unsigned
int
shift
)
{
__be16
*
b
=
buf
;
b
[
0
]
=
cpu_to_be16
(
val
);
b
[
0
]
=
cpu_to_be16
(
val
<<
shift
);
}
static
void
regmap_format_32
(
void
*
buf
,
unsigned
int
val
)
static
void
regmap_format_24
(
void
*
buf
,
unsigned
int
val
,
unsigned
int
shift
)
{
u8
*
b
=
buf
;
val
<<=
shift
;
b
[
0
]
=
val
>>
16
;
b
[
1
]
=
val
>>
8
;
b
[
2
]
=
val
;
}
static
void
regmap_format_32
(
void
*
buf
,
unsigned
int
val
,
unsigned
int
shift
)
{
__be32
*
b
=
buf
;
b
[
0
]
=
cpu_to_be32
(
val
);
b
[
0
]
=
cpu_to_be32
(
val
<<
shift
);
}
static
unsigned
int
regmap_parse_8
(
void
*
buf
)
...
...
@@ -149,6 +160,16 @@ static unsigned int regmap_parse_16(void *buf)
return
b
[
0
];
}
static
unsigned
int
regmap_parse_24
(
void
*
buf
)
{
u8
*
b
=
buf
;
unsigned
int
ret
=
b
[
2
];
ret
|=
((
unsigned
int
)
b
[
1
])
<<
8
;
ret
|=
((
unsigned
int
)
b
[
0
])
<<
16
;
return
ret
;
}
static
unsigned
int
regmap_parse_32
(
void
*
buf
)
{
__be32
*
b
=
buf
;
...
...
@@ -158,11 +179,32 @@ static unsigned int regmap_parse_32(void *buf)
return
b
[
0
];
}
static
void
regmap_lock_mutex
(
struct
regmap
*
map
)
{
mutex_lock
(
&
map
->
mutex
);
}
static
void
regmap_unlock_mutex
(
struct
regmap
*
map
)
{
mutex_unlock
(
&
map
->
mutex
);
}
static
void
regmap_lock_spinlock
(
struct
regmap
*
map
)
{
spin_lock
(
&
map
->
spinlock
);
}
static
void
regmap_unlock_spinlock
(
struct
regmap
*
map
)
{
spin_unlock
(
&
map
->
spinlock
);
}
/**
* regmap_init(): Initialise register map
*
* @dev: Device that will be interacted with
* @bus: Bus-specific callbacks to use with device
* @bus_context: Data passed to bus-specific callbacks
* @config: Configuration for register map
*
* The return value will be an ERR_PTR() on error or a valid pointer to
...
...
@@ -171,6 +213,7 @@ static unsigned int regmap_parse_32(void *buf)
*/
struct
regmap
*
regmap_init
(
struct
device
*
dev
,
const
struct
regmap_bus
*
bus
,
void
*
bus_context
,
const
struct
regmap_config
*
config
)
{
struct
regmap
*
map
;
...
...
@@ -185,14 +228,24 @@ struct regmap *regmap_init(struct device *dev,
goto
err
;
}
mutex_init
(
&
map
->
lock
);
if
(
bus
->
fast_io
)
{
spin_lock_init
(
&
map
->
spinlock
);
map
->
lock
=
regmap_lock_spinlock
;
map
->
unlock
=
regmap_unlock_spinlock
;
}
else
{
mutex_init
(
&
map
->
mutex
);
map
->
lock
=
regmap_lock_mutex
;
map
->
unlock
=
regmap_unlock_mutex
;
}
map
->
format
.
buf_size
=
(
config
->
reg_bits
+
config
->
val_bits
)
/
8
;
map
->
format
.
reg_bytes
=
DIV_ROUND_UP
(
config
->
reg_bits
,
8
);
map
->
format
.
pad_bytes
=
config
->
pad_bits
/
8
;
map
->
format
.
val_bytes
=
DIV_ROUND_UP
(
config
->
val_bits
,
8
);
map
->
format
.
buf_size
+=
map
->
format
.
pad_bytes
;
map
->
reg_shift
=
config
->
pad_bits
%
8
;
map
->
dev
=
dev
;
map
->
bus
=
bus
;
map
->
bus_context
=
bus_context
;
map
->
max_register
=
config
->
max_register
;
map
->
writeable_reg
=
config
->
writeable_reg
;
map
->
readable_reg
=
config
->
readable_reg
;
...
...
@@ -207,7 +260,7 @@ struct regmap *regmap_init(struct device *dev,
map
->
read_flag_mask
=
bus
->
read_flag_mask
;
}
switch
(
config
->
reg_bits
)
{
switch
(
config
->
reg_bits
+
map
->
reg_shift
)
{
case
2
:
switch
(
config
->
val_bits
)
{
case
6
:
...
...
@@ -273,6 +326,10 @@ struct regmap *regmap_init(struct device *dev,
map
->
format
.
format_val
=
regmap_format_16
;
map
->
format
.
parse_val
=
regmap_parse_16
;
break
;
case
24
:
map
->
format
.
format_val
=
regmap_format_24
;
map
->
format
.
parse_val
=
regmap_parse_24
;
break
;
case
32
:
map
->
format
.
format_val
=
regmap_format_32
;
map
->
format
.
parse_val
=
regmap_parse_32
;
...
...
@@ -289,7 +346,7 @@ struct regmap *regmap_init(struct device *dev,
goto
err_map
;
}
regmap_debugfs_init
(
map
);
regmap_debugfs_init
(
map
,
config
->
name
);
ret
=
regcache_init
(
map
,
config
);
if
(
ret
<
0
)
...
...
@@ -316,6 +373,7 @@ static void devm_regmap_release(struct device *dev, void *res)
*
* @dev: Device that will be interacted with
* @bus: Bus-specific callbacks to use with device
* @bus_context: Data passed to bus-specific callbacks
* @config: Configuration for register map
*
* The return value will be an ERR_PTR() on error or a valid pointer
...
...
@@ -325,6 +383,7 @@ static void devm_regmap_release(struct device *dev, void *res)
*/
struct
regmap
*
devm_regmap_init
(
struct
device
*
dev
,
const
struct
regmap_bus
*
bus
,
void
*
bus_context
,
const
struct
regmap_config
*
config
)
{
struct
regmap
**
ptr
,
*
regmap
;
...
...
@@ -333,7 +392,7 @@ struct regmap *devm_regmap_init(struct device *dev,
if
(
!
ptr
)
return
ERR_PTR
(
-
ENOMEM
);
regmap
=
regmap_init
(
dev
,
bus
,
config
);
regmap
=
regmap_init
(
dev
,
bus
,
bus_context
,
config
);
if
(
!
IS_ERR
(
regmap
))
{
*
ptr
=
regmap
;
devres_add
(
dev
,
ptr
);
...
...
@@ -360,7 +419,7 @@ int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config)
{
int
ret
;
m
utex_lock
(
&
map
->
lock
);
m
ap
->
lock
(
map
);
regcache_exit
(
map
);
regmap_debugfs_exit
(
map
);
...
...
@@ -372,14 +431,14 @@ int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config)
map
->
precious_reg
=
config
->
precious_reg
;
map
->
cache_type
=
config
->
cache_type
;
regmap_debugfs_init
(
map
);
regmap_debugfs_init
(
map
,
config
->
name
);
map
->
cache_bypass
=
false
;
map
->
cache_only
=
false
;
ret
=
regcache_init
(
map
,
config
);
m
utex_unlock
(
&
map
->
lock
);
m
ap
->
unlock
(
map
);
return
ret
;
}
...
...
@@ -391,6 +450,8 @@ void regmap_exit(struct regmap *map)
{
regcache_exit
(
map
);
regmap_debugfs_exit
(
map
);
if
(
map
->
bus
->
free_context
)
map
->
bus
->
free_context
(
map
->
bus_context
);
kfree
(
map
->
work_buf
);
kfree
(
map
);
}
...
...
@@ -431,7 +492,7 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
}
}
map
->
format
.
format_reg
(
map
->
work_buf
,
reg
);
map
->
format
.
format_reg
(
map
->
work_buf
,
reg
,
map
->
reg_shift
);
u8
[
0
]
|=
map
->
write_flag_mask
;
...
...
@@ -444,12 +505,12 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
*/
if
(
val
==
(
map
->
work_buf
+
map
->
format
.
pad_bytes
+
map
->
format
.
reg_bytes
))
ret
=
map
->
bus
->
write
(
map
->
dev
,
map
->
work_buf
,
ret
=
map
->
bus
->
write
(
map
->
bus_context
,
map
->
work_buf
,
map
->
format
.
reg_bytes
+
map
->
format
.
pad_bytes
+
val_len
);
else
if
(
map
->
bus
->
gather_write
)
ret
=
map
->
bus
->
gather_write
(
map
->
dev
,
map
->
work_buf
,
ret
=
map
->
bus
->
gather_write
(
map
->
bus_context
,
map
->
work_buf
,
map
->
format
.
reg_bytes
+
map
->
format
.
pad_bytes
,
val
,
val_len
);
...
...
@@ -464,7 +525,7 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
memcpy
(
buf
,
map
->
work_buf
,
map
->
format
.
reg_bytes
);
memcpy
(
buf
+
map
->
format
.
reg_bytes
+
map
->
format
.
pad_bytes
,
val
,
val_len
);
ret
=
map
->
bus
->
write
(
map
->
dev
,
buf
,
len
);
ret
=
map
->
bus
->
write
(
map
->
bus_context
,
buf
,
len
);
kfree
(
buf
);
}
...
...
@@ -498,7 +559,7 @@ int _regmap_write(struct regmap *map, unsigned int reg,
trace_regmap_hw_write_start
(
map
->
dev
,
reg
,
1
);
ret
=
map
->
bus
->
write
(
map
->
dev
,
map
->
work_buf
,
ret
=
map
->
bus
->
write
(
map
->
bus_context
,
map
->
work_buf
,
map
->
format
.
buf_size
);
trace_regmap_hw_write_done
(
map
->
dev
,
reg
,
1
);
...
...
@@ -506,7 +567,7 @@ int _regmap_write(struct regmap *map, unsigned int reg,
return
ret
;
}
else
{
map
->
format
.
format_val
(
map
->
work_buf
+
map
->
format
.
reg_bytes
+
map
->
format
.
pad_bytes
,
val
);
+
map
->
format
.
pad_bytes
,
val
,
0
);
return
_regmap_raw_write
(
map
,
reg
,
map
->
work_buf
+
map
->
format
.
reg_bytes
+
...
...
@@ -529,11 +590,11 @@ int regmap_write(struct regmap *map, unsigned int reg, unsigned int val)
{
int
ret
;
m
utex_lock
(
&
map
->
lock
);
m
ap
->
lock
(
map
);
ret
=
_regmap_write
(
map
,
reg
,
val
);
m
utex_unlock
(
&
map
->
lock
);
m
ap
->
unlock
(
map
);
return
ret
;
}
...
...
@@ -560,11 +621,14 @@ int regmap_raw_write(struct regmap *map, unsigned int reg,
{
int
ret
;
mutex_lock
(
&
map
->
lock
);
if
(
val_len
%
map
->
format
.
val_bytes
)
return
-
EINVAL
;
map
->
lock
(
map
);
ret
=
_regmap_raw_write
(
map
,
reg
,
val
,
val_len
);
m
utex_unlock
(
&
map
->
lock
);
m
ap
->
unlock
(
map
);
return
ret
;
}
...
...
@@ -594,7 +658,7 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
if
(
!
map
->
format
.
parse_val
)
return
-
EINVAL
;
m
utex_lock
(
&
map
->
lock
);
m
ap
->
lock
(
map
);
/* No formatting is require if val_byte is 1 */
if
(
val_bytes
==
1
)
{
...
...
@@ -615,7 +679,7 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
kfree
(
wval
);
out:
m
utex_unlock
(
&
map
->
lock
);
m
ap
->
unlock
(
map
);
return
ret
;
}
EXPORT_SYMBOL_GPL
(
regmap_bulk_write
);
...
...
@@ -626,7 +690,7 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
u8
*
u8
=
map
->
work_buf
;
int
ret
;
map
->
format
.
format_reg
(
map
->
work_buf
,
reg
);
map
->
format
.
format_reg
(
map
->
work_buf
,
reg
,
map
->
reg_shift
);
/*
* Some buses or devices flag reads by setting the high bits in the
...
...
@@ -639,7 +703,7 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
trace_regmap_hw_read_start
(
map
->
dev
,
reg
,
val_len
/
map
->
format
.
val_bytes
);
ret
=
map
->
bus
->
read
(
map
->
dev
,
map
->
work_buf
,
ret
=
map
->
bus
->
read
(
map
->
bus_context
,
map
->
work_buf
,
map
->
format
.
reg_bytes
+
map
->
format
.
pad_bytes
,
val
,
val_len
);
...
...
@@ -689,11 +753,11 @@ int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val)
{
int
ret
;
m
utex_lock
(
&
map
->
lock
);
m
ap
->
lock
(
map
);
ret
=
_regmap_read
(
map
,
reg
,
val
);
m
utex_unlock
(
&
map
->
lock
);
m
ap
->
unlock
(
map
);
return
ret
;
}
...
...
@@ -718,7 +782,10 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
unsigned
int
v
;
int
ret
,
i
;
mutex_lock
(
&
map
->
lock
);
if
(
val_len
%
map
->
format
.
val_bytes
)
return
-
EINVAL
;
map
->
lock
(
map
);
if
(
regmap_volatile_range
(
map
,
reg
,
val_count
)
||
map
->
cache_bypass
||
map
->
cache_type
==
REGCACHE_NONE
)
{
...
...
@@ -734,12 +801,12 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
if
(
ret
!=
0
)
goto
out
;
map
->
format
.
format_val
(
val
+
(
i
*
val_bytes
),
v
);
map
->
format
.
format_val
(
val
+
(
i
*
val_bytes
),
v
,
0
);
}
}
out:
m
utex_unlock
(
&
map
->
lock
);
m
ap
->
unlock
(
map
);
return
ret
;
}
...
...
@@ -792,7 +859,7 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg,
int
ret
;
unsigned
int
tmp
,
orig
;
m
utex_lock
(
&
map
->
lock
);
m
ap
->
lock
(
map
);
ret
=
_regmap_read
(
map
,
reg
,
&
orig
);
if
(
ret
!=
0
)
...
...
@@ -809,7 +876,7 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg,
}
out:
m
utex_unlock
(
&
map
->
lock
);
m
ap
->
unlock
(
map
);
return
ret
;
}
...
...
@@ -876,7 +943,7 @@ int regmap_register_patch(struct regmap *map, const struct reg_default *regs,
if
(
map
->
patch
)
return
-
EBUSY
;
m
utex_lock
(
&
map
->
lock
);
m
ap
->
lock
(
map
);
bypass
=
map
->
cache_bypass
;
...
...
@@ -904,7 +971,7 @@ int regmap_register_patch(struct regmap *map, const struct reg_default *regs,
out:
map
->
cache_bypass
=
bypass
;
m
utex_unlock
(
&
map
->
lock
);
m
ap
->
unlock
(
map
);
return
ret
;
}
...
...
include/linux/regmap.h
浏览文件 @
c0cc6fe1
...
...
@@ -46,6 +46,9 @@ struct reg_default {
/**
* Configuration for the register map of a device.
*
* @name: Optional name of the regmap. Useful when a device has multiple
* register regions.
*
* @reg_bits: Number of bits in a register address, mandatory.
* @pad_bits: Number of bits of padding between register and value.
* @val_bits: Number of bits in a register value, mandatory.
...
...
@@ -77,6 +80,8 @@ struct reg_default {
* @num_reg_defaults_raw: Number of elements in reg_defaults_raw.
*/
struct
regmap_config
{
const
char
*
name
;
int
reg_bits
;
int
pad_bits
;
int
val_bits
;
...
...
@@ -97,18 +102,21 @@ struct regmap_config {
u8
write_flag_mask
;
};
typedef
int
(
*
regmap_hw_write
)(
struct
device
*
dev
,
const
void
*
data
,
typedef
int
(
*
regmap_hw_write
)(
void
*
context
,
const
void
*
data
,
size_t
count
);
typedef
int
(
*
regmap_hw_gather_write
)(
struct
device
*
dev
,
typedef
int
(
*
regmap_hw_gather_write
)(
void
*
context
,
const
void
*
reg
,
size_t
reg_len
,
const
void
*
val
,
size_t
val_len
);
typedef
int
(
*
regmap_hw_read
)(
struct
device
*
dev
,
typedef
int
(
*
regmap_hw_read
)(
void
*
context
,
const
void
*
reg_buf
,
size_t
reg_size
,
void
*
val_buf
,
size_t
val_size
);
typedef
void
(
*
regmap_hw_free_context
)(
void
*
context
);
/**
* Description of a hardware bus for the register map infrastructure.
*
* @fast_io: Register IO is fast. Use a spinlock instead of a mutex
* to perform locking.
* @write: Write operation.
* @gather_write: Write operation with split register/value, return -ENOTSUPP
* if not implemented on a given device.
...
...
@@ -118,27 +126,37 @@ typedef int (*regmap_hw_read)(struct device *dev,
* a read.
*/
struct
regmap_bus
{
bool
fast_io
;
regmap_hw_write
write
;
regmap_hw_gather_write
gather_write
;
regmap_hw_read
read
;
regmap_hw_free_context
free_context
;
u8
read_flag_mask
;
};
struct
regmap
*
regmap_init
(
struct
device
*
dev
,
const
struct
regmap_bus
*
bus
,
void
*
bus_context
,
const
struct
regmap_config
*
config
);
struct
regmap
*
regmap_init_i2c
(
struct
i2c_client
*
i2c
,
const
struct
regmap_config
*
config
);
struct
regmap
*
regmap_init_spi
(
struct
spi_device
*
dev
,
const
struct
regmap_config
*
config
);
struct
regmap
*
regmap_init_mmio
(
struct
device
*
dev
,
void
__iomem
*
regs
,
const
struct
regmap_config
*
config
);
struct
regmap
*
devm_regmap_init
(
struct
device
*
dev
,
const
struct
regmap_bus
*
bus
,
void
*
bus_context
,
const
struct
regmap_config
*
config
);
struct
regmap
*
devm_regmap_init_i2c
(
struct
i2c_client
*
i2c
,
const
struct
regmap_config
*
config
);
struct
regmap
*
devm_regmap_init_spi
(
struct
spi_device
*
dev
,
const
struct
regmap_config
*
config
);
struct
regmap
*
devm_regmap_init_mmio
(
struct
device
*
dev
,
void
__iomem
*
regs
,
const
struct
regmap_config
*
config
);
void
regmap_exit
(
struct
regmap
*
map
);
int
regmap_reinit_cache
(
struct
regmap
*
map
,
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录