Unverified Commit 54515214 authored by Mark Brown's avatar Mark Brown
Browse files

Merge tag 'bd71847-support' into regulator-4.20

regulator/mfd: Support for the ROHM BD71847

This adds support for the BD71847 which touches both MFD and regulator.
There's a few other bits and pieces included as some dependency patches
had already been applied so would've required rebasing.
parents 5a7d7d0f 2ece646c
Loading
Loading
Loading
Loading
+9 −8
Original line number Diff line number Diff line
* ROHM BD71837 Power Management Integrated Circuit bindings
* ROHM BD71837 and BD71847 Power Management Integrated Circuit bindings

BD71837MWV is a programmable Power Management IC for powering single-core,
dual-core, and quad-core SoCs such as NXP-i.MX 8M. It is optimized for
low BOM cost and compact solution footprint. It integrates 8 Buck
egulators and 7 LDOs to provide all the power rails required by the SoC and
the commonly used peripherals.
BD71837MWV and BD71847MWV are programmable Power Management ICs for powering
single-core, dual-core, and quad-core SoCs such as NXP-i.MX 8M. They are
optimized for low BOM cost and compact solution footprint. BD71837MWV
integrates 8 Buck regulators and 7 LDOs. BD71847MWV contains 6 Buck regulators
and 6 LDOs.

Datasheet for PMIC is available at:
Datasheet for BD71837 is available at:
https://www.rohm.com/datasheet/BD71837MWV/bd71837mwv-e

Required properties:
 - compatible		: Should be "rohm,bd71837".
 - compatible		: Should be "rohm,bd71837" for bd71837
				    "rohm,bd71847" for bd71847.
 - reg			: I2C slave address.
 - interrupt-parent	: Phandle to the parent interrupt controller.
 - interrupts		: The interrupt line the device is connected to.
+9 −3
Original line number Diff line number Diff line
ROHM BD71837 Power Management Integrated Circuit (PMIC) regulator bindings
ROHM BD71837 and BD71847 Power Management Integrated Circuit regulator bindings

Required properties:
 - regulator-name: should be "buck1", ..., "buck8" and "ldo1", ..., "ldo7"
 - regulator-name: should be "buck1", ..., "buck8" and "ldo1", ..., "ldo7" for
                   BD71837. For BD71847 names should be "buck1", ..., "buck6"
		   and "ldo1", ..., "ldo6"

List of regulators provided by this controller. BD71837 regulators node
should be sub node of the BD71837 MFD node. See BD71837 MFD bindings at
@@ -16,10 +18,14 @@ disabled by driver at startup. LDO5 and LDO6 are supplied by those and
if they are disabled at startup the voltage monitoring for LDO5/LDO6 will
cause PMIC to reset.

The valid names for regulator nodes are:
The valid names for BD71837 regulator nodes are:
BUCK1, BUCK2, BUCK3, BUCK4, BUCK5, BUCK6, BUCK7, BUCK8
LDO1, LDO2, LDO3, LDO4, LDO5, LDO6, LDO7

The valid names for BD71847 regulator nodes are:
BUCK1, BUCK2, BUCK3, BUCK4, BUCK5, BUCK6
LDO1, LDO2, LDO3, LDO4, LDO5, LDO6

Optional properties:
- Any optional property defined in bindings/regulator/regulator.txt

+75 −87
Original line number Diff line number Diff line
@@ -2,26 +2,21 @@
//
// Copyright (C) 2018 ROHM Semiconductors
//
// ROHM BD71837MWV PMIC driver
// ROHM BD71837MWV and BD71847MWV PMIC driver
//
// Datasheet available from
// Datasheet for BD71837MWV available from
// https://www.rohm.com/datasheet/BD71837MWV/bd71837mwv-e

#include <linux/gpio_keys.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/mfd/rohm-bd718x7.h>
#include <linux/mfd/core.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/regmap.h>

/*
 * gpio_keys.h requires definiton of bool. It is brought in
 * by above includes. Keep this as last until gpio_keys.h gets fixed.
 */
#include <linux/gpio_keys.h>

static const u8 supported_revisions[] = { 0xA2 /* BD71837 */ };
#include <linux/types.h>

