// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2024 ROHM Semiconductors
// bd96801-regulator.c ROHM BD96801 regulator driver
/*
* This version of the "BD86801 scalable PMIC"'s driver supports only very
* basic set of the PMIC features. Most notably, there is no support for
* the configurations which should be done when the PMIC is in STBY mode.
*
* Being able to reliably do the configurations like changing the
* regulator safety limits (like limits for the over/under -voltages, over
* current, thermal protection) would require the configuring driver to be
* synchronized with entity causing the PMIC state transitions. Eg, one
* should be able to ensure the PMIC is in STBY state when the
* configurations are applied to the hardware. How and when the PMIC state
* transitions are to be done is likely to be very system specific, as will
* be the need to configure these safety limits. Hence it's not simple to
* come up with a generic solution.
*
* Users who require the STBY state configurations can have a look at the
* original RFC:
* https://lore.kernel.org/all/cover.1712920132.git.mazziesaccount@gmail.com/
* which implements some of the safety limit configurations - but leaves the
* state change handling and synchronization to be implemented.
*
* It would be great to hear (and receive a patch!) if you implement the
* STBY configuration support in your downstream driver ;)
*/
#include <linux/cleanup.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/linear_range.h>
#include <linux/mfd/rohm-generic.h>
#include <linux/mfd/rohm-bd96801.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/regulator/coupler.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/of_regulator.h>
#include <linux/slab.h>
#include <linux/timer.h>
enum {
BD96801_BUCK1,
BD96801_BUCK2,
BD96801_BUCK3,
BD96801_BUCK4,
BD96801_LDO5,
BD96801_LDO6,
BD96801_LDO7,
BD96801_REGULATOR_AMOUNT,
};
enum {
BD96801_PROT_OVP,
BD96801_PROT_UVP,
BD96801_PROT_OCP,
BD96801_PROT_TEMP,
BD96801_NUM_PROT,
};
#define BD96801_ALWAYS_ON_REG 0x3c
#define BD96801_REG_ENABLE 0x0b
#define BD96801_BUCK1_EN_MASK BIT(0)
#define BD96801_BUCK2_EN_MASK BIT(1)
#define BD96801_BUCK3_EN_MASK BIT(2)
#define BD96801_BUCK4_EN_MASK BIT(3)
#define BD96801_LDO5_EN_MASK BIT(4)
#define BD96801_LDO6_EN_MASK BIT(5)
#define BD96801_LDO7_EN_MASK BIT(6)
#define BD96801_BUCK1_VSEL_REG 0x28
#define BD96801_BUCK2_VSEL_REG 0x29
#define BD96801_BUCK3_VSEL_REG 0x2a
#define BD96801_BUCK4_VSEL_REG 0x2b
#define BD96801_LDO5_VSEL_REG 0x25
#define BD96801_LDO6_VSEL_REG 0x26
#define BD96801_LDO7_VSEL_REG 0x27
#define BD96801_BUCK_VSEL_MASK 0x1F
#define BD96805_BUCK_VSEL_MASK 0x3f
#define BD96801_LDO_VSEL_MASK 0xff
#define BD96801_MASK_RAMP_DELAY 0xc0
#define BD96801_INT_VOUT_BASE_REG 0x21
#define BD96801_BUCK_INT_VOUT_MASK 0xff
#define BD96801_BUCK_VOLTS 256
#define BD96805_BUCK_VOLTS 64
#define BD96801_LDO_VOLTS 256
#define BD96801_OVP_MASK 0x03
#define BD96801_MASK_BUCK1_OVP_SHIFT 0x00
#define BD96801_MASK_BUCK2_OVP_SHIFT 0x02
#define BD96801_MASK_BUCK3_OVP_SHIFT 0x04
#define BD96801_MASK_BUCK4_OVP_SHIFT 0x06
#define BD96801_MASK_LDO5_OVP_SHIFT 0x00
#define BD96801_MASK_LDO6_OVP_SHIFT 0x02
#define BD96801_MASK_LDO7_OVP_SHIFT 0x04
#define BD96801_PROT_LIMIT_OCP_MIN 0x00
#define BD96801_PROT_LIMIT_LOW 0x01
#define BD96801_PROT_LIMIT_MID 0x02
#define BD96801_PROT_LIMIT_HI 0x03
#define BD96801_REG_BUCK1_OCP 0x32
#define BD96801_REG_BUCK2_OCP 0x32
#define BD96801_REG_BUCK3_OCP 0x33
#define BD96801_REG_BUCK4_OCP 0x33
#define BD96801_MASK_BUCK1_OCP_SHIFT 0x00
#define BD96801_MASK_BUCK2_OCP_SHIFT 0x04
#define BD96801_MASK_BUCK3_OCP_SHIFT 0x00
#define BD96801_MASK_BUCK4_OCP_SHIFT 0x04
#define BD96801_REG_LDO5_OCP 0x34
#define BD96801_REG_LDO6_OCP 0x34
#define BD96801_REG_LDO7_OCP 0x34
#define BD96801_MASK_LDO5_OCP_SHIFT 0x00
#define BD96801_MASK_LDO6_OCP_SHIFT 0x02
#define BD96801_MASK_LDO7_OCP_SHIFT 0x04
#define BD96801_MASK_SHD_INTB BIT(7)
#define BD96801_INTB_FATAL BIT(7)
#define BD96801_NUM_REGULATORS 7
#define BD96801_NUM_LDOS 4
/*
* Ramp rates for bucks are controlled by bits [7:6] as follows:
* 00 => 1 mV/uS
* 01 => 5 mV/uS
* 10 => 10 mV/uS
* 11 => 20 mV/uS
*/
static const unsigned int<