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
Kirill Smelkov
linux
Commits
a8d99344
Commit
a8d99344
authored
Jan 05, 2016
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branches 'regmap/topic/64bit' and 'regmap/topic/irq-type' into regmap-next
parents
8798975b
782035ea
7a78479f
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
239 additions
and
0 deletions
+239
-0
drivers/base/regmap/regcache.c
drivers/base/regmap/regcache.c
+21
-0
drivers/base/regmap/regmap-irq.c
drivers/base/regmap/regmap-irq.c
+100
-0
drivers/base/regmap/regmap.c
drivers/base/regmap/regmap.c
+102
-0
include/linux/regmap.h
include/linux/regmap.h
+16
-0
No files found.
drivers/base/regmap/regcache.c
View file @
a8d99344
...
...
@@ -543,19 +543,30 @@ bool regcache_set_val(struct regmap *map, void *base, unsigned int idx,
switch
(
map
->
cache_word_size
)
{
case
1
:
{
u8
*
cache
=
base
;
cache
[
idx
]
=
val
;
break
;
}
case
2
:
{
u16
*
cache
=
base
;
cache
[
idx
]
=
val
;
break
;
}
case
4
:
{
u32
*
cache
=
base
;
cache
[
idx
]
=
val
;
break
;
}
#ifdef CONFIG_64BIT
case
8
:
{
u64
*
cache
=
base
;
cache
[
idx
]
=
val
;
break
;
}
#endif
default:
BUG
();
}
...
...
@@ -576,16 +587,26 @@ unsigned int regcache_get_val(struct regmap *map, const void *base,
switch
(
map
->
cache_word_size
)
{
case
1
:
{
const
u8
*
cache
=
base
;
return
cache
[
idx
];
}
case
2
:
{
const
u16
*
cache
=
base
;
return
cache
[
idx
];
}
case
4
:
{
const
u32
*
cache
=
base
;
return
cache
[
idx
];
}
#ifdef CONFIG_64BIT
case
8
:
{
const
u64
*
cache
=
base
;
return
cache
[
idx
];
}
#endif
default:
BUG
();
}
...
...
drivers/base/regmap/regmap-irq.c
View file @
a8d99344
...
...
@@ -39,8 +39,11 @@ struct regmap_irq_chip_data {
unsigned
int
*
mask_buf
;
unsigned
int
*
mask_buf_def
;
unsigned
int
*
wake_buf
;
unsigned
int
*
type_buf
;
unsigned
int
*
type_buf_def
;
unsigned
int
irq_reg_stride
;
unsigned
int
type_reg_stride
;
};
static
inline
const
...
...
@@ -144,6 +147,22 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
}
}
for
(
i
=
0
;
i
<
d
->
chip
->
num_type_reg
;
i
++
)
{
if
(
!
d
->
type_buf_def
[
i
])
continue
;
reg
=
d
->
chip
->
type_base
+
(
i
*
map
->
reg_stride
*
d
->
type_reg_stride
);
if
(
d
->
chip
->
type_invert
)
ret
=
regmap_update_bits
(
d
->
map
,
reg
,
d
->
type_buf_def
[
i
],
~
d
->
type_buf
[
i
]);
else
ret
=
regmap_update_bits
(
d
->
map
,
reg
,
d
->
type_buf_def
[
i
],
d
->
type_buf
[
i
]);
if
(
ret
!=
0
)
dev_err
(
d
->
map
->
dev
,
"Failed to sync type in %x
\n
"
,
reg
);
}
if
(
d
->
chip
->
runtime_pm
)
pm_runtime_put
(
map
->
dev
);
...
...
@@ -178,6 +197,38 @@ static void regmap_irq_disable(struct irq_data *data)
d
->
mask_buf
[
irq_data
->
reg_offset
/
map
->
reg_stride
]
|=
irq_data
->
mask
;
}
static
int
regmap_irq_set_type
(
struct
irq_data
*
data
,
unsigned
int
type
)
{
struct
regmap_irq_chip_data
*
d
=
irq_data_get_irq_chip_data
(
data
);
struct
regmap
*
map
=
d
->
map
;
const
struct
regmap_irq
*
irq_data
=
irq_to_regmap_irq
(
d
,
data
->
hwirq
);
int
reg
=
irq_data
->
type_reg_offset
/
map
->
reg_stride
;
if
(
!
(
irq_data
->
type_rising_mask
|
irq_data
->
type_falling_mask
))
return
0
;
d
->
type_buf
[
reg
]
&=
~
(
irq_data
->
type_falling_mask
|
irq_data
->
type_rising_mask
);
switch
(
type
)
{
case
IRQ_TYPE_EDGE_FALLING
:
d
->
type_buf
[
reg
]
|=
irq_data
->
type_falling_mask
;
break
;
case
IRQ_TYPE_EDGE_RISING
:
d
->
type_buf
[
reg
]
|=
irq_data
->
type_rising_mask
;
break
;
case
IRQ_TYPE_EDGE_BOTH
:
d
->
type_buf
[
reg
]
|=
(
irq_data
->
type_falling_mask
|
irq_data
->
type_rising_mask
);
break
;
default:
return
-
EINVAL
;
}
return
0
;
}
static
int
regmap_irq_set_wake
(
struct
irq_data
*
data
,
unsigned
int
on
)
{
struct
regmap_irq_chip_data
*
d
=
irq_data_get_irq_chip_data
(
data
);
...
...
@@ -204,6 +255,7 @@ static const struct irq_chip regmap_irq_chip = {
.
irq_bus_sync_unlock
=
regmap_irq_sync_unlock
,
.
irq_disable
=
regmap_irq_disable
,
.
irq_enable
=
regmap_irq_enable
,
.
irq_set_type
=
regmap_irq_set_type
,
.
irq_set_wake
=
regmap_irq_set_wake
,
};
...
...
@@ -408,6 +460,18 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
goto
err_alloc
;
}
if
(
chip
->
num_type_reg
)
{
d
->
type_buf_def
=
kcalloc
(
chip
->
num_type_reg
,
sizeof
(
unsigned
int
),
GFP_KERNEL
);
if
(
!
d
->
type_buf_def
)
goto
err_alloc
;
d
->
type_buf
=
kcalloc
(
chip
->
num_type_reg
,
sizeof
(
unsigned
int
),
GFP_KERNEL
);
if
(
!
d
->
type_buf
)
goto
err_alloc
;
}
d
->
irq_chip
=
regmap_irq_chip
;
d
->
irq_chip
.
name
=
chip
->
name
;
d
->
irq
=
irq
;
...
...
@@ -420,6 +484,11 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
else
d
->
irq_reg_stride
=
1
;
if
(
chip
->
type_reg_stride
)
d
->
type_reg_stride
=
chip
->
type_reg_stride
;
else
d
->
type_reg_stride
=
1
;
if
(
!
map
->
use_single_read
&&
map
->
reg_stride
==
1
&&
d
->
irq_reg_stride
==
1
)
{
d
->
status_reg_buf
=
kmalloc_array
(
chip
->
num_regs
,
...
...
@@ -512,6 +581,33 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
}
}
if
(
chip
->
num_type_reg
)
{
for
(
i
=
0
;
i
<
chip
->
num_irqs
;
i
++
)
{
reg
=
chip
->
irqs
[
i
].
type_reg_offset
/
map
->
reg_stride
;
d
->
type_buf_def
[
reg
]
|=
chip
->
irqs
[
i
].
type_rising_mask
|
chip
->
irqs
[
i
].
type_falling_mask
;
}
for
(
i
=
0
;
i
<
chip
->
num_type_reg
;
++
i
)
{
if
(
!
d
->
type_buf_def
[
i
])
continue
;
reg
=
chip
->
type_base
+
(
i
*
map
->
reg_stride
*
d
->
type_reg_stride
);
if
(
chip
->
type_invert
)
ret
=
regmap_update_bits
(
map
,
reg
,
d
->
type_buf_def
[
i
],
0xFF
);
else
ret
=
regmap_update_bits
(
map
,
reg
,
d
->
type_buf_def
[
i
],
0x0
);
if
(
ret
!=
0
)
{
dev_err
(
map
->
dev
,
"Failed to set type in 0x%x: %x
\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
,
...
...
@@ -542,6 +638,8 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
err_domain:
/* Should really dispose of the domain but... */
err_alloc:
kfree
(
d
->
type_buf
);
kfree
(
d
->
type_buf_def
);
kfree
(
d
->
wake_buf
);
kfree
(
d
->
mask_buf_def
);
kfree
(
d
->
mask_buf
);
...
...
@@ -565,6 +663,8 @@ void regmap_del_irq_chip(int irq, struct regmap_irq_chip_data *d)
free_irq
(
irq
,
d
);
irq_domain_remove
(
d
->
domain
);
kfree
(
d
->
type_buf
);
kfree
(
d
->
type_buf_def
);
kfree
(
d
->
wake_buf
);
kfree
(
d
->
mask_buf_def
);
kfree
(
d
->
mask_buf
);
...
...
drivers/base/regmap/regmap.c
View file @
a8d99344
...
...
@@ -245,6 +245,28 @@ static void regmap_format_32_native(void *buf, unsigned int val,
*
(
u32
*
)
buf
=
val
<<
shift
;
}
#ifdef CONFIG_64BIT
static
void
regmap_format_64_be
(
void
*
buf
,
unsigned
int
val
,
unsigned
int
shift
)
{
__be64
*
b
=
buf
;
b
[
0
]
=
cpu_to_be64
((
u64
)
val
<<
shift
);
}
static
void
regmap_format_64_le
(
void
*
buf
,
unsigned
int
val
,
unsigned
int
shift
)
{
__le64
*
b
=
buf
;
b
[
0
]
=
cpu_to_le64
((
u64
)
val
<<
shift
);
}
static
void
regmap_format_64_native
(
void
*
buf
,
unsigned
int
val
,
unsigned
int
shift
)
{
*
(
u64
*
)
buf
=
(
u64
)
val
<<
shift
;
}
#endif
static
void
regmap_parse_inplace_noop
(
void
*
buf
)
{
}
...
...
@@ -332,6 +354,41 @@ static unsigned int regmap_parse_32_native(const void *buf)
return
*
(
u32
*
)
buf
;
}
#ifdef CONFIG_64BIT
static
unsigned
int
regmap_parse_64_be
(
const
void
*
buf
)
{
const
__be64
*
b
=
buf
;
return
be64_to_cpu
(
b
[
0
]);
}
static
unsigned
int
regmap_parse_64_le
(
const
void
*
buf
)
{
const
__le64
*
b
=
buf
;
return
le64_to_cpu
(
b
[
0
]);
}
static
void
regmap_parse_64_be_inplace
(
void
*
buf
)
{
__be64
*
b
=
buf
;
b
[
0
]
=
be64_to_cpu
(
b
[
0
]);
}
static
void
regmap_parse_64_le_inplace
(
void
*
buf
)
{
__le64
*
b
=
buf
;
b
[
0
]
=
le64_to_cpu
(
b
[
0
]);
}
static
unsigned
int
regmap_parse_64_native
(
const
void
*
buf
)
{
return
*
(
u64
*
)
buf
;
}
#endif
static
void
regmap_lock_mutex
(
void
*
__map
)
{
struct
regmap
*
map
=
__map
;
...
...
@@ -712,6 +769,21 @@ struct regmap *__regmap_init(struct device *dev,
}
break
;
#ifdef CONFIG_64BIT
case
64
:
switch
(
reg_endian
)
{
case
REGMAP_ENDIAN_BIG
:
map
->
format
.
format_reg
=
regmap_format_64_be
;
break
;
case
REGMAP_ENDIAN_NATIVE
:
map
->
format
.
format_reg
=
regmap_format_64_native
;
break
;
default:
goto
err_map
;
}
break
;
#endif
default:
goto
err_map
;
}
...
...
@@ -771,6 +843,28 @@ struct regmap *__regmap_init(struct device *dev,
goto
err_map
;
}
break
;
#ifdef CONFIG_64BIT
case
64
:
switch
(
val_endian
)
{
case
REGMAP_ENDIAN_BIG
:
map
->
format
.
format_val
=
regmap_format_64_be
;
map
->
format
.
parse_val
=
regmap_parse_64_be
;
map
->
format
.
parse_inplace
=
regmap_parse_64_be_inplace
;
break
;
case
REGMAP_ENDIAN_LITTLE
:
map
->
format
.
format_val
=
regmap_format_64_le
;
map
->
format
.
parse_val
=
regmap_parse_64_le
;
map
->
format
.
parse_inplace
=
regmap_parse_64_le_inplace
;
break
;
case
REGMAP_ENDIAN_NATIVE
:
map
->
format
.
format_val
=
regmap_format_64_native
;
map
->
format
.
parse_val
=
regmap_parse_64_native
;
break
;
default:
goto
err_map
;
}
break
;
#endif
}
if
(
map
->
format
.
format_write
)
{
...
...
@@ -2488,11 +2582,19 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
* we assume that the values are native
* endian.
*/
#ifdef CONFIG_64BIT
u64
*
u64
=
val
;
#endif
u32
*
u32
=
val
;
u16
*
u16
=
val
;
u8
*
u8
=
val
;
switch
(
map
->
format
.
val_bytes
)
{
#ifdef CONFIG_64BIT
case
8
:
u64
[
i
]
=
ival
;
break
;
#endif
case
4
:
u32
[
i
]
=
ival
;
break
;
...
...
include/linux/regmap.h
View file @
a8d99344
...
...
@@ -788,10 +788,16 @@ int regmap_fields_update_bits(struct regmap_field *field, unsigned int id,
*
* @reg_offset: Offset of the status/mask register within the bank
* @mask: Mask used to flag/control the register.
* @type_reg_offset: Offset register for the irq type setting.
* @type_rising_mask: Mask bit to configure RISING type irq.
* @type_falling_mask: Mask bit to configure FALLING type irq.
*/
struct
regmap_irq
{
unsigned
int
reg_offset
;
unsigned
int
mask
;
unsigned
int
type_reg_offset
;
unsigned
int
type_rising_mask
;
unsigned
int
type_falling_mask
;
};
#define REGMAP_IRQ_REG(_irq, _off, _mask) \
...
...
@@ -811,18 +817,23 @@ struct regmap_irq {
* @ack_base: Base ack address. If zero then the chip is clear on read.
* Using zero value is possible with @use_ack bit.
* @wake_base: Base address for wake enables. If zero unsupported.
* @type_base: Base address for irq type. If zero unsupported.
* @irq_reg_stride: Stride to use for chips where registers are not contiguous.
* @init_ack_masked: Ack all masked interrupts once during initalization.
* @mask_invert: Inverted mask register: cleared bits are masked out.
* @use_ack: Use @ack register even if it is zero.
* @ack_invert: Inverted ack register: cleared bits for ack.
* @wake_invert: Inverted wake register: cleared bits are wake enabled.
* @type_invert: Invert the type flags.
* @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
* assigned based on the index in the array of the interrupt.
* @num_irqs: Number of descriptors.
* @num_type_reg: Number of type registers.
* @type_reg_stride: Stride to use for chips where type registers are not
* contiguous.
*/
struct
regmap_irq_chip
{
const
char
*
name
;
...
...
@@ -832,6 +843,7 @@ struct regmap_irq_chip {
unsigned
int
unmask_base
;
unsigned
int
ack_base
;
unsigned
int
wake_base
;
unsigned
int
type_base
;
unsigned
int
irq_reg_stride
;
bool
init_ack_masked
:
1
;
bool
mask_invert
:
1
;
...
...
@@ -839,11 +851,15 @@ struct regmap_irq_chip {
bool
ack_invert
:
1
;
bool
wake_invert
:
1
;
bool
runtime_pm
:
1
;
bool
type_invert
:
1
;
int
num_regs
;
const
struct
regmap_irq
*
irqs
;
int
num_irqs
;
int
num_type_reg
;
unsigned
int
type_reg_stride
;
};
struct
regmap_irq_chip_data
;
...
...
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