static struct gpio_keys_button button = {
	.code = KEY_POWER,
@@ -35,42 +30,42 @@ static struct gpio_keys_platform_data bd718xx_powerkey_data = {
	.name = "bd718xx-pwrkey",
};

static struct mfd_cell bd71837_mfd_cells[] = {
static struct mfd_cell bd718xx_mfd_cells[] = {
	{
		.name = "gpio-keys",
		.platform_data = &bd718xx_powerkey_data,
		.pdata_size = sizeof(bd718xx_powerkey_data),
	},
	{ .name = "bd71837-clk", },
	{ .name = "bd71837-pmic", },
	{ .name = "bd718xx-clk", },
	{ .name = "bd718xx-pmic", },
};

static const struct regmap_irq bd71837_irqs[] = {
	REGMAP_IRQ_REG(BD71837_INT_SWRST, 0, BD71837_INT_SWRST_MASK),
	REGMAP_IRQ_REG(BD71837_INT_PWRBTN_S, 0, BD71837_INT_PWRBTN_S_MASK),
	REGMAP_IRQ_REG(BD71837_INT_PWRBTN_L, 0, BD71837_INT_PWRBTN_L_MASK),
	REGMAP_IRQ_REG(BD71837_INT_PWRBTN, 0, BD71837_INT_PWRBTN_MASK),
	REGMAP_IRQ_REG(BD71837_INT_WDOG, 0, BD71837_INT_WDOG_MASK),
	REGMAP_IRQ_REG(BD71837_INT_ON_REQ, 0, BD71837_INT_ON_REQ_MASK),
	REGMAP_IRQ_REG(BD71837_INT_STBY_REQ, 0, BD71837_INT_STBY_REQ_MASK),
static const struct regmap_irq bd718xx_irqs[] = {
	REGMAP_IRQ_REG(BD718XX_INT_SWRST, 0, BD718XX_INT_SWRST_MASK),
	REGMAP_IRQ_REG(BD718XX_INT_PWRBTN_S, 0, BD718XX_INT_PWRBTN_S_MASK),
	REGMAP_IRQ_REG(BD718XX_INT_PWRBTN_L, 0, BD718XX_INT_PWRBTN_L_MASK),
	REGMAP_IRQ_REG(BD718XX_INT_PWRBTN, 0, BD718XX_INT_PWRBTN_MASK),
	REGMAP_IRQ_REG(BD718XX_INT_WDOG, 0, BD718XX_INT_WDOG_MASK),
	REGMAP_IRQ_REG(BD718XX_INT_ON_REQ, 0, BD718XX_INT_ON_REQ_MASK),
	REGMAP_IRQ_REG(BD718XX_INT_STBY_REQ, 0, BD718XX_INT_STBY_REQ_MASK),
};

static struct regmap_irq_chip bd71837_irq_chip = {
	.name = "bd71837-irq",
	.irqs = bd71837_irqs,
	.num_irqs = ARRAY_SIZE(bd71837_irqs),
static struct regmap_irq_chip bd718xx_irq_chip = {
	.name = "bd718xx-irq",
	.irqs = bd718xx_irqs,
	.num_irqs = ARRAY_SIZE(bd718xx_irqs),
	.num_regs = 1,
	.irq_reg_stride = 1,
	.status_base = BD71837_REG_IRQ,
	.mask_base = BD71837_REG_MIRQ,
	.ack_base = BD71837_REG_IRQ,
	.status_base = BD718XX_REG_IRQ,
	.mask_base = BD718XX_REG_MIRQ,
	.ack_base = BD718XX_REG_IRQ,
	.init_ack_masked = true,
	.mask_invert = false,
};

static const struct regmap_range pmic_status_range = {
	.range_min = BD71837_REG_IRQ,
	.range_max = BD71837_REG_POW_STATE,
	.range_min = BD718XX_REG_IRQ,
	.range_max = BD718XX_REG_POW_STATE,
};

static const struct regmap_access_table volatile_regs = {
@@ -78,67 +73,53 @@ static const struct regmap_access_table volatile_regs = {
	.n_yes_ranges = 1,
};

static const struct regmap_config bd71837_regmap_config = {
static const struct regmap_config bd718xx_regmap_config = {
	.reg_bits = 8,
	.val_bits = 8,
	.volatile_table = &volatile_regs,
	.max_register = BD71837_MAX_REGISTER - 1,
	.max_register = BD718XX_MAX_REGISTER - 1,
	.cache_type = REGCACHE_RBTREE,
};

static int bd71837_i2c_probe(struct i2c_client *i2c,
static int bd718xx_i2c_probe(struct i2c_client *i2c,
			    const struct i2c_device_id *id)
{
	struct bd71837 *bd71837;
	int ret, i;
	unsigned int val;

	bd71837 = devm_kzalloc(&i2c->dev, sizeof(struct bd71837), GFP_KERNEL);
	struct bd718xx *bd718xx;
	int ret;

	if (!bd71837)
		return -ENOMEM;

	bd71837->chip_irq = i2c->irq;

	if (!bd71837->chip_irq) {
	if (!i2c->irq) {
		dev_err(&i2c->dev, "No IRQ configured\n");
		return -EINVAL;
	}

	bd71837->dev = &i2c->dev;
	dev_set_drvdata(&i2c->dev, bd71837);
	bd718xx = devm_kzalloc(&i2c->dev, sizeof(struct bd718xx), GFP_KERNEL);

	bd71837->regmap = devm_regmap_init_i2c(i2c, &bd71837_regmap_config);
	if (IS_ERR(bd71837->regmap)) {
		dev_err(&i2c->dev, "regmap initialization failed\n");
		return PTR_ERR(bd71837->regmap);
	}
	if (!bd718xx)
		return -ENOMEM;

	ret = regmap_read(bd71837->regmap, BD71837_REG_REV, &val);
	if (ret) {
		dev_err(&i2c->dev, "Read BD71837_REG_DEVICE failed\n");
		return ret;
	}
	for (i = 0; i < ARRAY_SIZE(supported_revisions); i++)
		if (supported_revisions[i] == val)
			break;
	bd718xx->chip_irq = i2c->irq;
	bd718xx->chip_type = (unsigned int)
				of_device_get_match_data(&i2c->dev);
	bd718xx->dev = &i2c->dev;
	dev_set_drvdata(&i2c->dev, bd718xx);

	if (i == ARRAY_SIZE(supported_revisions)) {
		dev_err(&i2c->dev, "Unsupported chip revision\n");
		return -ENODEV;
	bd718xx->regmap = devm_regmap_init_i2c(i2c, &bd718xx_regmap_config);
	if (IS_ERR(bd718xx->regmap)) {
		dev_err(&i2c->dev, "regmap initialization failed\n");
		return PTR_ERR(bd718xx->regmap);
	}

	ret = devm_regmap_add_irq_chip(&i2c->dev, bd71837->regmap,
				       bd71837->chip_irq, IRQF_ONESHOT, 0,
				       &bd71837_irq_chip, &bd71837->irq_data);
	ret = devm_regmap_add_irq_chip(&i2c->dev, bd718xx->regmap,
				       bd718xx->chip_irq, IRQF_ONESHOT, 0,
				       &bd718xx_irq_chip, &bd718xx->irq_data);
	if (ret) {
		dev_err(&i2c->dev, "Failed to add irq_chip\n");
		return ret;
	}

	/* Configure short press to 10 milliseconds */
	ret = regmap_update_bits(bd71837->regmap,
				 BD71837_REG_PWRONCONFIG0,
	ret = regmap_update_bits(bd718xx->regmap,
				 BD718XX_REG_PWRONCONFIG0,
				 BD718XX_PWRBTN_PRESS_DURATION_MASK,
				 BD718XX_PWRBTN_SHORT_PRESS_10MS);
	if (ret) {
@@ -148,8 +129,8 @@ static int bd71837_i2c_probe(struct i2c_client *i2c,
	}

	/* Configure long press to 10 seconds */
	ret = regmap_update_bits(bd71837->regmap,
				 BD71837_REG_PWRONCONFIG1,
	ret = regmap_update_bits(bd718xx->regmap,
				 BD718XX_REG_PWRONCONFIG1,
				 BD718XX_PWRBTN_PRESS_DURATION_MASK,
				 BD718XX_PWRBTN_LONG_PRESS_10S);

@@ -159,7 +140,7 @@ static int bd71837_i2c_probe(struct i2c_client *i2c,
		return ret;
	}

	ret = regmap_irq_get_virq(bd71837->irq_data, BD71837_INT_PWRBTN_S);
	ret = regmap_irq_get_virq(bd718xx->irq_data, BD718XX_INT_PWRBTN_S);

	if (ret < 0) {
		dev_err(&i2c->dev, "Failed to get the IRQ\n");
@@ -168,44 +149,51 @@ static int bd71837_i2c_probe(struct i2c_client *i2c,

	button.irq = ret;

	ret = devm_mfd_add_devices(bd71837->dev, PLATFORM_DEVID_AUTO,
				   bd71837_mfd_cells,
				   ARRAY_SIZE(bd71837_mfd_cells), NULL, 0,
				   regmap_irq_get_domain(bd71837->irq_data));
	ret = devm_mfd_add_devices(bd718xx->dev, PLATFORM_DEVID_AUTO,
				   bd718xx_mfd_cells,
				   ARRAY_SIZE(bd718xx_mfd_cells), NULL, 0,
				   regmap_irq_get_domain(bd718xx->irq_data));
	if (ret)
		dev_err(&i2c->dev, "Failed to create subdevices\n");

	return ret;
}

static const struct of_device_id bd71837_of_match[] = {
	{ .compatible = "rohm,bd71837", },
static const struct of_device_id bd718xx_of_match[] = {
	{
		.compatible = "rohm,bd71837",
		.data = (void *)BD718XX_TYPE_BD71837,
	},
	{
		.compatible = "rohm,bd71847",
		.data = (void *)BD718XX_TYPE_BD71847,
	},
	{ }
};
MODULE_DEVICE_TABLE(of, bd71837_of_match);
MODULE_DEVICE_TABLE(of, bd718xx_of_match);

static struct i2c_driver bd71837_i2c_driver = {
static struct i2c_driver bd718xx_i2c_driver = {
	.driver = {
		.name = "rohm-bd718x7",
		.of_match_table = bd71837_of_match,
		.of_match_table = bd718xx_of_match,
	},
	.probe = bd71837_i2c_probe,
	.probe = bd718xx_i2c_probe,
};

static int __init bd71837_i2c_init(void)
static int __init bd718xx_i2c_init(void)
{
	return i2c_add_driver(&bd71837_i2c_driver);
	return i2c_add_driver(&bd718xx_i2c_driver);
}

/* Initialise early so consumer devices can complete system boot */
subsys_initcall(bd71837_i2c_init);
subsys_initcall(bd718xx_i2c_init);

static void __exit bd71837_i2c_exit(void)
static void __exit bd718xx_i2c_exit(void)
{
	i2c_del_driver(&bd71837_i2c_driver);
	i2c_del_driver(&bd718xx_i2c_driver);
}
module_exit(bd71837_i2c_exit);
module_exit(bd718xx_i2c_exit);

MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
MODULE_DESCRIPTION("ROHM BD71837 Power Management IC driver");
MODULE_DESCRIPTION("ROHM BD71837/BD71847 Power Management IC driver");
MODULE_LICENSE("GPL");
+1 −1
Original line number Diff line number Diff line
@@ -189,7 +189,7 @@ config REGULATOR_BD718XX
	  and LDO regulators.

	  This driver can also be built as a module. If so, the module
	  will be called bd71837-regulator.
	  will be called bd718x7-regulator.

config REGULATOR_BD9571MWV
	tristate "ROHM BD9571MWV Regulators"
+1 −1
Original line number Diff line number Diff line
@@ -27,7 +27,7 @@ obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o
obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o
obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o
obj-$(CONFIG_REGULATOR_BCM590XX) += bcm590xx-regulator.o
obj-$(CONFIG_REGULATOR_BD718XX) += bd71837-regulator.o
obj-$(CONFIG_REGULATOR_BD718XX) += bd718x7-regulator.o
obj-$(CONFIG_REGULATOR_BD9571MWV) += bd9571mwv-regulator.o
obj-$(CONFIG_REGULATOR_DA903X)	+= da903x.o
obj-$(CONFIG_REGULATOR_DA9052)	+= da9052-regulator.o
Loading