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

sy8824x.c (5930B)


      1// SPDX-License-Identifier: GPL-2.0
      2//
      3// SY8824C/SY8824E regulator driver
      4//
      5// Copyright (C) 2019 Synaptics Incorporated
      6//
      7// Author: Jisheng Zhang <jszhang@kernel.org>
      8
      9#include <linux/module.h>
     10#include <linux/i2c.h>
     11#include <linux/of_device.h>
     12#include <linux/regmap.h>
     13#include <linux/regulator/driver.h>
     14#include <linux/regulator/of_regulator.h>
     15
     16#define SY8824C_BUCK_EN		(1 << 7)
     17#define SY8824C_MODE		(1 << 6)
     18
     19struct sy8824_config {
     20	/* registers */
     21	unsigned int vol_reg;
     22	unsigned int mode_reg;
     23	unsigned int enable_reg;
     24	/* Voltage range and step(linear) */
     25	unsigned int vsel_min;
     26	unsigned int vsel_step;
     27	unsigned int vsel_count;
     28	const struct regmap_config *config;
     29};
     30
     31struct sy8824_device_info {
     32	struct device *dev;
     33	struct regulator_desc desc;
     34	struct regulator_init_data *regulator;
     35	const struct sy8824_config *cfg;
     36};
     37
     38static int sy8824_set_mode(struct regulator_dev *rdev, unsigned int mode)
     39{
     40	struct sy8824_device_info *di = rdev_get_drvdata(rdev);
     41	const struct sy8824_config *cfg = di->cfg;
     42
     43	switch (mode) {
     44	case REGULATOR_MODE_FAST:
     45		regmap_update_bits(rdev->regmap, cfg->mode_reg,
     46				   SY8824C_MODE, SY8824C_MODE);
     47		break;
     48	case REGULATOR_MODE_NORMAL:
     49		regmap_update_bits(rdev->regmap, cfg->mode_reg,
     50				   SY8824C_MODE, 0);
     51		break;
     52	default:
     53		return -EINVAL;
     54	}
     55	return 0;
     56}
     57
     58static unsigned int sy8824_get_mode(struct regulator_dev *rdev)
     59{
     60	struct sy8824_device_info *di = rdev_get_drvdata(rdev);
     61	const struct sy8824_config *cfg = di->cfg;
     62	u32 val;
     63	int ret = 0;
     64
     65	ret = regmap_read(rdev->regmap, cfg->mode_reg, &val);
     66	if (ret < 0)
     67		return ret;
     68	if (val & SY8824C_MODE)
     69		return REGULATOR_MODE_FAST;
     70	else
     71		return REGULATOR_MODE_NORMAL;
     72}
     73
     74static const struct regulator_ops sy8824_regulator_ops = {
     75	.set_voltage_sel = regulator_set_voltage_sel_regmap,
     76	.get_voltage_sel = regulator_get_voltage_sel_regmap,
     77	.set_voltage_time_sel = regulator_set_voltage_time_sel,
     78	.map_voltage = regulator_map_voltage_linear,
     79	.list_voltage = regulator_list_voltage_linear,
     80	.enable = regulator_enable_regmap,
     81	.disable = regulator_disable_regmap,
     82	.is_enabled = regulator_is_enabled_regmap,
     83	.set_mode = sy8824_set_mode,
     84	.get_mode = sy8824_get_mode,
     85};
     86
     87static int sy8824_regulator_register(struct sy8824_device_info *di,
     88			struct regulator_config *config)
     89{
     90	struct regulator_desc *rdesc = &di->desc;
     91	const struct sy8824_config *cfg = di->cfg;
     92	struct regulator_dev *rdev;
     93
     94	rdesc->name = "sy8824-reg";
     95	rdesc->supply_name = "vin";
     96	rdesc->ops = &sy8824_regulator_ops;
     97	rdesc->type = REGULATOR_VOLTAGE;
     98	rdesc->n_voltages = cfg->vsel_count;
     99	rdesc->enable_reg = cfg->enable_reg;
    100	rdesc->enable_mask = SY8824C_BUCK_EN;
    101	rdesc->min_uV = cfg->vsel_min;
    102	rdesc->uV_step = cfg->vsel_step;
    103	rdesc->vsel_reg = cfg->vol_reg;
    104	rdesc->vsel_mask = cfg->vsel_count - 1;
    105	rdesc->owner = THIS_MODULE;
    106
    107	rdev = devm_regulator_register(di->dev, &di->desc, config);
    108	return PTR_ERR_OR_ZERO(rdev);
    109}
    110
    111static const struct regmap_config sy8824_regmap_config = {
    112	.reg_bits = 8,
    113	.val_bits = 8,
    114	.num_reg_defaults_raw = 1,
    115	.cache_type = REGCACHE_FLAT,
    116};
    117
    118static const struct regmap_config sy20276_regmap_config = {
    119	.reg_bits = 8,
    120	.val_bits = 8,
    121	.num_reg_defaults_raw = 2,
    122	.cache_type = REGCACHE_FLAT,
    123};
    124
    125static int sy8824_i2c_probe(struct i2c_client *client)
    126{
    127	struct device *dev = &client->dev;
    128	struct device_node *np = dev->of_node;
    129	struct sy8824_device_info *di;
    130	struct regulator_config config = { };
    131	struct regmap *regmap;
    132	int ret;
    133
    134	di = devm_kzalloc(dev, sizeof(struct sy8824_device_info), GFP_KERNEL);
    135	if (!di)
    136		return -ENOMEM;
    137
    138	di->regulator = of_get_regulator_init_data(dev, np, &di->desc);
    139	if (!di->regulator) {
    140		dev_err(dev, "Platform data not found!\n");
    141		return -EINVAL;
    142	}
    143
    144	di->dev = dev;
    145	di->cfg = of_device_get_match_data(dev);
    146
    147	regmap = devm_regmap_init_i2c(client, di->cfg->config);
    148	if (IS_ERR(regmap)) {
    149		dev_err(dev, "Failed to allocate regmap!\n");
    150		return PTR_ERR(regmap);
    151	}
    152	i2c_set_clientdata(client, di);
    153
    154	config.dev = di->dev;
    155	config.init_data = di->regulator;
    156	config.regmap = regmap;
    157	config.driver_data = di;
    158	config.of_node = np;
    159
    160	ret = sy8824_regulator_register(di, &config);
    161	if (ret < 0)
    162		dev_err(dev, "Failed to register regulator!\n");
    163	return ret;
    164}
    165
    166static const struct sy8824_config sy8824c_cfg = {
    167	.vol_reg = 0x00,
    168	.mode_reg = 0x00,
    169	.enable_reg = 0x00,
    170	.vsel_min = 762500,
    171	.vsel_step = 12500,
    172	.vsel_count = 64,
    173	.config = &sy8824_regmap_config,
    174};
    175
    176static const struct sy8824_config sy8824e_cfg = {
    177	.vol_reg = 0x00,
    178	.mode_reg = 0x00,
    179	.enable_reg = 0x00,
    180	.vsel_min = 700000,
    181	.vsel_step = 12500,
    182	.vsel_count = 64,
    183	.config = &sy8824_regmap_config,
    184};
    185
    186static const struct sy8824_config sy20276_cfg = {
    187	.vol_reg = 0x00,
    188	.mode_reg = 0x01,
    189	.enable_reg = 0x01,
    190	.vsel_min = 600000,
    191	.vsel_step = 10000,
    192	.vsel_count = 128,
    193	.config = &sy20276_regmap_config,
    194};
    195
    196static const struct sy8824_config sy20278_cfg = {
    197	.vol_reg = 0x00,
    198	.mode_reg = 0x01,
    199	.enable_reg = 0x01,
    200	.vsel_min = 762500,
    201	.vsel_step = 12500,
    202	.vsel_count = 64,
    203	.config = &sy20276_regmap_config,
    204};
    205
    206static const struct of_device_id sy8824_dt_ids[] = {
    207	{
    208		.compatible = "silergy,sy8824c",
    209		.data = &sy8824c_cfg
    210	},
    211	{
    212		.compatible = "silergy,sy8824e",
    213		.data = &sy8824e_cfg
    214	},
    215	{
    216		.compatible = "silergy,sy20276",
    217		.data = &sy20276_cfg
    218	},
    219	{
    220		.compatible = "silergy,sy20278",
    221		.data = &sy20278_cfg
    222	},
    223	{ }
    224};
    225MODULE_DEVICE_TABLE(of, sy8824_dt_ids);
    226
    227static const struct i2c_device_id sy8824_id[] = {
    228	{ "sy8824", },
    229	{ },
    230};
    231MODULE_DEVICE_TABLE(i2c, sy8824_id);
    232
    233static struct i2c_driver sy8824_regulator_driver = {
    234	.driver = {
    235		.name = "sy8824-regulator",
    236		.of_match_table = of_match_ptr(sy8824_dt_ids),
    237	},
    238	.probe_new = sy8824_i2c_probe,
    239	.id_table = sy8824_id,
    240};
    241module_i2c_driver(sy8824_regulator_driver);
    242
    243MODULE_AUTHOR("Jisheng Zhang <jszhang@kernel.org>");
    244MODULE_DESCRIPTION("SY8824C/SY8824E regulator driver");
    245MODULE_LICENSE("GPL v2");