mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 06:01:57 +00:00
mfd: syscon: Add of_syscon_register_regmap() API
The of_syscon_register_regmap() API allows an externally created regmap to be registered with syscon. This regmap can then be returned to client drivers using the syscon_regmap_lookup_by_phandle() APIs. The API is used by platforms where mmio access to the syscon registers is not possible, and a underlying soc driver like exynos-pmu provides a SoC specific regmap that can issue a SMC or hypervisor call to write the register. This approach keeps the SoC complexities out of syscon, but allows common drivers such as syscon-poweroff, syscon-reboot and friends that are used by many SoCs already to be re-used. Signed-off-by: Peter Griffin <peter.griffin@linaro.org> Reviewed-by: Arnd Bergmann <arnd@arndb.de> Reviewed-by: Sam Protsenko <semen.protsenko@linaro.org> Tested-by: Will McVicker <willmcvicker@google.com> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> Link: https://lore.kernel.org/r/20240621115544.1655458-2-peter.griffin@linaro.org Signed-off-by: Lee Jones <lee@kernel.org>
This commit is contained in:
parent
1613e604df
commit
769cb63166
@ -192,6 +192,54 @@ static struct regmap *device_node_get_regmap(struct device_node *np,
|
||||
return syscon->regmap;
|
||||
}
|
||||
|
||||
/**
|
||||
* of_syscon_register_regmap() - Register regmap for specified device node
|
||||
* @np: Device tree node
|
||||
* @regmap: Pointer to regmap object
|
||||
*
|
||||
* Register an externally created regmap object with syscon for the specified
|
||||
* device tree node. This regmap will then be returned to client drivers using
|
||||
* the syscon_regmap_lookup_by_phandle() API.
|
||||
*
|
||||
* Return: 0 on success, negative error code on failure.
|
||||
*/
|
||||
int of_syscon_register_regmap(struct device_node *np, struct regmap *regmap)
|
||||
{
|
||||
struct syscon *entry, *syscon = NULL;
|
||||
int ret;
|
||||
|
||||
if (!np || !regmap)
|
||||
return -EINVAL;
|
||||
|
||||
syscon = kzalloc(sizeof(*syscon), GFP_KERNEL);
|
||||
if (!syscon)
|
||||
return -ENOMEM;
|
||||
|
||||
/* check if syscon entry already exists */
|
||||
spin_lock(&syscon_list_slock);
|
||||
|
||||
list_for_each_entry(entry, &syscon_list, list)
|
||||
if (entry->np == np) {
|
||||
ret = -EEXIST;
|
||||
goto err_unlock;
|
||||
}
|
||||
|
||||
syscon->regmap = regmap;
|
||||
syscon->np = np;
|
||||
|
||||
/* register the regmap in syscon list */
|
||||
list_add_tail(&syscon->list, &syscon_list);
|
||||
spin_unlock(&syscon_list_slock);
|
||||
|
||||
return 0;
|
||||
|
||||
err_unlock:
|
||||
spin_unlock(&syscon_list_slock);
|
||||
kfree(syscon);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_syscon_register_regmap);
|
||||
|
||||
struct regmap *device_node_to_regmap(struct device_node *np)
|
||||
{
|
||||
return device_node_get_regmap(np, false);
|
||||
|
@ -28,6 +28,8 @@ struct regmap *syscon_regmap_lookup_by_phandle_args(struct device_node *np,
|
||||
unsigned int *out_args);
|
||||
struct regmap *syscon_regmap_lookup_by_phandle_optional(struct device_node *np,
|
||||
const char *property);
|
||||
int of_syscon_register_regmap(struct device_node *np,
|
||||
struct regmap *regmap);
|
||||
#else
|
||||
static inline struct regmap *device_node_to_regmap(struct device_node *np)
|
||||
{
|
||||
@ -67,6 +69,12 @@ static inline struct regmap *syscon_regmap_lookup_by_phandle_optional(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int of_syscon_register_regmap(struct device_node *np,
|
||||
struct regmap *regmap)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __LINUX_MFD_SYSCON_H__ */
|
||||
|
Loading…
Reference in New Issue
Block a user