mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-09-16 04:29:28 -05:00
mfd: rohm: Factor out power button registration
Factor out the power button registration logic using software nodes from rohm-bd718x7 and rohm-bd71828 drivers into a shared module rohm-pwrbutton. This reduces duplication and makes it easier to support other ROHM PMICs with similar power button configurations. Suggested-by: Lee Jones <lee@kernel.org> Assisted-by: Antigravity:gemini-3.5-flash Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> Reviewed-by: Matti Vaittinen <mazziesaccount@gmail.com> Link: https://patch.msgid.link/akw4naN2Khjv8itB@google.com Signed-off-by: Lee Jones <lee@kernel.org>
This commit is contained in:
committed by
Lee Jones
parent
cbff6a720d
commit
1b86b4ef3a
@@ -23555,6 +23555,8 @@ F: drivers/mfd/rohm-bd71828.c
|
||||
F: drivers/mfd/rohm-bd718x7.c
|
||||
F: drivers/mfd/rohm-bd9576.c
|
||||
F: drivers/mfd/rohm-bd96801.c
|
||||
F: drivers/mfd/rohm-pwrbutton.c
|
||||
F: drivers/mfd/rohm-pwrbutton.h
|
||||
F: drivers/regulator/bd71815-regulator.c
|
||||
F: drivers/regulator/bd71828-regulator.c
|
||||
F: drivers/regulator/bd718x7-regulator.c
|
||||
|
||||
@@ -2207,6 +2207,10 @@ config MFD_STW481X
|
||||
in various ST Microelectronics and ST-Ericsson embedded
|
||||
Nomadik series.
|
||||
|
||||
config MFD_ROHM_PWRBUTTON
|
||||
tristate
|
||||
select MFD_CORE
|
||||
|
||||
config MFD_ROHM_BD718XX
|
||||
tristate "ROHM BD71837 Power Management IC"
|
||||
depends on I2C=y
|
||||
@@ -2214,6 +2218,7 @@ config MFD_ROHM_BD718XX
|
||||
select REGMAP_I2C
|
||||
select REGMAP_IRQ
|
||||
select MFD_CORE
|
||||
select MFD_ROHM_PWRBUTTON
|
||||
help
|
||||
Select this option to get support for the ROHM BD71837
|
||||
Power Management ICs. BD71837 is designed to power processors like
|
||||
@@ -2227,6 +2232,7 @@ config MFD_ROHM_BD71828
|
||||
select REGMAP_I2C
|
||||
select REGMAP_IRQ
|
||||
select MFD_CORE
|
||||
select MFD_ROHM_PWRBUTTON
|
||||
help
|
||||
Select this option to get support for the ROHM BD71815, BD71828,
|
||||
BD71879, BD72720 and BD73900 Power Management ICs (PMICs). These are
|
||||
|
||||
@@ -273,6 +273,7 @@ obj-$(CONFIG_MFD_STM32_TIMERS) += stm32-timers.o
|
||||
obj-$(CONFIG_MFD_MXS_LRADC) += mxs-lradc.o
|
||||
obj-$(CONFIG_MFD_SC27XX_PMIC) += sprd-sc27xx-spi.o
|
||||
obj-$(CONFIG_RAVE_SP_CORE) += rave-sp.o
|
||||
obj-$(CONFIG_MFD_ROHM_PWRBUTTON) += rohm-pwrbutton.o
|
||||
obj-$(CONFIG_MFD_ROHM_BD71828) += rohm-bd71828.o
|
||||
obj-$(CONFIG_MFD_ROHM_BD718XX) += rohm-bd718x7.o
|
||||
obj-$(CONFIG_MFD_ROHM_BD957XMUF) += rohm-bd9576.o
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
* ROHM BD718[15/28/79] and BD72720 PMIC driver
|
||||
*/
|
||||
|
||||
#include <linux/device/devres.h>
|
||||
#include <linux/gfp_types.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/interrupt.h>
|
||||
@@ -19,10 +17,11 @@
|
||||
#include <linux/mfd/rohm-generic.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "rohm-pwrbutton.h"
|
||||
|
||||
#define BD72720_TYPED_IRQ_REG(_irq, _stat_offset, _mask, _type_offset) \
|
||||
[_irq] = { \
|
||||
.reg_offset = (_stat_offset), \
|
||||
@@ -859,83 +858,7 @@ static int set_clk_mode(struct device *dev, struct regmap *regmap,
|
||||
OUT32K_MODE_CMOS);
|
||||
}
|
||||
|
||||
static const struct property_entry bd71828_powerkey_parent_props[] = {
|
||||
PROPERTY_ENTRY_STRING("label", "bd71828-pwrkey"),
|
||||
{ }
|
||||
};
|
||||
|
||||
static const struct property_entry bd71828_powerkey_props[] = {
|
||||
PROPERTY_ENTRY_U32("linux,code", KEY_POWER),
|
||||
PROPERTY_ENTRY_BOOL("wakeup-source"),
|
||||
{ }
|
||||
};
|
||||
|
||||
#define GPIO_KEYS 0 /* Node corresponding to gpio-keys device itself */
|
||||
#define PWRON_KEY 1 /* Node describing power button in gpio-keys */
|
||||
|
||||
static int bd71828_i2c_register_swnodes(const struct software_node *nodes)
|
||||
{
|
||||
const struct software_node * const node_group[] = {
|
||||
&nodes[GPIO_KEYS], &nodes[PWRON_KEY], NULL
|
||||
};
|
||||
|
||||
return software_node_register_node_group(node_group);
|
||||
}
|
||||
|
||||
static void bd71828_i2c_unregister_swnodes(void *data)
|
||||
{
|
||||
const struct software_node *nodes = data;
|
||||
const struct software_node * const node_group[] = {
|
||||
&nodes[GPIO_KEYS], &nodes[PWRON_KEY], NULL
|
||||
};
|
||||
|
||||
software_node_unregister_node_group(node_group);
|
||||
}
|
||||
|
||||
static int bd71828_i2c_register_pwrbutton(struct device *dev, int button_irq,
|
||||
struct irq_domain *irq_domain)
|
||||
{
|
||||
const struct resource res[] = {
|
||||
DEFINE_RES_IRQ_NAMED(button_irq, "bd71828-pwrkey"),
|
||||
};
|
||||
struct mfd_cell gpio_keys_cell = {
|
||||
.name = "gpio-keys",
|
||||
.resources = res,
|
||||
.num_resources = ARRAY_SIZE(res),
|
||||
};
|
||||
struct software_node *nodes;
|
||||
int ret;
|
||||
|
||||
nodes = devm_kcalloc(dev, 2, sizeof(*nodes), GFP_KERNEL);
|
||||
if (!nodes)
|
||||
return -ENOMEM;
|
||||
|
||||
nodes[GPIO_KEYS].name = devm_kasprintf(dev, GFP_KERNEL, "%s-power-key", dev_name(dev));
|
||||
if (!nodes[GPIO_KEYS].name)
|
||||
return -ENOMEM;
|
||||
|
||||
nodes[GPIO_KEYS].properties = bd71828_powerkey_parent_props;
|
||||
|
||||
nodes[PWRON_KEY].parent = &nodes[GPIO_KEYS];
|
||||
nodes[PWRON_KEY].properties = bd71828_powerkey_props;
|
||||
|
||||
ret = bd71828_i2c_register_swnodes(nodes);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_add_action_or_reset(dev, bd71828_i2c_unregister_swnodes, nodes);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
gpio_keys_cell.swnode = &nodes[GPIO_KEYS];
|
||||
|
||||
ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, &gpio_keys_cell, 1,
|
||||
NULL, 0, irq_domain);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Failed to register power-button");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct i2c_client *bd71828_dev;
|
||||
static void bd71828_power_off(void)
|
||||
@@ -1096,7 +1019,8 @@ static int bd71828_i2c_probe(struct i2c_client *i2c)
|
||||
return dev_err_probe(&i2c->dev, ret, "Failed to create subdevices\n");
|
||||
|
||||
if (button_irq) {
|
||||
ret = bd71828_i2c_register_pwrbutton(&i2c->dev, button_irq, irq_domain);
|
||||
ret = rohm_register_pwrbutton(&i2c->dev, button_irq,
|
||||
"bd71828-pwrkey", true, irq_domain);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
// Datasheet for BD71837MWV available from
|
||||
// https://www.rohm.com/datasheet/BD71837MWV/bd71837mwv-e
|
||||
|
||||
#include <linux/device/devres.h>
|
||||
#include <linux/gfp_types.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/interrupt.h>
|
||||
@@ -16,10 +14,11 @@
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "rohm-pwrbutton.h"
|
||||
|
||||
static struct mfd_cell bd71837_mfd_cells[] = {
|
||||
{ .name = "bd71837-clk", },
|
||||
{ .name = "bd71837-pmic", },
|
||||
@@ -105,83 +104,7 @@ static int bd718xx_init_press_duration(struct regmap *regmap,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct property_entry bd718xx_powerkey_parent_props[] = {
|
||||
PROPERTY_ENTRY_STRING("label", "bd718xx-pwrkey"),
|
||||
{ }
|
||||
};
|
||||
|
||||
static const struct property_entry bd718xx_powerkey_props[] = {
|
||||
PROPERTY_ENTRY_U32("linux,code", KEY_POWER),
|
||||
{ }
|
||||
};
|
||||
|
||||
static const struct resource bd718xx_powerkey_resources[] = {
|
||||
DEFINE_RES_IRQ_NAMED(BD718XX_INT_PWRBTN_S, "bd718xx-pwrkey"),
|
||||
};
|
||||
|
||||
#define GPIO_KEYS 0 /* Node corresponding to gpio-keys device itself */
|
||||
#define PWRON_KEY 1 /* Node describing power button in gpio-keys */
|
||||
|
||||
static int bd718xx_i2c_register_swnodes(const struct software_node *nodes)
|
||||
{
|
||||
const struct software_node * const node_group[] = {
|
||||
&nodes[GPIO_KEYS], &nodes[PWRON_KEY], NULL
|
||||
};
|
||||
|
||||
return software_node_register_node_group(node_group);
|
||||
}
|
||||
|
||||
static void bd718xx_i2c_unregister_swnodes(void *data)
|
||||
{
|
||||
const struct software_node *nodes = data;
|
||||
const struct software_node * const node_group[] = {
|
||||
&nodes[GPIO_KEYS], &nodes[PWRON_KEY], NULL
|
||||
};
|
||||
|
||||
software_node_unregister_node_group(node_group);
|
||||
}
|
||||
|
||||
static int bd718xx_i2c_register_pwrbutton(struct device *dev,
|
||||
struct irq_domain *irq_domain)
|
||||
{
|
||||
struct mfd_cell gpio_keys_cell = {
|
||||
.name = "gpio-keys",
|
||||
.resources = bd718xx_powerkey_resources,
|
||||
.num_resources = ARRAY_SIZE(bd718xx_powerkey_resources),
|
||||
};
|
||||
struct software_node *nodes;
|
||||
int ret;
|
||||
|
||||
nodes = devm_kcalloc(dev, 2, sizeof(*nodes), GFP_KERNEL);
|
||||
if (!nodes)
|
||||
return -ENOMEM;
|
||||
|
||||
nodes[GPIO_KEYS].name = devm_kasprintf(dev, GFP_KERNEL, "%s-power-key", dev_name(dev));
|
||||
if (!nodes[GPIO_KEYS].name)
|
||||
return -ENOMEM;
|
||||
|
||||
nodes[GPIO_KEYS].properties = bd718xx_powerkey_parent_props;
|
||||
|
||||
nodes[PWRON_KEY].parent = &nodes[GPIO_KEYS];
|
||||
nodes[PWRON_KEY].properties = bd718xx_powerkey_props;
|
||||
|
||||
ret = bd718xx_i2c_register_swnodes(nodes);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_add_action_or_reset(dev, bd718xx_i2c_unregister_swnodes, nodes);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
gpio_keys_cell.swnode = &nodes[GPIO_KEYS];
|
||||
|
||||
ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, &gpio_keys_cell, 1,
|
||||
NULL, 0, irq_domain);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Failed to register power-button");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bd718xx_i2c_probe(struct i2c_client *i2c)
|
||||
{
|
||||
@@ -235,7 +158,8 @@ static int bd718xx_i2c_probe(struct i2c_client *i2c)
|
||||
if (ret)
|
||||
return dev_err_probe(&i2c->dev, ret, "Failed to create subdevices\n");
|
||||
|
||||
ret = bd718xx_i2c_register_pwrbutton(&i2c->dev, irq_domain);
|
||||
ret = rohm_register_pwrbutton(&i2c->dev, BD718XX_INT_PWRBTN_S,
|
||||
"bd718xx-pwrkey", false, irq_domain);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Shared helper for ROHM PMIC power button registration
|
||||
*
|
||||
* Copyright 2018, 2019 ROHM Semiconductors
|
||||
* Copyright 2026 Google LLC
|
||||
*/
|
||||
|
||||
#include <linux/device/devres.h>
|
||||
#include <linux/gfp_types.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "rohm-pwrbutton.h"
|
||||
|
||||
#define GPIO_KEYS 0 /* Node corresponding to gpio-keys device itself */
|
||||
#define PWRON_KEY 1 /* Node describing power button in gpio-keys */
|
||||
|
||||
static int rohm_pwrbutton_register_swnodes(const struct software_node *nodes)
|
||||
{
|
||||
const struct software_node * const node_group[] = {
|
||||
&nodes[GPIO_KEYS], &nodes[PWRON_KEY], NULL
|
||||
};
|
||||
|
||||
return software_node_register_node_group(node_group);
|
||||
}
|
||||
|
||||
static void rohm_pwrbutton_unregister_swnodes(void *data)
|
||||
{
|
||||
const struct software_node *nodes = data;
|
||||
const struct software_node * const node_group[] = {
|
||||
&nodes[GPIO_KEYS], &nodes[PWRON_KEY], NULL
|
||||
};
|
||||
|
||||
software_node_unregister_node_group(node_group);
|
||||
}
|
||||
|
||||
int rohm_register_pwrbutton(struct device *dev, int irq, const char *name,
|
||||
bool wakeup, struct irq_domain *irq_domain)
|
||||
{
|
||||
const struct resource res[] = {
|
||||
DEFINE_RES_IRQ_NAMED(irq, name),
|
||||
};
|
||||
struct mfd_cell gpio_keys_cell = {
|
||||
.name = "gpio-keys",
|
||||
.resources = res,
|
||||
.num_resources = ARRAY_SIZE(res),
|
||||
};
|
||||
struct property_entry *parent_props;
|
||||
struct property_entry *child_props;
|
||||
struct software_node *nodes;
|
||||
int n_props;
|
||||
int ret;
|
||||
|
||||
if (irq <= 0)
|
||||
return -EINVAL;
|
||||
|
||||
nodes = devm_kcalloc(dev, 2, sizeof(*nodes), GFP_KERNEL);
|
||||
if (!nodes)
|
||||
return -ENOMEM;
|
||||
|
||||
nodes[GPIO_KEYS].name = devm_kasprintf(dev, GFP_KERNEL, "%s-power-key", dev_name(dev));
|
||||
if (!nodes[GPIO_KEYS].name)
|
||||
return -ENOMEM;
|
||||
|
||||
parent_props = devm_kcalloc(dev, 2, sizeof(*parent_props), GFP_KERNEL);
|
||||
if (!parent_props)
|
||||
return -ENOMEM;
|
||||
|
||||
parent_props[0] = PROPERTY_ENTRY_STRING("label", name);
|
||||
nodes[GPIO_KEYS].properties = parent_props;
|
||||
|
||||
n_props = 2; /* linux,code and terminator */
|
||||
if (wakeup)
|
||||
n_props++;
|
||||
|
||||
child_props = devm_kcalloc(dev, n_props, sizeof(*child_props), GFP_KERNEL);
|
||||
if (!child_props)
|
||||
return -ENOMEM;
|
||||
|
||||
child_props[0] = PROPERTY_ENTRY_U32("linux,code", KEY_POWER);
|
||||
if (wakeup)
|
||||
child_props[1] = PROPERTY_ENTRY_BOOL("wakeup-source");
|
||||
|
||||
nodes[PWRON_KEY].parent = &nodes[GPIO_KEYS];
|
||||
nodes[PWRON_KEY].properties = child_props;
|
||||
|
||||
ret = rohm_pwrbutton_register_swnodes(nodes);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_add_action_or_reset(dev, rohm_pwrbutton_unregister_swnodes, nodes);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
gpio_keys_cell.swnode = &nodes[GPIO_KEYS];
|
||||
|
||||
ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, &gpio_keys_cell, 1,
|
||||
NULL, 0, irq_domain);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Failed to register power-button");
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rohm_register_pwrbutton);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Dmitry Torokhov <dmitry.torokhov@gmail.com>");
|
||||
MODULE_DESCRIPTION("Shared helper for ROHM PMIC power button registration");
|
||||
@@ -0,0 +1,12 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#ifndef __LINUX_MFD_ROHM_PWRBUTTON_H__
|
||||
#define __LINUX_MFD_ROHM_PWRBUTTON_H__
|
||||
|
||||
struct device;
|
||||
struct irq_domain;
|
||||
|
||||
int rohm_register_pwrbutton(struct device *dev, int irq, const char *name,
|
||||
bool wakeup, struct irq_domain *irq_domain);
|
||||
|
||||
#endif /* __LINUX_MFD_ROHM_PWRBUTTON_H__ */
|
||||
Reference in New Issue
Block a user