cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

max77650-regulator.c (12967B)


      1// SPDX-License-Identifier: GPL-2.0
      2//
      3// Copyright (C) 2018 BayLibre SAS
      4// Author: Bartosz Golaszewski <bgolaszewski@baylibre.com>
      5//
      6// Regulator driver for MAXIM 77650/77651 charger/power-supply.
      7
      8#include <linux/of.h>
      9#include <linux/mfd/max77650.h>
     10#include <linux/module.h>
     11#include <linux/platform_device.h>
     12#include <linux/regmap.h>
     13#include <linux/regulator/driver.h>
     14
     15#define MAX77650_REGULATOR_EN_CTRL_MASK		GENMASK(3, 0)
     16#define MAX77650_REGULATOR_EN_CTRL_BITS(_reg) \
     17		((_reg) & MAX77650_REGULATOR_EN_CTRL_MASK)
     18#define MAX77650_REGULATOR_ENABLED		GENMASK(2, 1)
     19#define MAX77650_REGULATOR_DISABLED		BIT(2)
     20
     21#define MAX77650_REGULATOR_V_LDO_MASK		GENMASK(6, 0)
     22#define MAX77650_REGULATOR_V_SBB_MASK		GENMASK(5, 0)
     23#define MAX77651_REGULATOR_V_SBB1_MASK		GENMASK(5, 2)
     24#define MAX77651_REGULATOR_V_SBB1_RANGE_MASK	GENMASK(1, 0)
     25
     26#define MAX77650_REGULATOR_AD_MASK		BIT(3)
     27#define MAX77650_REGULATOR_AD_DISABLED		0x00
     28#define MAX77650_REGULATOR_AD_ENABLED		BIT(3)
     29
     30#define MAX77650_REGULATOR_CURR_LIM_MASK	GENMASK(7, 6)
     31
     32enum {
     33	MAX77650_REGULATOR_ID_LDO = 0,
     34	MAX77650_REGULATOR_ID_SBB0,
     35	MAX77650_REGULATOR_ID_SBB1,
     36	MAX77650_REGULATOR_ID_SBB2,
     37	MAX77650_REGULATOR_NUM_REGULATORS,
     38};
     39
     40struct max77650_regulator_desc {
     41	struct regulator_desc desc;
     42	unsigned int regA;
     43	unsigned int regB;
     44};
     45
     46static struct max77650_regulator_desc max77651_SBB1_desc;
     47
     48static const unsigned int max77651_sbb1_volt_range_sel[] = {
     49	0x0, 0x1, 0x2, 0x3
     50};
     51
     52static const struct linear_range max77651_sbb1_volt_ranges[] = {
     53	/* range index 0 */
     54	REGULATOR_LINEAR_RANGE(2400000, 0x00, 0x0f, 50000),
     55	/* range index 1 */
     56	REGULATOR_LINEAR_RANGE(3200000, 0x00, 0x0f, 50000),
     57	/* range index 2 */
     58	REGULATOR_LINEAR_RANGE(4000000, 0x00, 0x0f, 50000),
     59	/* range index 3 */
     60	REGULATOR_LINEAR_RANGE(4800000, 0x00, 0x09, 50000),
     61};
     62
     63static const unsigned int max77650_current_limit_table[] = {
     64	1000000, 866000, 707000, 500000,
     65};
     66
     67static int max77650_regulator_is_enabled(struct regulator_dev *rdev)
     68{
     69	struct max77650_regulator_desc *rdesc;
     70	struct regmap *map;
     71	int val, rv, en;
     72
     73	rdesc = rdev_get_drvdata(rdev);
     74	map = rdev_get_regmap(rdev);
     75
     76	rv = regmap_read(map, rdesc->regB, &val);
     77	if (rv)
     78		return rv;
     79
     80	en = MAX77650_REGULATOR_EN_CTRL_BITS(val);
     81
     82	return en != MAX77650_REGULATOR_DISABLED;
     83}
     84
     85static int max77650_regulator_enable(struct regulator_dev *rdev)
     86{
     87	struct max77650_regulator_desc *rdesc;
     88	struct regmap *map;
     89
     90	rdesc = rdev_get_drvdata(rdev);
     91	map = rdev_get_regmap(rdev);
     92
     93	return regmap_update_bits(map, rdesc->regB,
     94				  MAX77650_REGULATOR_EN_CTRL_MASK,
     95				  MAX77650_REGULATOR_ENABLED);
     96}
     97
     98static int max77650_regulator_disable(struct regulator_dev *rdev)
     99{
    100	struct max77650_regulator_desc *rdesc;
    101	struct regmap *map;
    102
    103	rdesc = rdev_get_drvdata(rdev);
    104	map = rdev_get_regmap(rdev);
    105
    106	return regmap_update_bits(map, rdesc->regB,
    107				  MAX77650_REGULATOR_EN_CTRL_MASK,
    108				  MAX77650_REGULATOR_DISABLED);
    109}
    110
    111static const struct regulator_ops max77650_regulator_LDO_ops = {
    112	.is_enabled		= max77650_regulator_is_enabled,
    113	.enable			= max77650_regulator_enable,
    114	.disable		= max77650_regulator_disable,
    115	.list_voltage		= regulator_list_voltage_linear,
    116	.map_voltage		= regulator_map_voltage_linear,
    117	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
    118	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
    119	.set_active_discharge	= regulator_set_active_discharge_regmap,
    120};
    121
    122static const struct regulator_ops max77650_regulator_SBB_ops = {
    123	.is_enabled		= max77650_regulator_is_enabled,
    124	.enable			= max77650_regulator_enable,
    125	.disable		= max77650_regulator_disable,
    126	.list_voltage		= regulator_list_voltage_linear,
    127	.map_voltage		= regulator_map_voltage_linear,
    128	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
    129	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
    130	.get_current_limit	= regulator_get_current_limit_regmap,
    131	.set_current_limit	= regulator_set_current_limit_regmap,
    132	.set_active_discharge	= regulator_set_active_discharge_regmap,
    133};
    134
    135/* Special case for max77651 SBB1 - pickable linear-range voltage mapping. */
    136static const struct regulator_ops max77651_SBB1_regulator_ops = {
    137	.is_enabled		= max77650_regulator_is_enabled,
    138	.enable			= max77650_regulator_enable,
    139	.disable		= max77650_regulator_disable,
    140	.list_voltage		= regulator_list_voltage_pickable_linear_range,
    141	.get_voltage_sel	= regulator_get_voltage_sel_pickable_regmap,
    142	.set_voltage_sel	= regulator_set_voltage_sel_pickable_regmap,
    143	.get_current_limit	= regulator_get_current_limit_regmap,
    144	.set_current_limit	= regulator_set_current_limit_regmap,
    145	.set_active_discharge	= regulator_set_active_discharge_regmap,
    146};
    147
    148static struct max77650_regulator_desc max77650_LDO_desc = {
    149	.desc = {
    150		.name			= "ldo",
    151		.of_match		= of_match_ptr("ldo"),
    152		.regulators_node	= of_match_ptr("regulators"),
    153		.supply_name		= "in-ldo",
    154		.id			= MAX77650_REGULATOR_ID_LDO,
    155		.ops			= &max77650_regulator_LDO_ops,
    156		.min_uV			= 1350000,
    157		.uV_step		= 12500,
    158		.n_voltages		= 128,
    159		.vsel_step		= 1,
    160		.vsel_mask		= MAX77650_REGULATOR_V_LDO_MASK,
    161		.vsel_reg		= MAX77650_REG_CNFG_LDO_A,
    162		.active_discharge_off	= MAX77650_REGULATOR_AD_DISABLED,
    163		.active_discharge_on	= MAX77650_REGULATOR_AD_ENABLED,
    164		.active_discharge_mask	= MAX77650_REGULATOR_AD_MASK,
    165		.active_discharge_reg	= MAX77650_REG_CNFG_LDO_B,
    166		.enable_time		= 100,
    167		.type			= REGULATOR_VOLTAGE,
    168		.owner			= THIS_MODULE,
    169	},
    170	.regA		= MAX77650_REG_CNFG_LDO_A,
    171	.regB		= MAX77650_REG_CNFG_LDO_B,
    172};
    173
    174static struct max77650_regulator_desc max77650_SBB0_desc = {
    175	.desc = {
    176		.name			= "sbb0",
    177		.of_match		= of_match_ptr("sbb0"),
    178		.regulators_node	= of_match_ptr("regulators"),
    179		.supply_name		= "in-sbb0",
    180		.id			= MAX77650_REGULATOR_ID_SBB0,
    181		.ops			= &max77650_regulator_SBB_ops,
    182		.min_uV			= 800000,
    183		.uV_step		= 25000,
    184		.n_voltages		= 64,
    185		.vsel_step		= 1,
    186		.vsel_mask		= MAX77650_REGULATOR_V_SBB_MASK,
    187		.vsel_reg		= MAX77650_REG_CNFG_SBB0_A,
    188		.active_discharge_off	= MAX77650_REGULATOR_AD_DISABLED,
    189		.active_discharge_on	= MAX77650_REGULATOR_AD_ENABLED,
    190		.active_discharge_mask	= MAX77650_REGULATOR_AD_MASK,
    191		.active_discharge_reg	= MAX77650_REG_CNFG_SBB0_B,
    192		.enable_time		= 100,
    193		.type			= REGULATOR_VOLTAGE,
    194		.owner			= THIS_MODULE,
    195		.csel_reg		= MAX77650_REG_CNFG_SBB0_A,
    196		.csel_mask		= MAX77650_REGULATOR_CURR_LIM_MASK,
    197		.curr_table		= max77650_current_limit_table,
    198		.n_current_limits = ARRAY_SIZE(max77650_current_limit_table),
    199	},
    200	.regA		= MAX77650_REG_CNFG_SBB0_A,
    201	.regB		= MAX77650_REG_CNFG_SBB0_B,
    202};
    203
    204static struct max77650_regulator_desc max77650_SBB1_desc = {
    205	.desc = {
    206		.name			= "sbb1",
    207		.of_match		= of_match_ptr("sbb1"),
    208		.regulators_node	= of_match_ptr("regulators"),
    209		.supply_name		= "in-sbb1",
    210		.id			= MAX77650_REGULATOR_ID_SBB1,
    211		.ops			= &max77650_regulator_SBB_ops,
    212		.min_uV			= 800000,
    213		.uV_step		= 12500,
    214		.n_voltages		= 64,
    215		.vsel_step		= 1,
    216		.vsel_mask		= MAX77650_REGULATOR_V_SBB_MASK,
    217		.vsel_reg		= MAX77650_REG_CNFG_SBB1_A,
    218		.active_discharge_off	= MAX77650_REGULATOR_AD_DISABLED,
    219		.active_discharge_on	= MAX77650_REGULATOR_AD_ENABLED,
    220		.active_discharge_mask	= MAX77650_REGULATOR_AD_MASK,
    221		.active_discharge_reg	= MAX77650_REG_CNFG_SBB1_B,
    222		.enable_time		= 100,
    223		.type			= REGULATOR_VOLTAGE,
    224		.owner			= THIS_MODULE,
    225		.csel_reg		= MAX77650_REG_CNFG_SBB1_A,
    226		.csel_mask		= MAX77650_REGULATOR_CURR_LIM_MASK,
    227		.curr_table		= max77650_current_limit_table,
    228		.n_current_limits = ARRAY_SIZE(max77650_current_limit_table),
    229	},
    230	.regA		= MAX77650_REG_CNFG_SBB1_A,
    231	.regB		= MAX77650_REG_CNFG_SBB1_B,
    232};
    233
    234static struct max77650_regulator_desc max77651_SBB1_desc = {
    235	.desc = {
    236		.name			= "sbb1",
    237		.of_match		= of_match_ptr("sbb1"),
    238		.regulators_node	= of_match_ptr("regulators"),
    239		.supply_name		= "in-sbb1",
    240		.id			= MAX77650_REGULATOR_ID_SBB1,
    241		.ops			= &max77651_SBB1_regulator_ops,
    242		.linear_range_selectors	= max77651_sbb1_volt_range_sel,
    243		.linear_ranges		= max77651_sbb1_volt_ranges,
    244		.n_linear_ranges	= ARRAY_SIZE(max77651_sbb1_volt_ranges),
    245		.n_voltages		= 58,
    246		.vsel_step		= 1,
    247		.vsel_range_mask	= MAX77651_REGULATOR_V_SBB1_RANGE_MASK,
    248		.vsel_range_reg		= MAX77650_REG_CNFG_SBB1_A,
    249		.vsel_mask		= MAX77651_REGULATOR_V_SBB1_MASK,
    250		.vsel_reg		= MAX77650_REG_CNFG_SBB1_A,
    251		.active_discharge_off	= MAX77650_REGULATOR_AD_DISABLED,
    252		.active_discharge_on	= MAX77650_REGULATOR_AD_ENABLED,
    253		.active_discharge_mask	= MAX77650_REGULATOR_AD_MASK,
    254		.active_discharge_reg	= MAX77650_REG_CNFG_SBB1_B,
    255		.enable_time		= 100,
    256		.type			= REGULATOR_VOLTAGE,
    257		.owner			= THIS_MODULE,
    258		.csel_reg		= MAX77650_REG_CNFG_SBB1_A,
    259		.csel_mask		= MAX77650_REGULATOR_CURR_LIM_MASK,
    260		.curr_table		= max77650_current_limit_table,
    261		.n_current_limits = ARRAY_SIZE(max77650_current_limit_table),
    262	},
    263	.regA		= MAX77650_REG_CNFG_SBB1_A,
    264	.regB		= MAX77650_REG_CNFG_SBB1_B,
    265};
    266
    267static struct max77650_regulator_desc max77650_SBB2_desc = {
    268	.desc = {
    269		.name			= "sbb2",
    270		.of_match		= of_match_ptr("sbb2"),
    271		.regulators_node	= of_match_ptr("regulators"),
    272		.supply_name		= "in-sbb0",
    273		.id			= MAX77650_REGULATOR_ID_SBB2,
    274		.ops			= &max77650_regulator_SBB_ops,
    275		.min_uV			= 800000,
    276		.uV_step		= 50000,
    277		.n_voltages		= 64,
    278		.vsel_step		= 1,
    279		.vsel_mask		= MAX77650_REGULATOR_V_SBB_MASK,
    280		.vsel_reg		= MAX77650_REG_CNFG_SBB2_A,
    281		.active_discharge_off	= MAX77650_REGULATOR_AD_DISABLED,
    282		.active_discharge_on	= MAX77650_REGULATOR_AD_ENABLED,
    283		.active_discharge_mask	= MAX77650_REGULATOR_AD_MASK,
    284		.active_discharge_reg	= MAX77650_REG_CNFG_SBB2_B,
    285		.enable_time		= 100,
    286		.type			= REGULATOR_VOLTAGE,
    287		.owner			= THIS_MODULE,
    288		.csel_reg		= MAX77650_REG_CNFG_SBB2_A,
    289		.csel_mask		= MAX77650_REGULATOR_CURR_LIM_MASK,
    290		.curr_table		= max77650_current_limit_table,
    291		.n_current_limits = ARRAY_SIZE(max77650_current_limit_table),
    292	},
    293	.regA		= MAX77650_REG_CNFG_SBB2_A,
    294	.regB		= MAX77650_REG_CNFG_SBB2_B,
    295};
    296
    297static struct max77650_regulator_desc max77651_SBB2_desc = {
    298	.desc = {
    299		.name			= "sbb2",
    300		.of_match		= of_match_ptr("sbb2"),
    301		.regulators_node	= of_match_ptr("regulators"),
    302		.supply_name		= "in-sbb0",
    303		.id			= MAX77650_REGULATOR_ID_SBB2,
    304		.ops			= &max77650_regulator_SBB_ops,
    305		.min_uV			= 2400000,
    306		.uV_step		= 50000,
    307		.n_voltages		= 64,
    308		.vsel_step		= 1,
    309		.vsel_mask		= MAX77650_REGULATOR_V_SBB_MASK,
    310		.vsel_reg		= MAX77650_REG_CNFG_SBB2_A,
    311		.active_discharge_off	= MAX77650_REGULATOR_AD_DISABLED,
    312		.active_discharge_on	= MAX77650_REGULATOR_AD_ENABLED,
    313		.active_discharge_mask	= MAX77650_REGULATOR_AD_MASK,
    314		.active_discharge_reg	= MAX77650_REG_CNFG_SBB2_B,
    315		.enable_time		= 100,
    316		.type			= REGULATOR_VOLTAGE,
    317		.owner			= THIS_MODULE,
    318		.csel_reg		= MAX77650_REG_CNFG_SBB2_A,
    319		.csel_mask		= MAX77650_REGULATOR_CURR_LIM_MASK,
    320		.curr_table		= max77650_current_limit_table,
    321		.n_current_limits = ARRAY_SIZE(max77650_current_limit_table),
    322	},
    323	.regA		= MAX77650_REG_CNFG_SBB2_A,
    324	.regB		= MAX77650_REG_CNFG_SBB2_B,
    325};
    326
    327static int max77650_regulator_probe(struct platform_device *pdev)
    328{
    329	struct max77650_regulator_desc **rdescs;
    330	struct max77650_regulator_desc *rdesc;
    331	struct regulator_config config = { };
    332	struct device *dev, *parent;
    333	struct regulator_dev *rdev;
    334	struct regmap *map;
    335	unsigned int val;
    336	int i, rv;
    337
    338	dev = &pdev->dev;
    339	parent = dev->parent;
    340
    341	if (!dev->of_node)
    342		dev->of_node = parent->of_node;
    343
    344	rdescs = devm_kcalloc(dev, MAX77650_REGULATOR_NUM_REGULATORS,
    345			      sizeof(*rdescs), GFP_KERNEL);
    346	if (!rdescs)
    347		return -ENOMEM;
    348
    349	map = dev_get_regmap(parent, NULL);
    350	if (!map)
    351		return -ENODEV;
    352
    353	rv = regmap_read(map, MAX77650_REG_CID, &val);
    354	if (rv)
    355		return rv;
    356
    357	rdescs[MAX77650_REGULATOR_ID_LDO] = &max77650_LDO_desc;
    358	rdescs[MAX77650_REGULATOR_ID_SBB0] = &max77650_SBB0_desc;
    359
    360	switch (MAX77650_CID_BITS(val)) {
    361	case MAX77650_CID_77650A:
    362	case MAX77650_CID_77650C:
    363		rdescs[MAX77650_REGULATOR_ID_SBB1] = &max77650_SBB1_desc;
    364		rdescs[MAX77650_REGULATOR_ID_SBB2] = &max77650_SBB2_desc;
    365		break;
    366	case MAX77650_CID_77651A:
    367	case MAX77650_CID_77651B:
    368		rdescs[MAX77650_REGULATOR_ID_SBB1] = &max77651_SBB1_desc;
    369		rdescs[MAX77650_REGULATOR_ID_SBB2] = &max77651_SBB2_desc;
    370		break;
    371	default:
    372		return -ENODEV;
    373	}
    374
    375	config.dev = parent;
    376
    377	for (i = 0; i < MAX77650_REGULATOR_NUM_REGULATORS; i++) {
    378		rdesc = rdescs[i];
    379		config.driver_data = rdesc;
    380
    381		rdev = devm_regulator_register(dev, &rdesc->desc, &config);
    382		if (IS_ERR(rdev))
    383			return PTR_ERR(rdev);
    384	}
    385
    386	return 0;
    387}
    388
    389static const struct of_device_id max77650_regulator_of_match[] = {
    390	{ .compatible = "maxim,max77650-regulator" },
    391	{ }
    392};
    393MODULE_DEVICE_TABLE(of, max77650_regulator_of_match);
    394
    395static struct platform_driver max77650_regulator_driver = {
    396	.driver = {
    397		.name = "max77650-regulator",
    398		.of_match_table = max77650_regulator_of_match,
    399	},
    400	.probe = max77650_regulator_probe,
    401};
    402module_platform_driver(max77650_regulator_driver);
    403
    404MODULE_DESCRIPTION("MAXIM 77650/77651 regulator driver");
    405MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");
    406MODULE_LICENSE("GPL v2");
    407MODULE_ALIAS("platform:max77650-regulator");