Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
feff98f5
Commit
feff98f5
authored
Jun 30, 2013
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'regmap/topic/cache' into regmap-next
parents
9e895ace
d6814a7d
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
180 additions
and
27 deletions
+180
-27
drivers/base/regmap/internal.h
drivers/base/regmap/internal.h
+2
-0
drivers/base/regmap/regcache-rbtree.c
drivers/base/regmap/regcache-rbtree.c
+48
-14
drivers/base/regmap/regcache.c
drivers/base/regmap/regcache.c
+79
-4
drivers/base/regmap/regmap-debugfs.c
drivers/base/regmap/regmap-debugfs.c
+4
-0
drivers/base/regmap/regmap.c
drivers/base/regmap/regmap.c
+12
-9
include/linux/regmap.h
include/linux/regmap.h
+12
-0
include/trace/events/regmap.h
include/trace/events/regmap.h
+23
-0
No files found.
drivers/base/regmap/internal.h
View file @
feff98f5
...
...
@@ -52,6 +52,7 @@ struct regmap_async {
struct
regmap
{
struct
mutex
mutex
;
spinlock_t
spinlock
;
unsigned
long
spinlock_flags
;
regmap_lock
lock
;
regmap_unlock
unlock
;
void
*
lock_arg
;
/* This is passed to lock/unlock functions */
...
...
@@ -148,6 +149,7 @@ struct regcache_ops {
int
(
*
read
)(
struct
regmap
*
map
,
unsigned
int
reg
,
unsigned
int
*
value
);
int
(
*
write
)(
struct
regmap
*
map
,
unsigned
int
reg
,
unsigned
int
value
);
int
(
*
sync
)(
struct
regmap
*
map
,
unsigned
int
min
,
unsigned
int
max
);
int
(
*
drop
)(
struct
regmap
*
map
,
unsigned
int
min
,
unsigned
int
max
);
};
bool
regmap_writeable
(
struct
regmap
*
map
,
unsigned
int
reg
);
...
...
drivers/base/regmap/regcache-rbtree.c
View file @
feff98f5
...
...
@@ -304,6 +304,48 @@ static int regcache_rbtree_insert_to_block(struct regmap *map,
return
0
;
}
static
struct
regcache_rbtree_node
*
regcache_rbtree_node_alloc
(
struct
regmap
*
map
,
unsigned
int
reg
)
{
struct
regcache_rbtree_node
*
rbnode
;
const
struct
regmap_range
*
range
;
int
i
;
rbnode
=
kzalloc
(
sizeof
(
*
rbnode
),
GFP_KERNEL
);
if
(
!
rbnode
)
return
NULL
;
/* If there is a read table then use it to guess at an allocation */
if
(
map
->
rd_table
)
{
for
(
i
=
0
;
i
<
map
->
rd_table
->
n_yes_ranges
;
i
++
)
{
if
(
regmap_reg_in_range
(
reg
,
&
map
->
rd_table
->
yes_ranges
[
i
]))
break
;
}
if
(
i
!=
map
->
rd_table
->
n_yes_ranges
)
{
range
=
&
map
->
rd_table
->
yes_ranges
[
i
];
rbnode
->
blklen
=
range
->
range_max
-
range
->
range_min
+
1
;
rbnode
->
base_reg
=
range
->
range_min
;
}
}
if
(
!
rbnode
->
blklen
)
{
rbnode
->
blklen
=
sizeof
(
*
rbnode
);
rbnode
->
base_reg
=
reg
;
}
rbnode
->
block
=
kmalloc
(
rbnode
->
blklen
*
map
->
cache_word_size
,
GFP_KERNEL
);
if
(
!
rbnode
->
block
)
{
kfree
(
rbnode
);
return
NULL
;
}
return
rbnode
;
}
static
int
regcache_rbtree_write
(
struct
regmap
*
map
,
unsigned
int
reg
,
unsigned
int
value
)
{
...
...
@@ -354,23 +396,15 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg,
return
0
;
}
}
/* we did not manage to find a place to insert it in an existing
* block so create a new rbnode with a single register in its block.
* This block will get populated further if any other adjacent
* registers get modified in the future.
/* We did not manage to find a place to insert it in
* an existing block so create a new rbnode.
*/
rbnode
=
kzalloc
(
sizeof
*
rbnode
,
GFP_KERNEL
);
rbnode
=
regcache_rbtree_node_alloc
(
map
,
reg
);
if
(
!
rbnode
)
return
-
ENOMEM
;
rbnode
->
blklen
=
sizeof
(
*
rbnode
);
rbnode
->
base_reg
=
reg
;
rbnode
->
block
=
kmalloc
(
rbnode
->
blklen
*
map
->
cache_word_size
,
GFP_KERNEL
);
if
(
!
rbnode
->
block
)
{
kfree
(
rbnode
);
return
-
ENOMEM
;
}
regcache_rbtree_set_register
(
map
,
rbnode
,
0
,
value
);
regcache_rbtree_set_register
(
map
,
rbnode
,
reg
-
rbnode
->
base_reg
,
value
);
regcache_rbtree_insert
(
map
,
&
rbtree_ctx
->
root
,
rbnode
);
rbtree_ctx
->
cached_rbnode
=
rbnode
;
}
...
...
drivers/base/regmap/regcache.c
View file @
feff98f5
...
...
@@ -250,6 +250,38 @@ int regcache_write(struct regmap *map,
return
0
;
}
static
int
regcache_default_sync
(
struct
regmap
*
map
,
unsigned
int
min
,
unsigned
int
max
)
{
unsigned
int
reg
;
for
(
reg
=
min
;
reg
<=
max
;
reg
++
)
{
unsigned
int
val
;
int
ret
;
if
(
regmap_volatile
(
map
,
reg
))
continue
;
ret
=
regcache_read
(
map
,
reg
,
&
val
);
if
(
ret
)
return
ret
;
/* Is this the hardware default? If so skip. */
ret
=
regcache_lookup_reg
(
map
,
reg
);
if
(
ret
>=
0
&&
val
==
map
->
reg_defaults
[
ret
].
def
)
continue
;
map
->
cache_bypass
=
1
;
ret
=
_regmap_write
(
map
,
reg
,
val
);
map
->
cache_bypass
=
0
;
if
(
ret
)
return
ret
;
dev_dbg
(
map
->
dev
,
"Synced register %#x, value %#x
\n
"
,
reg
,
val
);
}
return
0
;
}
/**
* regcache_sync: Sync the register cache with the hardware.
*
...
...
@@ -268,7 +300,7 @@ int regcache_sync(struct regmap *map)
const
char
*
name
;
unsigned
int
bypass
;
BUG_ON
(
!
map
->
cache_ops
||
!
map
->
cache_ops
->
sync
);
BUG_ON
(
!
map
->
cache_ops
);
map
->
lock
(
map
->
lock_arg
);
/* Remember the initial bypass state */
...
...
@@ -297,7 +329,10 @@ int regcache_sync(struct regmap *map)
}
map
->
cache_bypass
=
0
;
if
(
map
->
cache_ops
->
sync
)
ret
=
map
->
cache_ops
->
sync
(
map
,
0
,
map
->
max_register
);
else
ret
=
regcache_default_sync
(
map
,
0
,
map
->
max_register
);
if
(
ret
==
0
)
map
->
cache_dirty
=
false
;
...
...
@@ -331,7 +366,7 @@ int regcache_sync_region(struct regmap *map, unsigned int min,
const
char
*
name
;
unsigned
int
bypass
;
BUG_ON
(
!
map
->
cache_ops
||
!
map
->
cache_ops
->
sync
);
BUG_ON
(
!
map
->
cache_ops
);
map
->
lock
(
map
->
lock_arg
);
...
...
@@ -346,7 +381,10 @@ int regcache_sync_region(struct regmap *map, unsigned int min,
if
(
!
map
->
cache_dirty
)
goto
out
;
if
(
map
->
cache_ops
->
sync
)
ret
=
map
->
cache_ops
->
sync
(
map
,
min
,
max
);
else
ret
=
regcache_default_sync
(
map
,
min
,
max
);
out:
trace_regcache_sync
(
map
->
dev
,
name
,
"stop region"
);
...
...
@@ -358,6 +396,43 @@ int regcache_sync_region(struct regmap *map, unsigned int min,
}
EXPORT_SYMBOL_GPL
(
regcache_sync_region
);
/**
* regcache_drop_region: Discard part of the register cache
*
* @map: map to operate on
* @min: first register to discard
* @max: last register to discard
*
* Discard part of the register cache.
*
* Return a negative value on failure, 0 on success.
*/
int
regcache_drop_region
(
struct
regmap
*
map
,
unsigned
int
min
,
unsigned
int
max
)
{
unsigned
int
reg
;
int
ret
=
0
;
if
(
!
map
->
cache_present
&&
!
(
map
->
cache_ops
&&
map
->
cache_ops
->
drop
))
return
-
EINVAL
;
map
->
lock
(
map
->
lock_arg
);
trace_regcache_drop_region
(
map
->
dev
,
min
,
max
);
if
(
map
->
cache_present
)
for
(
reg
=
min
;
reg
<
max
+
1
;
reg
++
)
clear_bit
(
reg
,
map
->
cache_present
);
if
(
map
->
cache_ops
&&
map
->
cache_ops
->
drop
)
ret
=
map
->
cache_ops
->
drop
(
map
,
min
,
max
);
map
->
unlock
(
map
->
lock_arg
);
return
ret
;
}
EXPORT_SYMBOL_GPL
(
regcache_drop_region
);
/**
* regcache_cache_only: Put a register map into cache only mode
*
...
...
drivers/base/regmap/regmap-debugfs.c
View file @
feff98f5
...
...
@@ -84,6 +84,10 @@ static unsigned int regmap_debugfs_get_dump_start(struct regmap *map,
unsigned
int
fpos_offset
;
unsigned
int
reg_offset
;
/* Suppress the cache if we're using a subrange */
if
(
from
)
return
from
;
/*
* If we don't have a cache build one so we don't have to do a
* linear scan each time.
...
...
drivers/base/regmap/regmap.c
View file @
feff98f5
...
...
@@ -65,8 +65,7 @@ bool regmap_reg_in_ranges(unsigned int reg,
}
EXPORT_SYMBOL_GPL
(
regmap_reg_in_ranges
);
static
bool
_regmap_check_range_table
(
struct
regmap
*
map
,
unsigned
int
reg
,
bool
regmap_check_range_table
(
struct
regmap
*
map
,
unsigned
int
reg
,
const
struct
regmap_access_table
*
table
)
{
/* Check "no ranges" first */
...
...
@@ -80,6 +79,7 @@ static bool _regmap_check_range_table(struct regmap *map,
return
regmap_reg_in_ranges
(
reg
,
table
->
yes_ranges
,
table
->
n_yes_ranges
);
}
EXPORT_SYMBOL_GPL
(
regmap_check_range_table
);
bool
regmap_writeable
(
struct
regmap
*
map
,
unsigned
int
reg
)
{
...
...
@@ -90,7 +90,7 @@ bool regmap_writeable(struct regmap *map, unsigned int reg)
return
map
->
writeable_reg
(
map
->
dev
,
reg
);
if
(
map
->
wr_table
)
return
_
regmap_check_range_table
(
map
,
reg
,
map
->
wr_table
);
return
regmap_check_range_table
(
map
,
reg
,
map
->
wr_table
);
return
true
;
}
...
...
@@ -107,7 +107,7 @@ bool regmap_readable(struct regmap *map, unsigned int reg)
return
map
->
readable_reg
(
map
->
dev
,
reg
);
if
(
map
->
rd_table
)
return
_
regmap_check_range_table
(
map
,
reg
,
map
->
rd_table
);
return
regmap_check_range_table
(
map
,
reg
,
map
->
rd_table
);
return
true
;
}
...
...
@@ -121,7 +121,7 @@ bool regmap_volatile(struct regmap *map, unsigned int reg)
return
map
->
volatile_reg
(
map
->
dev
,
reg
);
if
(
map
->
volatile_table
)
return
_
regmap_check_range_table
(
map
,
reg
,
map
->
volatile_table
);
return
regmap_check_range_table
(
map
,
reg
,
map
->
volatile_table
);
return
true
;
}
...
...
@@ -135,7 +135,7 @@ bool regmap_precious(struct regmap *map, unsigned int reg)
return
map
->
precious_reg
(
map
->
dev
,
reg
);
if
(
map
->
precious_table
)
return
_
regmap_check_range_table
(
map
,
reg
,
map
->
precious_table
);
return
regmap_check_range_table
(
map
,
reg
,
map
->
precious_table
);
return
false
;
}
...
...
@@ -302,13 +302,16 @@ static void regmap_unlock_mutex(void *__map)
static
void
regmap_lock_spinlock
(
void
*
__map
)
{
struct
regmap
*
map
=
__map
;
spin_lock
(
&
map
->
spinlock
);
unsigned
long
flags
;
spin_lock_irqsave
(
&
map
->
spinlock
,
flags
);
map
->
spinlock_flags
=
flags
;
}
static
void
regmap_unlock_spinlock
(
void
*
__map
)
{
struct
regmap
*
map
=
__map
;
spin_unlock
(
&
map
->
spinlock
);
spin_unlock
_irqrestore
(
&
map
->
spinlock
,
map
->
spinlock_flags
);
}
static
void
dev_get_regmap_release
(
struct
device
*
dev
,
void
*
res
)
...
...
include/linux/regmap.h
View file @
feff98f5
...
...
@@ -394,10 +394,15 @@ bool regmap_can_raw_write(struct regmap *map);
int
regcache_sync
(
struct
regmap
*
map
);
int
regcache_sync_region
(
struct
regmap
*
map
,
unsigned
int
min
,
unsigned
int
max
);
int
regcache_drop_region
(
struct
regmap
*
map
,
unsigned
int
min
,
unsigned
int
max
);
void
regcache_cache_only
(
struct
regmap
*
map
,
bool
enable
);
void
regcache_cache_bypass
(
struct
regmap
*
map
,
bool
enable
);
void
regcache_mark_dirty
(
struct
regmap
*
map
);
bool
regmap_check_range_table
(
struct
regmap
*
map
,
unsigned
int
reg
,
const
struct
regmap_access_table
*
table
);
int
regmap_register_patch
(
struct
regmap
*
map
,
const
struct
reg_default
*
regs
,
int
num_regs
);
...
...
@@ -562,6 +567,13 @@ static inline int regcache_sync_region(struct regmap *map, unsigned int min,
return
-
EINVAL
;
}
static
inline
int
regcache_drop_region
(
struct
regmap
*
map
,
unsigned
int
min
,
unsigned
int
max
)
{
WARN_ONCE
(
1
,
"regmap API is disabled"
);
return
-
EINVAL
;
}
static
inline
void
regcache_cache_only
(
struct
regmap
*
map
,
bool
enable
)
{
WARN_ONCE
(
1
,
"regmap API is disabled"
);
...
...
include/trace/events/regmap.h
View file @
feff98f5
...
...
@@ -223,6 +223,29 @@ DEFINE_EVENT(regmap_async, regmap_async_complete_done,
);
TRACE_EVENT
(
regcache_drop_region
,
TP_PROTO
(
struct
device
*
dev
,
unsigned
int
from
,
unsigned
int
to
),
TP_ARGS
(
dev
,
from
,
to
),
TP_STRUCT__entry
(
__string
(
name
,
dev_name
(
dev
)
)
__field
(
unsigned
int
,
from
)
__field
(
unsigned
int
,
to
)
),
TP_fast_assign
(
__assign_str
(
name
,
dev_name
(
dev
));
__entry
->
from
=
from
;
__entry
->
to
=
to
;
),
TP_printk
(
"%s %u-%u"
,
__get_str
(
name
),
(
unsigned
int
)
__entry
->
from
,
(
unsigned
int
)
__entry
->
to
)
);
#endif
/* _TRACE_REGMAP_H */
/* This part must be outside protection */
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment