Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Unverified Commit 44bd79f5 authored by Mark Brown's avatar Mark Brown
Browse files

Merge branch 'topic/bd9571mwv' of...

Merge branch 'topic/bd9571mwv' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator into regulator-4.18
parents 1f5d6462 6eb0bfae
Loading
Loading
Loading
Loading
+21 −0
Original line number Original line Diff line number Diff line
@@ -25,6 +25,25 @@ Required properties:
			    Each child node is defined using the standard
			    Each child node is defined using the standard
			    binding for regulators.
			    binding for regulators.


Optional properties:
  - rohm,ddr-backup-power : Value to use for DDR-Backup Power (default 0).
			    This is a bitmask that specifies which DDR power
			    rails need to be kept powered when backup mode is
			    entered, for system suspend:
			      - bit 0: DDR0
			      - bit 1: DDR1
			      - bit 2: DDR0C
			      - bit 3: DDR1C
			    These bits match the KEEPON_DDR* bits in the
			    documentation for the "BKUP Mode Cnt" register.
  - rohm,rstbmode-level: The RSTB signal is configured for level mode, to
			 accommodate a toggle power switch (the RSTBMODE pin is
			 strapped low).
  - rohm,rstbmode-pulse: The RSTB signal is configured for pulse mode, to
			 accommodate a momentary power switch (the RSTBMODE pin
			 is strapped high).
			 The two properties above are mutually exclusive.

Example:
Example:


	pmic: pmic@30 {
	pmic: pmic@30 {
@@ -36,6 +55,8 @@ Example:
		#interrupt-cells = <2>;
		#interrupt-cells = <2>;
		gpio-controller;
		gpio-controller;
		#gpio-cells = <2>;
		#gpio-cells = <2>;
		rohm,ddr-backup-power = <0xf>;
		rohm,rstbmode-pulse;


		regulators {
		regulators {
			dvfs: dvfs {
			dvfs: dvfs {
+2 −0
Original line number Original line Diff line number Diff line
@@ -29,6 +29,7 @@ static const struct mfd_cell bd9571mwv_cells[] = {


static const struct regmap_range bd9571mwv_readable_yes_ranges[] = {
static const struct regmap_range bd9571mwv_readable_yes_ranges[] = {
	regmap_reg_range(BD9571MWV_VENDOR_CODE, BD9571MWV_PRODUCT_REVISION),
	regmap_reg_range(BD9571MWV_VENDOR_CODE, BD9571MWV_PRODUCT_REVISION),
	regmap_reg_range(BD9571MWV_BKUP_MODE_CNT, BD9571MWV_BKUP_MODE_CNT),
	regmap_reg_range(BD9571MWV_AVS_SET_MONI, BD9571MWV_AVS_DVFS_VID(3)),
	regmap_reg_range(BD9571MWV_AVS_SET_MONI, BD9571MWV_AVS_DVFS_VID(3)),
	regmap_reg_range(BD9571MWV_VD18_VID, BD9571MWV_VD33_VID),
	regmap_reg_range(BD9571MWV_VD18_VID, BD9571MWV_VD33_VID),
	regmap_reg_range(BD9571MWV_DVFS_VINIT, BD9571MWV_DVFS_VINIT),
	regmap_reg_range(BD9571MWV_DVFS_VINIT, BD9571MWV_DVFS_VINIT),
@@ -44,6 +45,7 @@ static const struct regmap_access_table bd9571mwv_readable_table = {
};
};


static const struct regmap_range bd9571mwv_writable_yes_ranges[] = {
static const struct regmap_range bd9571mwv_writable_yes_ranges[] = {
	regmap_reg_range(BD9571MWV_BKUP_MODE_CNT, BD9571MWV_BKUP_MODE_CNT),
	regmap_reg_range(BD9571MWV_AVS_VD09_VID(0), BD9571MWV_AVS_VD09_VID(3)),
	regmap_reg_range(BD9571MWV_AVS_VD09_VID(0), BD9571MWV_AVS_VD09_VID(3)),
	regmap_reg_range(BD9571MWV_DVFS_SETVID, BD9571MWV_DVFS_SETVID),
	regmap_reg_range(BD9571MWV_DVFS_SETVID, BD9571MWV_DVFS_SETVID),
	regmap_reg_range(BD9571MWV_GPIO_DIR, BD9571MWV_GPIO_OUT),
	regmap_reg_range(BD9571MWV_GPIO_DIR, BD9571MWV_GPIO_OUT),
+126 −1
Original line number Original line Diff line number Diff line
@@ -24,6 +24,18 @@


#include <linux/mfd/bd9571mwv.h>
#include <linux/mfd/bd9571mwv.h>


struct bd9571mwv_reg {
	struct bd9571mwv *bd;

	/* DDR Backup Power */
	u8 bkup_mode_cnt_keepon;	/* from "rohm,ddr-backup-power" */
	u8 bkup_mode_cnt_saved;

	/* Power switch type */
	bool rstbmode_level;
	bool rstbmode_pulse;
};

enum bd9571mwv_regulators { VD09, VD18, VD25, VD33, DVFS };
enum bd9571mwv_regulators { VD09, VD18, VD25, VD33, DVFS };


#define BD9571MWV_REG(_name, _of, _id, _ops, _vr, _vm, _nv, _min, _step, _lmin)\
#define BD9571MWV_REG(_name, _of, _id, _ops, _vr, _vm, _nv, _min, _step, _lmin)\
@@ -131,14 +143,99 @@ static struct regulator_desc regulators[] = {
		      0x80, 600000, 10000, 0x3c),
		      0x80, 600000, 10000, 0x3c),
};
};


#ifdef CONFIG_PM_SLEEP
static int bd9571mwv_bkup_mode_read(struct bd9571mwv *bd, unsigned int *mode)
{
	int ret;

	ret = regmap_read(bd->regmap, BD9571MWV_BKUP_MODE_CNT, mode);
	if (ret) {
		dev_err(bd->dev, "failed to read backup mode (%d)\n", ret);
		return ret;
	}

	return 0;
}

static int bd9571mwv_bkup_mode_write(struct bd9571mwv *bd, unsigned int mode)
{
	int ret;

	ret = regmap_write(bd->regmap, BD9571MWV_BKUP_MODE_CNT, mode);
	if (ret) {
		dev_err(bd->dev, "failed to configure backup mode 0x%x (%d)\n",
			mode, ret);
		return ret;
	}

	return 0;
}

static int bd9571mwv_suspend(struct device *dev)
{
	struct bd9571mwv_reg *bdreg = dev_get_drvdata(dev);
	unsigned int mode;
	int ret;

	if (!device_may_wakeup(dev))
		return 0;

	/* Save DDR Backup Mode */
	ret = bd9571mwv_bkup_mode_read(bdreg->bd, &mode);
	if (ret)
		return ret;

	bdreg->bkup_mode_cnt_saved = mode;

	if (!bdreg->rstbmode_pulse)
		return 0;

	/* Enable DDR Backup Mode */
	mode &= ~BD9571MWV_BKUP_MODE_CNT_KEEPON_MASK;
	mode |= bdreg->bkup_mode_cnt_keepon;

	if (mode != bdreg->bkup_mode_cnt_saved)
		return bd9571mwv_bkup_mode_write(bdreg->bd, mode);

	return 0;
}

static int bd9571mwv_resume(struct device *dev)
{
	struct bd9571mwv_reg *bdreg = dev_get_drvdata(dev);

	if (!device_may_wakeup(dev))
		return 0;

	/* Restore DDR Backup Mode */
	return bd9571mwv_bkup_mode_write(bdreg->bd, bdreg->bkup_mode_cnt_saved);
}

static const struct dev_pm_ops bd9571mwv_pm  = {
	SET_SYSTEM_SLEEP_PM_OPS(bd9571mwv_suspend, bd9571mwv_resume)
};

#define DEV_PM_OPS	&bd9571mwv_pm
#else
#define DEV_PM_OPS	NULL
#endif /* CONFIG_PM_SLEEP */

static int bd9571mwv_regulator_probe(struct platform_device *pdev)
static int bd9571mwv_regulator_probe(struct platform_device *pdev)
{
{
	struct bd9571mwv *bd = dev_get_drvdata(pdev->dev.parent);
	struct bd9571mwv *bd = dev_get_drvdata(pdev->dev.parent);
	struct regulator_config config = { };
	struct regulator_config config = { };
	struct bd9571mwv_reg *bdreg;
	struct regulator_dev *rdev;
	struct regulator_dev *rdev;
	unsigned int val;
	int i;
	int i;


	platform_set_drvdata(pdev, bd);
	bdreg = devm_kzalloc(&pdev->dev, sizeof(*bdreg), GFP_KERNEL);
	if (!bdreg)
		return -ENOMEM;

	bdreg->bd = bd;

	platform_set_drvdata(pdev, bdreg);


	config.dev = &pdev->dev;
	config.dev = &pdev->dev;
	config.dev->of_node = bd->dev->of_node;
	config.dev->of_node = bd->dev->of_node;
@@ -155,6 +252,33 @@ static int bd9571mwv_regulator_probe(struct platform_device *pdev)
		}
		}
	}
	}


	val = 0;
	of_property_read_u32(bd->dev->of_node, "rohm,ddr-backup-power", &val);
	if (val & ~BD9571MWV_BKUP_MODE_CNT_KEEPON_MASK) {
		dev_err(bd->dev, "invalid %s mode %u\n",
			"rohm,ddr-backup-power", val);
		return -EINVAL;
	}
	bdreg->bkup_mode_cnt_keepon = val;

	bdreg->rstbmode_level = of_property_read_bool(bd->dev->of_node,
						      "rohm,rstbmode-level");
	bdreg->rstbmode_pulse = of_property_read_bool(bd->dev->of_node,
						      "rohm,rstbmode-pulse");
	if (bdreg->rstbmode_level && bdreg->rstbmode_pulse) {
		dev_err(bd->dev, "only one rohm,rstbmode-* may be specified");
		return -EINVAL;
	}

	if (bdreg->bkup_mode_cnt_keepon) {
		device_set_wakeup_capable(&pdev->dev, true);
		/*
		 * Wakeup is enabled by default in pulse mode, but needs
		 * explicit user setup in level mode.
		 */
		device_set_wakeup_enable(&pdev->dev, bdreg->rstbmode_pulse);
	}

	return 0;
	return 0;
}
}


@@ -167,6 +291,7 @@ MODULE_DEVICE_TABLE(platform, bd9571mwv_regulator_id_table);
static struct platform_driver bd9571mwv_regulator_driver = {
static struct platform_driver bd9571mwv_regulator_driver = {
	.driver = {
	.driver = {
		.name = "bd9571mwv-regulator",
		.name = "bd9571mwv-regulator",
		.pm = DEV_PM_OPS,
	},
	},
	.probe = bd9571mwv_regulator_probe,
	.probe = bd9571mwv_regulator_probe,
	.id_table = bd9571mwv_regulator_id_table,
	.id_table = bd9571mwv_regulator_id_table,
+5 −0
Original line number Original line Diff line number Diff line
@@ -33,6 +33,11 @@
#define BD9571MWV_I2C_MD2_E1_BIT_2		0x12
#define BD9571MWV_I2C_MD2_E1_BIT_2		0x12


#define BD9571MWV_BKUP_MODE_CNT			0x20
#define BD9571MWV_BKUP_MODE_CNT			0x20
#define BD9571MWV_BKUP_MODE_CNT_KEEPON_MASK	GENMASK(3, 0)
#define BD9571MWV_BKUP_MODE_CNT_KEEPON_DDR0	BIT(0)
#define BD9571MWV_BKUP_MODE_CNT_KEEPON_DDR1	BIT(1)
#define BD9571MWV_BKUP_MODE_CNT_KEEPON_DDR0C	BIT(2)
#define BD9571MWV_BKUP_MODE_CNT_KEEPON_DDR1C	BIT(3)
#define BD9571MWV_BKUP_MODE_STATUS		0x21
#define BD9571MWV_BKUP_MODE_STATUS		0x21
#define BD9571MWV_BKUP_RECOVERY_CNT		0x22
#define BD9571MWV_BKUP_RECOVERY_CNT		0x22
#define BD9571MWV_BKUP_CTRL_TIM_CNT		0x23
#define BD9571MWV_BKUP_CTRL_TIM_CNT		0x23