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
9b98f92c
Commit
9b98f92c
authored
May 29, 2020
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'regmap/for-5.8' into regmap-next
parents
4bcc6a0b
93b92992
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
222 additions
and
55 deletions
+222
-55
drivers/base/regmap/regmap-i2c.c
drivers/base/regmap/regmap-i2c.c
+61
-0
drivers/base/regmap/regmap-irq.c
drivers/base/regmap/regmap-irq.c
+68
-16
drivers/base/regmap/regmap.c
drivers/base/regmap/regmap.c
+23
-0
include/linux/regmap.h
include/linux/regmap.h
+70
-39
No files found.
drivers/base/regmap/regmap-i2c.c
View file @
9b98f92c
...
...
@@ -246,6 +246,63 @@ static const struct regmap_bus regmap_i2c_smbus_i2c_block = {
.
max_raw_write
=
I2C_SMBUS_BLOCK_MAX
,
};
static
int
regmap_i2c_smbus_i2c_write_reg16
(
void
*
context
,
const
void
*
data
,
size_t
count
)
{
struct
device
*
dev
=
context
;
struct
i2c_client
*
i2c
=
to_i2c_client
(
dev
);
if
(
count
<
2
)
return
-
EINVAL
;
count
--
;
return
i2c_smbus_write_i2c_block_data
(
i2c
,
((
u8
*
)
data
)[
0
],
count
,
(
u8
*
)
data
+
1
);
}
static
int
regmap_i2c_smbus_i2c_read_reg16
(
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
);
int
ret
,
count
,
len
=
val_size
;
if
(
reg_size
!=
2
)
return
-
EINVAL
;
ret
=
i2c_smbus_write_byte_data
(
i2c
,
((
u16
*
)
reg
)[
0
]
&
0xff
,
((
u16
*
)
reg
)[
0
]
>>
8
);
if
(
ret
<
0
)
return
ret
;
count
=
0
;
do
{
/* Current Address Read */
ret
=
i2c_smbus_read_byte
(
i2c
);
if
(
ret
<
0
)
break
;
*
((
u8
*
)
val
++
)
=
ret
;
count
++
;
len
--
;
}
while
(
len
>
0
);
if
(
count
==
val_size
)
return
0
;
else
if
(
ret
<
0
)
return
ret
;
else
return
-
EIO
;
}
static
const
struct
regmap_bus
regmap_i2c_smbus_i2c_block_reg16
=
{
.
write
=
regmap_i2c_smbus_i2c_write_reg16
,
.
read
=
regmap_i2c_smbus_i2c_read_reg16
,
.
max_raw_read
=
I2C_SMBUS_BLOCK_MAX
,
.
max_raw_write
=
I2C_SMBUS_BLOCK_MAX
,
};
static
const
struct
regmap_bus
*
regmap_get_i2c_bus
(
struct
i2c_client
*
i2c
,
const
struct
regmap_config
*
config
)
{
...
...
@@ -255,6 +312,10 @@ static const struct regmap_bus *regmap_get_i2c_bus(struct i2c_client *i2c,
i2c_check_functionality
(
i2c
->
adapter
,
I2C_FUNC_SMBUS_I2C_BLOCK
))
return
&
regmap_i2c_smbus_i2c_block
;
else
if
(
config
->
val_bits
==
8
&&
config
->
reg_bits
==
16
&&
i2c_check_functionality
(
i2c
->
adapter
,
I2C_FUNC_SMBUS_I2C_BLOCK
))
return
&
regmap_i2c_smbus_i2c_block_reg16
;
else
if
(
config
->
val_bits
==
16
&&
config
->
reg_bits
==
8
&&
i2c_check_functionality
(
i2c
->
adapter
,
I2C_FUNC_SMBUS_WORD_DATA
))
...
...
drivers/base/regmap/regmap-irq.c
View file @
9b98f92c
...
...
@@ -541,8 +541,9 @@ static const struct irq_domain_ops regmap_domain_ops = {
};
/**
* regmap_add_irq_chip() - Use standard regmap IRQ controller handling
* regmap_add_irq_chip
_np
() - Use standard regmap IRQ controller handling
*
* @np: The device_node where the IRQ domain should be added to.
* @map: The regmap for the device.
* @irq: The IRQ the device uses to signal interrupts.
* @irq_flags: The IRQF_ flags to use for the primary interrupt.
...
...
@@ -556,8 +557,9 @@ static const struct irq_domain_ops regmap_domain_ops = {
* register cache. The chip driver is responsible for restoring the
* register values used by the IRQ controller over suspend and resume.
*/
int
regmap_add_irq_chip
(
struct
regmap
*
map
,
int
irq
,
int
irq_flags
,
int
irq_base
,
const
struct
regmap_irq_chip
*
chip
,
int
regmap_add_irq_chip_np
(
struct
device_node
*
np
,
struct
regmap
*
map
,
int
irq
,
int
irq_flags
,
int
irq_base
,
const
struct
regmap_irq_chip
*
chip
,
struct
regmap_irq_chip_data
**
data
)
{
struct
regmap_irq_chip_data
*
d
;
...
...
@@ -769,12 +771,10 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
}
if
(
irq_base
)
d
->
domain
=
irq_domain_add_legacy
(
map
->
dev
->
of_node
,
chip
->
num_irqs
,
irq_base
,
0
,
&
regmap_domain_ops
,
d
);
d
->
domain
=
irq_domain_add_legacy
(
np
,
chip
->
num_irqs
,
irq_base
,
0
,
&
regmap_domain_ops
,
d
);
else
d
->
domain
=
irq_domain_add_linear
(
map
->
dev
->
of_node
,
chip
->
num_irqs
,
d
->
domain
=
irq_domain_add_linear
(
np
,
chip
->
num_irqs
,
&
regmap_domain_ops
,
d
);
if
(
!
d
->
domain
)
{
dev_err
(
map
->
dev
,
"Failed to create IRQ domain
\n
"
);
...
...
@@ -808,6 +808,30 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
kfree
(
d
);
return
ret
;
}
EXPORT_SYMBOL_GPL
(
regmap_add_irq_chip_np
);
/**
* regmap_add_irq_chip() - Use standard regmap IRQ controller handling
*
* @map: The regmap for the device.
* @irq: The IRQ the device uses to signal interrupts.
* @irq_flags: The IRQF_ flags to use for the primary interrupt.
* @irq_base: Allocate at specific IRQ number if irq_base > 0.
* @chip: Configuration for the interrupt controller.
* @data: Runtime data structure for the controller, allocated on success.
*
* Returns 0 on success or an errno on failure.
*
* This is the same as regmap_add_irq_chip_np, except that the device
* node of the regmap is used.
*/
int
regmap_add_irq_chip
(
struct
regmap
*
map
,
int
irq
,
int
irq_flags
,
int
irq_base
,
const
struct
regmap_irq_chip
*
chip
,
struct
regmap_irq_chip_data
**
data
)
{
return
regmap_add_irq_chip_np
(
map
->
dev
->
of_node
,
map
,
irq
,
irq_flags
,
irq_base
,
chip
,
data
);
}
EXPORT_SYMBOL_GPL
(
regmap_add_irq_chip
);
/**
...
...
@@ -875,9 +899,10 @@ static int devm_regmap_irq_chip_match(struct device *dev, void *res, void *data)
}
/**
* devm_regmap_add_irq_chip
() - Resource manager regmap_add_irq_chi
p()
* devm_regmap_add_irq_chip
_np() - Resource manager regmap_add_irq_chip_n
p()
*
* @dev: The device pointer on which irq_chip belongs to.
* @np: The device_node where the IRQ domain should be added to.
* @map: The regmap for the device.
* @irq: The IRQ the device uses to signal interrupts
* @irq_flags: The IRQF_ flags to use for the primary interrupt.
...
...
@@ -890,8 +915,9 @@ static int devm_regmap_irq_chip_match(struct device *dev, void *res, void *data)
* The ®map_irq_chip_data will be automatically released when the device is
* unbound.
*/
int
devm_regmap_add_irq_chip
(
struct
device
*
dev
,
struct
regmap
*
map
,
int
irq
,
int
irq_flags
,
int
irq_base
,
int
devm_regmap_add_irq_chip_np
(
struct
device
*
dev
,
struct
device_node
*
np
,
struct
regmap
*
map
,
int
irq
,
int
irq_flags
,
int
irq_base
,
const
struct
regmap_irq_chip
*
chip
,
struct
regmap_irq_chip_data
**
data
)
{
...
...
@@ -903,7 +929,7 @@ int devm_regmap_add_irq_chip(struct device *dev, struct regmap *map, int irq,
if
(
!
ptr
)
return
-
ENOMEM
;
ret
=
regmap_add_irq_chip
(
map
,
irq
,
irq_flags
,
irq_base
,
ret
=
regmap_add_irq_chip
_np
(
np
,
map
,
irq
,
irq_flags
,
irq_base
,
chip
,
&
d
);
if
(
ret
<
0
)
{
devres_free
(
ptr
);
...
...
@@ -915,6 +941,32 @@ int devm_regmap_add_irq_chip(struct device *dev, struct regmap *map, int irq,
*
data
=
d
;
return
0
;
}
EXPORT_SYMBOL_GPL
(
devm_regmap_add_irq_chip_np
);
/**
* devm_regmap_add_irq_chip() - Resource manager regmap_add_irq_chip()
*
* @dev: The device pointer on which irq_chip belongs to.
* @map: The regmap for the device.
* @irq: The IRQ the device uses to signal interrupts
* @irq_flags: The IRQF_ flags to use for the primary interrupt.
* @irq_base: Allocate at specific IRQ number if irq_base > 0.
* @chip: Configuration for the interrupt controller.
* @data: Runtime data structure for the controller, allocated on success
*
* Returns 0 on success or an errno on failure.
*
* The ®map_irq_chip_data will be automatically released when the device is
* unbound.
*/
int
devm_regmap_add_irq_chip
(
struct
device
*
dev
,
struct
regmap
*
map
,
int
irq
,
int
irq_flags
,
int
irq_base
,
const
struct
regmap_irq_chip
*
chip
,
struct
regmap_irq_chip_data
**
data
)
{
return
devm_regmap_add_irq_chip_np
(
dev
,
map
->
dev
->
of_node
,
map
,
irq
,
irq_flags
,
irq_base
,
chip
,
data
);
}
EXPORT_SYMBOL_GPL
(
devm_regmap_add_irq_chip
);
/**
...
...
drivers/base/regmap/regmap.c
View file @
9b98f92c
...
...
@@ -827,6 +827,7 @@ struct regmap *__regmap_init(struct device *dev,
}
else
if
(
!
bus
->
read
||
!
bus
->
write
)
{
map
->
reg_read
=
_regmap_bus_reg_read
;
map
->
reg_write
=
_regmap_bus_reg_write
;
map
->
reg_update_bits
=
bus
->
reg_update_bits
;
map
->
defer_caching
=
false
;
goto
skip_format_initialization
;
...
...
@@ -2936,6 +2937,28 @@ int regmap_update_bits_base(struct regmap *map, unsigned int reg,
}
EXPORT_SYMBOL_GPL
(
regmap_update_bits_base
);
/**
* regmap_test_bits() - Check if all specified bits are set in a register.
*
* @map: Register map to operate on
* @reg: Register to read from
* @bits: Bits to test
*
* Returns -1 if the underlying regmap_read() fails, 0 if at least one of the
* tested bits is not set and 1 if all tested bits are set.
*/
int
regmap_test_bits
(
struct
regmap
*
map
,
unsigned
int
reg
,
unsigned
int
bits
)
{
unsigned
int
val
,
ret
;
ret
=
regmap_read
(
map
,
reg
,
&
val
);
if
(
ret
)
return
ret
;
return
(
val
&
bits
)
==
bits
;
}
EXPORT_SYMBOL_GPL
(
regmap_test_bits
);
void
regmap_async_complete_cb
(
struct
regmap_async
*
async
,
int
ret
)
{
struct
regmap
*
map
=
async
->
map
;
...
...
include/linux/regmap.h
View file @
9b98f92c
...
...
@@ -17,10 +17,12 @@
#include <linux/err.h>
#include <linux/bug.h>
#include <linux/lockdep.h>
#include <linux/iopoll.h>
struct
module
;
struct
clk
;
struct
device
;
struct
device_node
;
struct
i2c_client
;
struct
i3c_device
;
struct
irq_domain
;
...
...
@@ -71,6 +73,13 @@ struct reg_sequence {
unsigned
int
delay_us
;
};
#define REG_SEQ(_reg, _def, _delay_us) { \
.reg = _reg, \
.def = _def, \
.delay_us = _delay_us, \
}
#define REG_SEQ0(_reg, _def) REG_SEQ(_reg, _def, 0)
#define regmap_update_bits(map, reg, mask, val) \
regmap_update_bits_base(map, reg, mask, val, NULL, false, false)
#define regmap_update_bits_async(map, reg, mask, val)\
...
...
@@ -122,26 +131,10 @@ struct reg_sequence {
*/
#define regmap_read_poll_timeout(map, addr, val, cond, sleep_us, timeout_us) \
({ \
u64 __timeout_us = (timeout_us); \
unsigned long __sleep_us = (sleep_us); \
ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us); \
int __ret; \
might_sleep_if(__sleep_us); \
for (;;) { \
__ret = regmap_read((map), (addr), &(val)); \
if (__ret) \
break; \
if (cond) \
break; \
if ((__timeout_us) && \
ktime_compare(ktime_get(), __timeout) > 0) { \
__ret = regmap_read((map), (addr), &(val)); \
break; \
} \
if (__sleep_us) \
usleep_range((__sleep_us >> 2) + 1, __sleep_us); \
} \
__ret ?: ((cond) ? 0 : -ETIMEDOUT); \
int __ret, __tmp; \
__tmp = read_poll_timeout(regmap_read, __ret, __ret || (cond), \
sleep_us, timeout_us, false, (map), (addr), &(val)); \
__ret ?: __tmp; \
})
/**
...
...
@@ -209,25 +202,10 @@ struct reg_sequence {
*/
#define regmap_field_read_poll_timeout(field, val, cond, sleep_us, timeout_us) \
({ \
u64 __timeout_us = (timeout_us); \
unsigned long __sleep_us = (sleep_us); \
ktime_t timeout = ktime_add_us(ktime_get(), __timeout_us); \
int pollret; \
might_sleep_if(__sleep_us); \
for (;;) { \
pollret = regmap_field_read((field), &(val)); \
if (pollret) \
break; \
if (cond) \
break; \
if (__timeout_us && ktime_compare(ktime_get(), timeout) > 0) { \
pollret = regmap_field_read((field), &(val)); \
break; \
} \
if (__sleep_us) \
usleep_range((__sleep_us >> 2) + 1, __sleep_us); \
} \
pollret ?: ((cond) ? 0 : -ETIMEDOUT); \
int __ret, __tmp; \
__tmp = read_poll_timeout(regmap_field_read, __ret, __ret || (cond), \
sleep_us, timeout_us, false, (field), &(val)); \
__ret ?: __tmp; \
})
#ifdef CONFIG_REGMAP
...
...
@@ -1111,6 +1089,21 @@ bool regmap_reg_in_ranges(unsigned int reg,
const
struct
regmap_range
*
ranges
,
unsigned
int
nranges
);
static
inline
int
regmap_set_bits
(
struct
regmap
*
map
,
unsigned
int
reg
,
unsigned
int
bits
)
{
return
regmap_update_bits_base
(
map
,
reg
,
bits
,
bits
,
NULL
,
false
,
false
);
}
static
inline
int
regmap_clear_bits
(
struct
regmap
*
map
,
unsigned
int
reg
,
unsigned
int
bits
)
{
return
regmap_update_bits_base
(
map
,
reg
,
bits
,
0
,
NULL
,
false
,
false
);
}
int
regmap_test_bits
(
struct
regmap
*
map
,
unsigned
int
reg
,
unsigned
int
bits
);
/**
* struct reg_field - Description of an register field
*
...
...
@@ -1134,6 +1127,14 @@ struct reg_field {
.msb = _msb, \
}
#define REG_FIELD_ID(_reg, _lsb, _msb, _size, _offset) { \
.reg = _reg, \
.lsb = _lsb, \
.msb = _msb, \
.id_size = _size, \
.id_offset = _offset, \
}
struct
regmap_field
*
regmap_field_alloc
(
struct
regmap
*
regmap
,
struct
reg_field
reg_field
);
void
regmap_field_free
(
struct
regmap_field
*
field
);
...
...
@@ -1310,12 +1311,21 @@ struct regmap_irq_chip_data;
int
regmap_add_irq_chip
(
struct
regmap
*
map
,
int
irq
,
int
irq_flags
,
int
irq_base
,
const
struct
regmap_irq_chip
*
chip
,
struct
regmap_irq_chip_data
**
data
);
int
regmap_add_irq_chip_np
(
struct
device_node
*
np
,
struct
regmap
*
map
,
int
irq
,
int
irq_flags
,
int
irq_base
,
const
struct
regmap_irq_chip
*
chip
,
struct
regmap_irq_chip_data
**
data
);
void
regmap_del_irq_chip
(
int
irq
,
struct
regmap_irq_chip_data
*
data
);
int
devm_regmap_add_irq_chip
(
struct
device
*
dev
,
struct
regmap
*
map
,
int
irq
,
int
irq_flags
,
int
irq_base
,
const
struct
regmap_irq_chip
*
chip
,
struct
regmap_irq_chip_data
**
data
);
int
devm_regmap_add_irq_chip_np
(
struct
device
*
dev
,
struct
device_node
*
np
,
struct
regmap
*
map
,
int
irq
,
int
irq_flags
,
int
irq_base
,
const
struct
regmap_irq_chip
*
chip
,
struct
regmap_irq_chip_data
**
data
);
void
devm_regmap_del_irq_chip
(
struct
device
*
dev
,
int
irq
,
struct
regmap_irq_chip_data
*
data
);
...
...
@@ -1410,6 +1420,27 @@ static inline int regmap_update_bits_base(struct regmap *map, unsigned int reg,
return
-
EINVAL
;
}
static
inline
int
regmap_set_bits
(
struct
regmap
*
map
,
unsigned
int
reg
,
unsigned
int
bits
)
{
WARN_ONCE
(
1
,
"regmap API is disabled"
);
return
-
EINVAL
;
}
static
inline
int
regmap_clear_bits
(
struct
regmap
*
map
,
unsigned
int
reg
,
unsigned
int
bits
)
{
WARN_ONCE
(
1
,
"regmap API is disabled"
);
return
-
EINVAL
;
}
static
inline
int
regmap_test_bits
(
struct
regmap
*
map
,
unsigned
int
reg
,
unsigned
int
bits
)
{
WARN_ONCE
(
1
,
"regmap API is disabled"
);
return
-
EINVAL
;
}
static
inline
int
regmap_field_update_bits_base
(
struct
regmap_field
*
field
,
unsigned
int
mask
,
unsigned
int
val
,
bool
*
change
,
bool
async
,
bool
force
)
...
...
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