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

sy8827n.c (5105B)


      1// SPDX-License-Identifier: GPL-2.0
      2//
      3// SY8827N regulator driver
      4//
      5// Copyright (C) 2020 Synaptics Incorporated
      6//
      7// Author: Jisheng Zhang <jszhang@kernel.org>
      8
      9#include <linux/gpio/consumer.h>
     10#include <linux/module.h>
     11#include <linux/i2c.h>
     12#include <linux/of_device.h>
     13#include <linux/regmap.h>
     14#include <linux/regulator/driver.h>
     15#include <linux/regulator/of_regulator.h>
     16
     17#define SY8827N_VSEL0		0
     18#define   SY8827N_BUCK_EN	(1 << 7)
     19#define   SY8827N_MODE		(1 << 6)
     20#define SY8827N_VSEL1		1
     21#define SY8827N_CTRL		2
     22#define SY8827N_ID1		3
     23#define SY8827N_ID2		4
     24#define SY8827N_PGOOD		5
     25#define SY8827N_MAX		(SY8827N_PGOOD + 1)
     26
     27#define SY8827N_NVOLTAGES	64
     28#define SY8827N_VSELMIN		600000
     29#define SY8827N_VSELSTEP	12500
     30
     31struct sy8827n_device_info {
     32	struct device *dev;
     33	struct regulator_desc desc;
     34	struct regulator_init_data *regulator;
     35	struct gpio_desc *en_gpio;
     36	unsigned int vsel_reg;
     37};
     38
     39static int sy8827n_set_mode(struct regulator_dev *rdev, unsigned int mode)
     40{
     41	struct sy8827n_device_info *di = rdev_get_drvdata(rdev);
     42
     43	switch (mode) {
     44	case REGULATOR_MODE_FAST:
     45		regmap_update_bits(rdev->regmap, di->vsel_reg,
     46				   SY8827N_MODE, SY8827N_MODE);
     47		break;
     48	case REGULATOR_MODE_NORMAL:
     49		regmap_update_bits(rdev->regmap, di->vsel_reg,
     50				   SY8827N_MODE, 0);
     51		break;
     52	default:
     53		return -EINVAL;
     54	}
     55	return 0;
     56}
     57
     58static unsigned int sy8827n_get_mode(struct regulator_dev *rdev)
     59{
     60	struct sy8827n_device_info *di = rdev_get_drvdata(rdev);
     61	u32 val;
     62	int ret = 0;
     63
     64	ret = regmap_read(rdev->regmap, di->vsel_reg, &val);
     65	if (ret < 0)
     66		return ret;
     67	if (val & SY8827N_MODE)
     68		return REGULATOR_MODE_FAST;
     69	else
     70		return REGULATOR_MODE_NORMAL;
     71}
     72
     73static const struct regulator_ops sy8827n_regulator_ops = {
     74	.set_voltage_sel = regulator_set_voltage_sel_regmap,
     75	.get_voltage_sel = regulator_get_voltage_sel_regmap,
     76	.set_voltage_time_sel = regulator_set_voltage_time_sel,
     77	.map_voltage = regulator_map_voltage_linear,
     78	.list_voltage = regulator_list_voltage_linear,
     79	.enable = regulator_enable_regmap,
     80	.disable = regulator_disable_regmap,
     81	.is_enabled = regulator_is_enabled_regmap,
     82	.set_mode = sy8827n_set_mode,
     83	.get_mode = sy8827n_get_mode,
     84};
     85
     86static int sy8827n_regulator_register(struct sy8827n_device_info *di,
     87			struct regulator_config *config)
     88{
     89	struct regulator_desc *rdesc = &di->desc;
     90	struct regulator_dev *rdev;
     91
     92	rdesc->name = "sy8827n-reg";
     93	rdesc->supply_name = "vin";
     94	rdesc->ops = &sy8827n_regulator_ops;
     95	rdesc->type = REGULATOR_VOLTAGE;
     96	rdesc->n_voltages = SY8827N_NVOLTAGES;
     97	rdesc->enable_reg = di->vsel_reg;
     98	rdesc->enable_mask = SY8827N_BUCK_EN;
     99	rdesc->min_uV = SY8827N_VSELMIN;
    100	rdesc->uV_step = SY8827N_VSELSTEP;
    101	rdesc->vsel_reg = di->vsel_reg;
    102	rdesc->vsel_mask = rdesc->n_voltages - 1;
    103	rdesc->owner = THIS_MODULE;
    104
    105	rdev = devm_regulator_register(di->dev, &di->desc, config);
    106	return PTR_ERR_OR_ZERO(rdev);
    107}
    108
    109static bool sy8827n_volatile_reg(struct device *dev, unsigned int reg)
    110{
    111	if (reg == SY8827N_PGOOD)
    112		return true;
    113	return false;
    114}
    115
    116static const struct regmap_config sy8827n_regmap_config = {
    117	.reg_bits = 8,
    118	.val_bits = 8,
    119	.volatile_reg = sy8827n_volatile_reg,
    120	.num_reg_defaults_raw = SY8827N_MAX,
    121	.cache_type = REGCACHE_FLAT,
    122};
    123
    124static int sy8827n_i2c_probe(struct i2c_client *client)
    125{
    126	struct device *dev = &client->dev;
    127	struct device_node *np = dev->of_node;
    128	struct sy8827n_device_info *di;
    129	struct regulator_config config = { };
    130	struct regmap *regmap;
    131	int ret;
    132
    133	di = devm_kzalloc(dev, sizeof(struct sy8827n_device_info), GFP_KERNEL);
    134	if (!di)
    135		return -ENOMEM;
    136
    137	di->regulator = of_get_regulator_init_data(dev, np, &di->desc);
    138	if (!di->regulator) {
    139		dev_err(dev, "Platform data not found!\n");
    140		return -EINVAL;
    141	}
    142
    143	di->en_gpio = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_HIGH);
    144	if (IS_ERR(di->en_gpio))
    145		return PTR_ERR(di->en_gpio);
    146
    147	if (of_property_read_bool(np, "silergy,vsel-state-high"))
    148		di->vsel_reg = SY8827N_VSEL1;
    149	else
    150		di->vsel_reg = SY8827N_VSEL0;
    151
    152	di->dev = dev;
    153
    154	regmap = devm_regmap_init_i2c(client, &sy8827n_regmap_config);
    155	if (IS_ERR(regmap)) {
    156		dev_err(dev, "Failed to allocate regmap!\n");
    157		return PTR_ERR(regmap);
    158	}
    159	i2c_set_clientdata(client, di);
    160
    161	config.dev = di->dev;
    162	config.init_data = di->regulator;
    163	config.regmap = regmap;
    164	config.driver_data = di;
    165	config.of_node = np;
    166
    167	ret = sy8827n_regulator_register(di, &config);
    168	if (ret < 0)
    169		dev_err(dev, "Failed to register regulator!\n");
    170	return ret;
    171}
    172
    173#ifdef CONFIG_OF
    174static const struct of_device_id sy8827n_dt_ids[] = {
    175	{
    176		.compatible = "silergy,sy8827n",
    177	},
    178	{ }
    179};
    180MODULE_DEVICE_TABLE(of, sy8827n_dt_ids);
    181#endif
    182
    183static const struct i2c_device_id sy8827n_id[] = {
    184	{ "sy8827n", },
    185	{ },
    186};
    187MODULE_DEVICE_TABLE(i2c, sy8827n_id);
    188
    189static struct i2c_driver sy8827n_regulator_driver = {
    190	.driver = {
    191		.name = "sy8827n-regulator",
    192		.of_match_table = of_match_ptr(sy8827n_dt_ids),
    193	},
    194	.probe_new = sy8827n_i2c_probe,
    195	.id_table = sy8827n_id,
    196};
    197module_i2c_driver(sy8827n_regulator_driver);
    198
    199MODULE_AUTHOR("Jisheng Zhang <jszhang@kernel.org>");
    200MODULE_DESCRIPTION("SY8827N regulator driver");
    201MODULE_LICENSE("GPL v2");